使用粒子可以很容易的创建很多细小的物体,例如雨滴雪花等

本章主要内容:

  1 使用ParticleBasicMaterial(基础粒子材质)来创建和设计粒子

  2 使用ParticleSystem来创建一个粒子集合

  3 使用已有的几何体来创建一个粒子系统

  4 让粒子和粒子系统动起来

  5 用纹理给粒子造型

  6 使用ParticleCanvasMaterial在画布上为粒子造型

名称 描述
Sprite粒子

参数是material,生成的sprite可以设置position和scale等属性直接添加到场景中

  var sprite = new THREE.Sprite(material);
sprite.position.set(x * 10, y * 10, 0
);
scene.add(sprite);
SpriteMaterial粒子的基本材质

粒子的基本材质,将在本章第7部分重点讲解其参数

 var material = new THREE.SpriteMaterial();
PointCloud粒子系统

参数几何体和材质

var cloud = new THREE.PointCloud(geom, material);

scene.add(cloud);

PointCloudMaterial粒子系统的材质

设置所有粒子的大小,颜色,顶点颜色,透明度,是否根据相机距离的远近改变大小等属性

var material = new THREE.PointCloudMaterial({size: 4, vertexColors: true, color: 0xffffff});

SpriteCanvasMaterial  专门为CanvasRenderer渲染器创建的材质,该材质的program属性输出的是粒子的纹理

1 粒子-----THREE.Particle

  注意:新的THREE.js已经定义了Sprite对象,即THREE.Sprite,向后兼容THREE.Particle = THREE.Sprite;粒子Particle已经更名为精灵Sprite

  THREE.js源码中有这样一行代码

  THREE.Sprite跟THREE.Mesh一样,都是THREE.Object3D对象的扩展,Sprite的参数是材质material,

  另外CanvasRenderer对象已经不存在了,只有WebGLRenderer(已经找到原因,three.js中只有WebGLRenderer,要引入CanvasRenderer.js才可以)

<!DOCTYPE html>

<html>

<head>
<title>Example 07.01 - Particles - Only works in CanvasRenderer</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
//THREE.CanvasRenderer虽然书中介绍的CanvasRenderer,但是THREE.CanvasRenderer的值是undefined,还没有找到原因
//var canvasRenderer = new THREE.CanvasRenderer();
var canvasRenderer = new THREE.WebGLRenderer();
canvasRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
canvasRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(canvasRenderer.domElement); createSprites();
render(); function createSprites() {
var material = new THREE.SpriteMaterial();
//var material = new THREE.ParticleBasicMaterial(); for (var x = -5; x < 5; x++) {
for (var y = -5; y < 5; y++) {
//var sprite = new THREE.Particle(material);
var sprite = new THREE.Sprite(material);
sprite.position.set(x * 10, y * 10, 0
);
scene.add(sprite);

}
}
} function render() {
stats.update(); requestAnimationFrame(render);
canvasRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
}
}
window.onload = init;
</script>
</body>
</html>
console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' );
//ParticleBasicMaterial已经更名为PointCloudMaterial
console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' );//THREE.ParticleSystemMaterial已经更名为THREE.PointCloudMaterial 
console.warn( 'THREE.ParticleSystem has been renamed to THREE.PointCloud.' ); 
<!DOCTYPE html>

<html>

<head>
<title>Example 07.02 - Particles - Only works in WebGLRenderer</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); createParticles();
render(); function createParticles() { var geom = new THREE.Geometry();
console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' );
console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' ); //创建一个点云材质
//PointCloudMaterial==ParticleBasicMaterial
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));
}
}
//console.warn( 'THREE.ParticleSystem has been renamed to THREE.PointCloud.' );
//PointCloud==ParticleSystem
var cloud = new THREE.PointCloud(geom, material);
scene.add(cloud);

} function render() {
stats.update(); requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
}
}
window.onload = init;
</script>
</body>
</html>

  2 粒子材质PointCloudMaterial和粒子系统PointCloud

PointCloudMaterial的属性 描述
color

