- 一了解粒子
- 使用THREESprite建立簡單粒子
- 使用THREEPointCloud處理大量粒子
- 給粒子使用樣式
- 使用HTML5畫布樣式化粒子
- 在THREECanvasRenderer中使用HTML5畫布
- 在WebGLRenderer中使用HTML5畫布
- 使用紋理樣式化粒子
- 使用精靈貼圖
- 從進階幾何體建立THREEPointCloud
本文學習資源來自《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.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);
}