本文学习资源来自《Three.js开发指南》
一、理解粒子
粒子用来模拟很多细小的物体,如雨滴、雪花、烟等。
1. 使用THREE.Sprite创建简单粒子
关键代码:
function createSprites() {
var material = new THREE.SpriteMaterial();
for (var x = -5; x < 5; x++) {
for (var y = -5; y < 5; y++) {
var sprite = new THREE.Sprite(material);
sprite.position.set(x * 10, y * 10, 0);
scene.add(sprite);
}
}
}
创建10*10的粒子,一个粒子是一个二维平面,总是面向摄像机。
这些粒子没有指定属性,默认渲染成白色方块。
这里使用的THREE.Sprite用来创建粒子。THREE.Sprite是THREE.Object3D对象的扩展,也就是说THREE.Mesh的大部分属性和函数都可用于THREE.Sprite。
当粒子数量非常大时,使用大量THREE.Sprite会遇到性能问题。
2. 使用THREE.PointCloud处理大量粒子
function createParticles() {
var geom = new THREE.Geometry();
var material = new THREE.PointCloudMaterial({size: 4, vertexColors: true, color: 0xffffff});
for (var x = -5; x < 5; x++) {
for (var y = -5; y < 5; y++) {
var particle = new THREE.Vector3(x * 10, y * 10, 0);
geom.vertices.push(particle);
geom.colors.push(new THREE.Color(Math.random() * 0x00ffff));
}
}
var cloud = new THREE.PointCloud(geom, material);
scene.add(cloud);
}
这里每个粒子需要创建一个顶点THREE.Vector3对象,并添加到THREE.Geometry中,使用THREE.Geometry和THREE.PointCloudMaterial一起创建THREE.PointCloud,再把云添加到场景中。
3. 给粒子使用样式
function createParticles(size, transparent, opacity, vertexColors, sizeAttenuation, color) {
var geom = new THREE.Geometry();
var material = new THREE.PointCloudMaterial({
size: size,
transparent: transparent,
opacity: opacity,
vertexColors: vertexColors,
sizeAttenuation: sizeAttenuation,
color: color
});
var range = 500;
for (var i = 0; i < 15000; i++) {
var particle = new THREE.Vector3(Math.random() * range - range / 2, Math.random() * range - range / 2, Math.random() * range - range / 2);
geom.vertices.push(particle);
var color = new THREE.Color(0x00ff00);
color.setHSL(color.getHSL().h, color.getHSL().s, Math.random() * color.getHSL().l);
geom.colors.push(color);
}
cloud = new THREE.PointCloud(geom, material);
cloud.name = "particles";
scene.add(cloud);
}
var step = 0;
function render() {
stats.update();
if (controls.rotateSystem) {
step += 0.01;
cloud.rotation.x = step;
cloud.rotation.z = step;
}
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
书籍官方式示例效果:
3. 使用HTML5画布样式化粒子
Three.js提供了三种使用HTML5画布来样式化粒子的方法。
如果使用的是THREE.CanvasRenderer,可以通过THREE.SpriteCanvasMaterial直接引用HTML5画布。如果用的是THREE.WebGLRenderer,那么需要采取一些额外的步骤才能使用HTML5画布样式化粒子。
在THREE.CanvasRenderer中使用HTML5画布
在WebGLRenderer中使用HTML5画布
4. 使用纹理样式化粒子
function createPointCloud(size, transparent, opacity, sizeAttenuation, color) {
var texture = THREE.ImageUtils.loadTexture("../assets/textures/particles/raindrop-3.png");
var geom = new THREE.Geometry();
var material = new THREE.ParticleBasicMaterial({
size: size,
transparent: transparent,
opacity: opacity,
map: texture,
blending: THREE.AdditiveBlending,
sizeAttenuation: sizeAttenuation,
color: color
});
var range = 40;
for (var i = 0; i < 1500; i++) {
var particle = new THREE.Vector3(
Math.random() * range - range / 2,
Math.random() * range * 1.5,
Math.random() * range - range / 2);
particle.velocityY = 0.1 + Math.random() / 5;
particle.velocityX = (Math.random() - 0.5) / 3;
geom.vertices.push(particle);
}
cloud = new THREE.ParticleSystem(geom, material);
cloud.sortParticles = true;
scene.add(cloud);
}
5. 使用精灵贴图
6. 从高级几何体创建THREE.PointCloud
render();
// from THREE.js examples
function generateSprite() {
var canvas = document.createElement('canvas');
canvas.width = 16;
canvas.height = 16;
var context = canvas.getContext('2d');
var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
gradient.addColorStop(0, 'rgba(255,255,255,1)');
gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
gradient.addColorStop(1, 'rgba(0,0,0,1)');
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
return texture;
}
function createPointCloud(geom) {
var material = new THREE.PointCloudMaterial({
color: 0xffffff,
size: 3,
transparent: true,
blending: THREE.AdditiveBlending,
map: generateSprite() //把粒子设置成发光点
});
var cloud = new THREE.PointCloud(geom, material);
cloud.sortParticles = true;
return cloud;
}
function createMesh(geom) {
// assign two materials
var meshMaterial = new THREE.MeshNormalMaterial({});
meshMaterial.side = THREE.DoubleSide;
// create a multimaterial
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]);
return mesh;
}
function render() {
stats.update();
if (controls.rotate) {
knot.rotation.y = step += 0.01;
}
// render using requestAnimationFrame
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
官方运行示例:
参考:
https://www.cnblogs.com/amy2011/p/6358330.html