PointCloud中所有的粒子的颜色都相同,

除非设置了vertexColors且该几何体的colors属性不为空,才会使用colors颜色,否则都使用该属性

map 在粒子上应用某种材质
size 粒子的大小
sizeAnnutation

false:无论相机的位置,所有的粒子大小一致;

true:离相机近的粒子更大一些,离相机越远越小

vetexColors true:且该几何体的colors属性有值,则该粒子会舍弃第一个属性--color,而应用该几何体的colors属性的颜色
opacity 透明度
transparent 是否透明
blending 渲染粒子时的融合模式
fog 是否受场景的雾化影响
<!DOCTYPE html>

<html>

<head>
<title>Example 07.03 - Particle Basic Material</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); var cloud; var controls = new function () {
this.size = 4;
this.transparent = true;
this.opacity = 0.6;
this.vertexColors = true;
this.color = 0xffffff;
this.sizeAttenuation = true;
this.rotateSystem = true; this.redraw = function () {
if (scene.getObjectByName("particles")) {
scene.remove(scene.getObjectByName("particles"));
}
createParticles(controls.size, controls.transparent, controls.opacity, controls.vertexColors, controls.sizeAttenuation, controls.color);
};
}; var gui = new dat.GUI();
gui.add(controls, 'size', 0, 10).onChange(controls.redraw);
gui.add(controls, 'transparent').onChange(controls.redraw);
gui.add(controls, 'opacity', 0, 1).onChange(controls.redraw);
gui.add(controls, 'vertexColors').onChange(controls.redraw);
gui.addColor(controls, 'color').onChange(controls.redraw);
gui.add(controls, 'sizeAttenuation').onChange(controls.redraw);
gui.add(controls, 'rotateSystem'); controls.redraw();
render(); 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,
/*通常情况下,所有的粒子应用同一种颜色,但是若该值设置为true,
且几何体的colors数组也有值,则会使用colors数组的颜色*/
sizeAttenuation: sizeAttenuation,
/*false:不管粒子距离相机的远近,它们都拥有相同的尺寸
true:粒子的大小取决于它们距离相机的远近
*/ 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); }
//粒子系统PointCloud与网格Mesh相同,只接受几何体和材质两个参数
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);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
}
}
window.onload = init;
</script>
</body>
</html>

  3 使用画布格式化粒子---针对CanvasRenderer渲染器所创建的材质SpriteCanvasMaterial

<!DOCTYPE html>

<html>

<head>
<title>Example 07.04 - Particles - Canvas based texture</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<script type="text/javascript" src="../libs/CanvasRenderer.js"></script>
<script type="text/javascript" src="../libs/Projector.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var canvasRenderer = new THREE.CanvasRenderer();
// var canvasRenderer = new THREE.WebGLRenderer(); canvasRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
canvasRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(canvasRenderer.domElement); var getTexture = function (ctx) { // the body,绘制吃豆人中幽灵的身体
ctx.translate(-81, -84); ctx.fillStyle = "orange";
ctx.beginPath();
ctx.moveTo(83, 116);
ctx.lineTo(83, 102);
ctx.bezierCurveTo(83, 94, 89, 88, 97, 88);
ctx.bezierCurveTo(105, 88, 111, 94, 111, 102);
ctx.lineTo(111, 116);
ctx.lineTo(106.333, 111.333);
ctx.lineTo(101.666, 116);
ctx.lineTo(97, 111.333);
ctx.lineTo(92.333, 116);
ctx.lineTo(87.666, 111.333);
ctx.lineTo(83, 116);
ctx.fill(); // the eyes
//绘制其眼睛
ctx.fillStyle = "white";
ctx.beginPath();
ctx.moveTo(91, 96);
ctx.bezierCurveTo(88, 96, 87, 99, 87, 101);
ctx.bezierCurveTo(87, 103, 88, 106, 91, 106);
ctx.bezierCurveTo(94, 106, 95, 103, 95, 101);
ctx.bezierCurveTo(95, 99, 94, 96, 91, 96);
ctx.moveTo(103, 96);
ctx.bezierCurveTo(100, 96, 99, 99, 99, 101);
ctx.bezierCurveTo(99, 103, 100, 106, 103, 106);
ctx.bezierCurveTo(106, 106, 107, 103, 107, 101);
ctx.bezierCurveTo(107, 99, 106, 96, 103, 96);
ctx.fill(); // the pupils
//绘制其眼珠
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc(101, 102, 2, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(89, 102, 2, 0, Math.PI * 2, true);
ctx.fill(); }; createSprites();
render(); function createSprites() {
var material = new THREE.SpriteCanvasMaterial({
program: getTexture,

color: 0xffffff
}
); material.rotation = Math.PI; var range = 500;
for (var i = 0; i < 1500; i++) {
//Sprite是Object3D的扩展
var sprite = new THREE.Sprite(material);
sprite.position.set(Math.random() * range - range / 2, Math.random() * range - range / 2, Math.random() * range - range / 2);
sprite.scale.set(0.1, 0.1, 0.1);
scene.add(sprite);
}
} var step = 0; function render() { stats.update(); requestAnimationFrame(render);
canvasRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
} }
window.onload = init;
</script>
</body>
</html>

  4 基于WebGLRenderer渲染器使用的粒子材质----PointCloudMaterial

  PointCloudMaterial材质的map属性使用的是THREE.Texture纹理,该纹理是画布canvas作为参数传递给纹理构造函数得到的

   var texture = new THREE.Texture(canvas);

