本文假设读者已经了解了Three.js是什么样的库,如果不了解,请看
https://github.com/mrdoob/three.js
作为一个优秀的开源项目,应该广而告之。
粒子系统指的是,通过创建很多细小的物体,用来模拟雪花或者雨滴的系统。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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/OrbitAndPanControls.new.js">script>
<script type="text/javascript">
var scene, camera, renderer, spot1, stats;
var clock = new THREE.Clock();//时钟
var cameraControls;
var cloud, controls;
function init() {
stats = new initStats();//初始化检测帧频
scene = new THREE.Scene();//场景
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);//透视相机
camera.position.set(0, 0, 150);//相机位置
scene.add(camera);//add到场景中
spot1 = new THREE.SpotLight(0xffffff, 1);//点光源
spot1.position.set(100, 200, 100);
scene.add(spot1);
renderer = new THREE.WebGLRenderer({antialias: true});//渲染
renderer.setClearColor(0x00000);//设置可以认为是底图的颜色
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;//shadow,阴影,表明能渲染阴影
cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement);//相机控制器
cameraControls.target.set(0, 0, 0);//控制器始终指向原点
document.getElementById('webGL_output').appendChild(renderer.domElement);//将渲染Element添加到Dom中
/*
控制器,用于选择创建粒子的数量大小等
*/
controls = new function () {
this.createNums = 5000;//默认创建5000个粒子
this.size = 4;//默认大小
this.transparent = true;//透明的
this.opacity = 0.6;//不透明
this.vertexColors = true;//坐标点集颜色
this.color = 0xffffff;//控制器本身颜色
this.sizeAttenuation = true;//如果为false 则所有粒子拥有相同的尺寸。无论距离相机多远
this.rotateSystem = true;//是否旋转
this.rotateSpeed = 0.005;//默认旋转速度
this.redraw = function () {
if (scene.getObjectByName('particles')) {
scene.remove(scene.getObjectByName('particles'));
}//存在则清除,然后重制
createParticles(controls.createNums, controls.size, controls.transparent, controls.opacity, controls.vertexColors, controls.sizeAttenuation, controls.color);
}
};
var gui = new dat.GUI();
gui.add(controls, 'createNums', 1, 10000).onChange(controls.redraw);//创建粒子数由1到10000个
gui.add(controls, 'size', 0, 10).onChange(controls.redraw);//大小0——10
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').onChange(controls.redraw);
gui.add(controls, 'rotateSpeed', 0.001, 0.01).onChange(controls.redraw);
controls.redraw();
render();
}
/*
将检测帧频显示在左上方。
*/
function initStats() {
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById('stats_output').appendChild(stats.domElement);
return stats;
}
/*
该函数用于生成粒子
*/
function createParticles(createNums, 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,
blending:true,
color: color
});
var range = 500;
for (var i = 0; i < createNums; 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);//默认,关于颜色的设置只在vertexColors设置为true时使用
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 += controls.rotateSpeed;
cloud.rotation.x = step;
// cloud.rotation.y = step;
cloud.rotation.z = step;
}//旋转起来
requestAnimationFrame(render);//html5的方法,用于绘制一次动画帧
var delta = clock.getDelta();//根据鼠标拉扯,相机旋转
cameraControls.update(delta);
renderer.render(scene, camera);
}
window.onload = init;
script>
head>
<body>
<div id="stats_output">div>
<div id="webGL_output">div>
body>
html>
代码位于https://github.com/Suminzhang/ThreeJSDemo
效果如下,可以自己试试