<!DOCTYPE html>

<html>

<head>
<title>Example 07.05 - Particles - Canvas based texture - WebGL</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); var getTexture = function () {
var canvas = document.createElement('canvas');
canvas.width = 32;
canvas.height = 32; var ctx = canvas.getContext('2d');
// the body
ctx.translate(-81, -84); ctx.fillStyle = "orange";
ctx.beginPath();
ctx.moveTo(83, 116);
ctx.lineTo(83, 102);
ctx.bezierCurveTo(83, 94, 89, 88, 97, 88);
ctx.bezierCurveTo(105, 88, 111, 94, 111, 102);
ctx.lineTo(111, 116);
ctx.lineTo(106.333, 111.333);
ctx.lineTo(101.666, 116);
ctx.lineTo(97, 111.333);
ctx.lineTo(92.333, 116);
ctx.lineTo(87.666, 111.333);
ctx.lineTo(83, 116);
ctx.fill(); // the eyes
ctx.fillStyle = "white";
ctx.beginPath();
ctx.moveTo(91, 96);
ctx.bezierCurveTo(88, 96, 87, 99, 87, 101);
ctx.bezierCurveTo(87, 103, 88, 106, 91, 106);
ctx.bezierCurveTo(94, 106, 95, 103, 95, 101);
ctx.bezierCurveTo(95, 99, 94, 96, 91, 96);
ctx.moveTo(103, 96);
ctx.bezierCurveTo(100, 96, 99, 99, 99, 101);
ctx.bezierCurveTo(99, 103, 100, 106, 103, 106);
ctx.bezierCurveTo(106, 106, 107, 103, 107, 101);
ctx.bezierCurveTo(107, 99, 106, 96, 103, 96);
ctx.fill(); // the pupils
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc(101, 102, 2, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(89, 102, 2, 0, Math.PI * 2, true);
ctx.fill(); var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
return
texture;
}; var cloud; var controls = new function () {
this.size = 15;
this.transparent = true;
this.opacity = 0.6;
this.color = 0xffffff;
this.rotateSystem = true;
this.sizeAttenuation = true; this.redraw = function () {
if (scene.getObjectByName("pointcloud")) {
scene.remove(scene.getObjectByName("pointcloud"));
}
createPointCloud(controls.size, controls.transparent, controls.opacity, controls.sizeAttenuation, controls.color);
};
}; var gui = new dat.GUI();
gui.add(controls, 'size', 0, 20).onChange(controls.redraw);
gui.add(controls, 'transparent').onChange(controls.redraw);
gui.add(controls, 'opacity', 0, 1).onChange(controls.redraw);
gui.addColor(controls, 'color').onChange(controls.redraw);
gui.add(controls, 'sizeAttenuation').onChange(controls.redraw); gui.add(controls, 'rotateSystem'); controls.redraw(); render(); function createPointCloud(size, transparent, opacity, sizeAttenuation, color) { var geom = new THREE.Geometry(); var material = new THREE.PointCloudMaterial({
size: size,
transparent: transparent,
opacity: opacity,
map: getTexture(),
sizeAttenuation: sizeAttenuation,
color: color
}); var range = 500;
for (var i = 0; i < 5000; 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);
} cloud = new THREE.PointCloud(geom, material);
cloud.name = 'pointcloud';
cloud.sortParticles = true;
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);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
} }
window.onload = init;
</script>
</body>
</html>

  5 引入外部图片形成纹理,然后利用该纹理格式化粒子

  引入外部图片形成纹理var texture=new THREE.ImageUtils.loadTexture("../img/rain.jpg");

  格式化粒子的材质var material = new THREE.PiontCloudMaterial({map:texture});

  利用该材质生成粒子系统 var cloud = new THREE.PointCloud(geom, material);


<!DOCTYPE html>

<html>

<head>
<title>Example 07.06 - Particles - Rainy scene</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 40;
camera.position.z = 110;
camera.lookAt(new THREE.Vector3(20, 30, 0)); // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); var system1;
var cloud; var controls = new function () {
this.size = 3;
this.transparent = true;
this.opacity = 0.6;
this.color = 0xffffff; this.sizeAttenuation = true; this.redraw = function () {
//有两个粒子系统
scene.remove(scene.getObjectByName("particles1"));
scene.remove(scene.getObjectByName("particles2")); createPointCloud(controls.size, controls.transparent, controls.opacity, controls.sizeAttenuation, controls.color);
};
}; var gui = new dat.GUI();
gui.add(controls, 'size', 0, 20).onChange(controls.redraw);
gui.add(controls, 'transparent').onChange(controls.redraw);
gui.add(controls, 'opacity', 0, 1).onChange(controls.redraw);
gui.addColor(controls, 'color').onChange(controls.redraw);
gui.add(controls, 'sizeAttenuation').onChange(controls.redraw); controls.redraw(); render(); 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.PointCloudMaterial({
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.PointCloud(geom, material);
cloud.sortParticles = true; scene.add(cloud);
} function render() {
stats.update();
var vertices = cloud.geometry.vertices;
vertices.forEach(function (v) {
v.y = v.y - (v.velocityY);
v.x = v.x - (v.velocityX); if (v.y <= 0) v.y = 60;
if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1
;
}); requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
} }
window.onload = init;
</script>
</body>
</html>

  6 通过模拟下雪,学习多个粒子系统并发进行

<!DOCTYPE html>

<html>

<head>
<title>Example 07.07 - Particles - Snowy scene</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 40;
camera.position.z = 110;
camera.lookAt(new THREE.Vector3(20, 30, 0)); // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); var system1;
var system2; var controls = new function () {
this.size = 10;
this.transparent = true;
this.opacity = 0.6;
this.color = 0xffffff; this.sizeAttenuation = true; this.redraw = function () {
var toRemove = [];
scene.children.forEach(function (child) {
if (child instanceof THREE.PointCloud) {
toRemove.push(child);
}
});
toRemove.forEach(function (child) {
scene.remove(child)
});
createPointClouds(controls.size, controls.transparent, controls.opacity, controls.sizeAttenuation, controls.color);
};
}; var gui = new dat.GUI();
gui.add(controls, 'size', 0, 20).onChange(controls.redraw);
gui.add(controls, 'transparent').onChange(controls.redraw);
gui.add(controls, 'opacity', 0, 1).onChange(controls.redraw);
gui.addColor(controls, 'color').onChange(controls.redraw);
gui.add(controls, 'sizeAttenuation').onChange(controls.redraw); controls.redraw(); render(); function createPointCloud(name, texture, size, transparent, opacity, sizeAttenuation, color) {
var geom = new THREE.Geometry(); var color = new THREE.Color(color);
color.setHSL(color.getHSL().h,
color.getHSL().s,
(Math.random()) * color.getHSL().l); var material = new THREE.PointCloudMaterial({
size: size,
transparent: transparent,
opacity: opacity,
map: texture,
blending: THREE.AdditiveBlending,
depthWrite: false,/*该属性决定了这个对象是否影响WebGL的深度缓存,将其设置为false,则各个粒子系统之间互不干涉*/
sizeAttenuation: sizeAttenuation,
color: color
}); var range = 40;
for (var i = 0; i < 50; 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;
particle.velocityZ = (Math.random() - 0.5) / 3;
geom.vertices.push(particle);
} var system = new THREE.PointCloud(geom, material);
system.name = name;
system.sortParticles = true;
return system;
} function createPointClouds(size, transparent, opacity, sizeAttenuation, color) { var texture1 = THREE.ImageUtils.loadTexture("../assets/textures/particles/snowflake1.png");
var texture2 = THREE.ImageUtils.loadTexture("../assets/textures/particles/snowflake2.png");
var texture3 = THREE.ImageUtils.loadTexture("../assets/textures/particles/snowflake3.png");
var texture4 = THREE.ImageUtils.loadTexture("../assets/textures/particles/snowflake5.png"); scene.add(createPointCloud("system1", texture1, size, transparent, opacity, sizeAttenuation, color));
scene.add(createPointCloud("system2", texture2, size, transparent, opacity, sizeAttenuation, color));
scene.add(createPointCloud("system3", texture3, size, transparent, opacity, sizeAttenuation, color));
scene.add(createPointCloud("system4"
, texture4, size, transparent, opacity, sizeAttenuation, color));
} function render() { stats.update(); scene.children.forEach(function (child) {
if (child instanceof THREE.PointCloud) {
var vertices = child.geometry.vertices;
vertices.forEach(function (v) {
v.y = v.y - (v.velocityY);
v.x = v.x - (v.velocityX);
v.z = v.z - (v.velocityZ); if (v.y <= 0) v.y = 60;
if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1;
if (v.z <= -20 || v.z >= 20) v.velocityZ = v.velocityZ * -1;
});
}
}); requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
} }
window.onload = init;
</script>
</body>
</html>

  7 Sprite粒子和SpriteMaterial粒子的基本材质

SpriteMaterial属性 描述
color 粒子的颜色
map 粒子的纹理
sizeAnnutation 相机的远近是否影响粒子的大小
opacity 透明度
transparent 是否透明
blending 融合方式
fog 是否受场景雾化的影响
useScreenCoordinates true:粒子的位置是绝对位置,原点是屏幕的左上角
scaleByViewport

true:粒子的大小取决于视窗的尺寸,粒子的宽=图片的宽/窗口的高

false:粒子的宽=图片的宽/1.0

alignment

当粒子被缩放的时候,指定从哪里开始缩放,

THREE.SpriteAlignment.topLeft左上角保持不动,进行缩放

uvOffset 当载入的图片是一个精灵图片,即很多小图组成一张大图,取大图上具体某个小图时,使用该属性,进行偏移得到具体的小图
uvScale 对根据uvOffset获取到的小图进行缩放
<!DOCTYPE html>

<html>

<head>
<title>Example 07.09 - Sprites in 3D</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight); // position and point the camera to the center of the scene
camera.position.x = 20;
camera.position.y = 0;
camera.position.z = 150; // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); createSprites();
render(); var group; function createSprites() { group = new THREE.Object3D();
var range = 200;
for (var i = 0; i < 400; i++) {
group.add(createSprite(10, false, 0.6, 0xffffff, i % 5, range));
}
scene.add(group);
} function getTexture() {
//只需要载入一张大图,该大图由5个小图组成
var texture = new THREE.ImageUtils.loadTexture("../assets/textures/particles/sprite-sheet.png");
return
texture;
} function createSprite(size, transparent, opacity, color, spriteNumber, range) { var spriteMaterial = new THREE.SpriteMaterial({
opacity: opacity,
color: color,
transparent: transparent,
map: getTexture()
}
); // we have 1 row, with five sprites
spriteMaterial.map.offset = new THREE.Vector2(0.2 * spriteNumber, 0);
spriteMaterial.map.repeat = new THREE.Vector2(1 / 5, 1);
spriteMaterial.depthTest = false
; spriteMaterial.blending = THREE.AdditiveBlending; var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(size, size, size);
sprite.position.set(Math.random() * range - range / 2, Math.random() * range - range / 2, Math.random() * range - range / 2);
sprite.velocityX = 5; return sprite;
} var step = 0; function render() { stats.update();
step += 0.01;
group.rotation.x = step; requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
} }
window.onload = init;
</script>
</body>
</html>

  8 将canvas作为纹理,其中canvas上绘制了一条放射颜色渐变,扭结环几何体的各个顶点和canvas纹理作为参数传递粒子系统的构造函数,生成一个粒子系统

   var gradient = context.createRadialGradient()//canvas上绘制一条放射颜色渐变

  var texture = new THREE.Texture(canvas);//canvas作为参数传递给纹理构造函数,生成一个纹理
 var material = new THREE.PointCloudMaterial({map: generateSprite()});// 利用粒子基本材质的map属性应用该纹理,生成材质

var geom = new THREE.TorusKnotGeometry()//扭结环构造函数,生成一个几何体

   var cloud = new THREE.PointCloud(geom, material);//利用上面得到的几何体和材质得到一个粒子系统

<!DOCTYPE html>

<html>

<head>
<title>Example 07.10 - 3D Torusknot</title>
<script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body> <div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div> <!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript"> // once everything is loaded, we run our Three.js stuff.
function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene(); // create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true; // position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0)); // add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement); // call the render function
var step = 0; var knot; // setup the control gui
var controls = new function () {
// we need the first child, since it's a multimaterial
this.radius = 13;
this.tube = 1.7;
this.radialSegments = 156;
this.tubularSegments = 12;
this.p = 5;
this.q = 4;
this.heightScale = 3.5;
this.asParticles = false;
this.rotate = false; this.redraw = function () {
// remove the old plane
if (knot) scene.remove(knot);
// create a new one
var geom = new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q), controls.heightScale); if (controls.asParticles) {
knot = createPointCloud(geom);
} else {
knot = createMesh(geom);
} // add it to the scene.
scene.add(knot);
}; }; var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'tube', 0, 40).onChange(controls.redraw);
gui.add(controls, 'radialSegments', 0, 400).step(1).onChange(controls.redraw);
gui.add(controls, 'tubularSegments', 1, 20).step(1).onChange(controls.redraw);
gui.add(controls, 'p', 1, 10).step(1).onChange(controls.redraw);
gui.add(controls, 'q', 1, 15).step(1).onChange(controls.redraw);
gui.add(controls, 'heightScale', 0, 5).onChange(controls.redraw);
gui.add(controls, 'asParticles').onChange(controls.redraw);
gui.add(controls, 'rotate').onChange(controls.redraw); controls.redraw(); 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);
} function initStats() { var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms // Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats;
}
}
window.onload = init;
</script>
</body>
</html>

Three.js开发指南---粒子和粒子系统(第七章)的更多相关文章

  1. Node.js开发指南中的例子(mysql版)

    工作原因需要用到nodejs,于是找到了<node.js开发指南>这本书来看看,作者BYVoid 为清华大学计算机系的高材生,年纪竟比我还小一两岁,中华地广物博真是人才辈出,佩服. 言归正 ...

  2. 学习Nodejs:《Node.js开发指南》微博项目express2迁移至express4过程中填的坑

    <Node.js开发指南>项目地址https://github.com/BYVoid/microblog好不容易找到的基础版教程,但书中是基于express2的,而现在用的是express ...

  3. 《Three js开发指南》 PDF

    电子版仅供预览及学习交流使用,下载后请24小时内删除,支持正版,喜欢的请购买正版书籍:<Three js开发指南> pdf下载地址:链接: https://pan.baidu.com/s/ ...

  4. 《node.js开发指南》partial is not defined的解决方案

    由于ejs的升级,<node.js开发指南>中使用的 partial 函数已经摒弃,使用foreach,include代替 原来的代码是: <%- partial('listitem ...

  5. 【vue.js权威指南】读书笔记(第一章)

    最近在读新书<vue.js权威指南>,一边读,一边把笔记整理下来,方便自己以后温故知新,也希望能把自己的读书心得分享给大家. [第1章:遇见vue.js] vue.js是什么? vue.j ...

  6. 《Odoo开发指南》精选分享—第1章-开始使用Odoo开发(1)

    引言 在进入Odoo开发之前,我们需要建立我们的开发环境,并学习它的基本管理任务. 在本章中,我们将学习如何设置工作环境,在这里我们将构建我们的Odoo应用程序.我们将学习如何设置Debian或Ubu ...

  7. VSTO开发指南(VB2013版) 第一章 Office对象模型

    完美地将visual basic和office 办公软件结合起来.来自微软公司VSTO小组的权威专家所编著. 全书共712页,内容极其全面而深入,猛一看,厚地犹如庞然大物.看完离大神就不远了哦< ...

  8. 重温《js权威指南》 第7,8章

    第七章 数组         数组是值的有序集合.js数组是无类型的,数组元素可以是任意类型,同一个数组中不同元素也可能有不同的类型.数组可以动态增长或缩减,创建时无须生命那个一个固定的大小并且数组大 ...

  9. NODE.JS开发指南学习笔记

    1.Node.js是什么 Node.js是一个让JS运行在服务器端的开发平台,它可以作为服务器向用户提供服务.Node.js中的javascript只是Core javascript,或者说是ECMA ...

随机推荐

  1. 自用 docker-compose

    version: '3.1' services: mysql: image: mysql: command: --default-authentication-plugin=mysql_native_ ...

  2. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  3. CentOS 7 下网络管理

    如果最小化安装centos7  后会发现,安装完了进去配置网络发现,ifup ,ipconfig 这些命令不见了,那是因为 7 使用了新的网络管理工具NetworkManager ,具体的命令是nmc ...

  4. centos7上编译安装mysql5.6

    注意,在做实验室统一关闭防火墙做的,在生产环境需要做防火墙规则的,大家要注意,做的时候尽量都是模仿生产环境的,比如服务一般都在/data/soft下面,尽量避免在/usr/local/下面. 安装编译 ...

  5. odoo开发环境搭建(四):python开发工具IDE pycharm配置

    odoo开发环境搭建(四):python开发工具IDE pycharm配置

  6. odoo开发笔记 -- wkhtmltox打印不显示中文 --ubuntu字体安装

    wkhtmltox 是一个开源的将网页内容转换成PDF的软件包,常嵌套在网页页面里边做打印功能. 以微软雅黑字体为例(其他的宋体.黑体等点阵字体都一样的),我们的雅黑字体文件是:Yahei.ttf(放 ...

  7. 课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 3、Python Basics with numpy (optional)

    Python Basics with numpy (optional)Welcome to your first (Optional) programming exercise of the deep ...

  8. StringBuffer、StringBuilder、冒泡与选择排序、二分查找、基本数据类型包装类_DAY13

    1:数组的高级操作(预习) (1)数组:存储同一种数据类型的多个元素的容器. (2)特点:每个元素都有从0开始的编号,方便我们获取.专业名称:索引. (3)数组操作: A:遍历 public stat ...

  9. git status的用法

    git status 用于查看工作区与暂存区的已tracked及untracked的所有文件status. 以下为help结果. git help status NAME git-status - S ...

  10. MySQL笔记(3)---文件

    1.前言 第二章简单记录了一下InnoDB存储引擎的一个基本内容,介绍了保证高效插入的Insert Buffer,change Buffer和确保数据安全的write ahead log以及doubl ...