Three.js 粒子系统实战:从基础创建到动态物理效果
本文详解如何在 Three.js 中构建粒子系统。从基础几何体创建、纹理映射与混合模式设置,到引入重力加速度实现雨滴下落效果。涵盖粒子初始化、帧循环中的位置更新及性能优化建议,帮助开发者掌握浏览器端高性能 3D 粒子特效的实现方法。
Three.js 粒子系统概述
Three.js 是一款优秀的开源 WebGL 库,它允许 JavaScript 直接调用 GPU 资源,从而在浏览器环境中实现真正的三维渲染。然而,由于该技术仍处于不断演进阶段,相关的学习资源相对稀缺,开发者通常需要依靠示例代码以及 Three.js 的源代码来进行深入学习和实践。
0.简介
很高兴再次与你交流。至此,我们已经开始了 Three.js 的学习之旅。如果你尚未阅读前三篇基础教程,建议先补全相关知识。如果你已经掌握了前文内容,或许会想要尝试制作一些粒子特效。让我们直接切入主题:粒子效果总是令人着迷,而且实际上,创建它们并没有想象中那么困难。
1.创建一个粒子系统
在 Three.js 中,粒子系统被视作一种基础几何体,因为它拥有形状、位置、缩放比例和旋转属性等几何特征。系统将几何对象中的每个顶点视为独立的粒子。这种设计主要基于两点考虑:首先,整个粒子系统的绘制只需调用一次绘制函数,避免了成百上千次的单独调用;其次,这允许我们设定全局参数,统一影响系统内所有粒子的行为。
尽管粒子系统作为一个整体对象存在,我们仍可为每个粒子单独指定颜色。这是因为在绘制过程中,Three.js 通过 attribute 变量 'colour' 将每个顶点的颜色信息传递给着色器。本篇教程暂不涉及此高级用法,若感兴趣,可查阅 GitHub 上 Three.js 的相关示例代码。
粒子系统还有一个关键特性需要注意:Three.js 会在粒子系统首次渲染时将数据缓存,此后无法动态增加或减少粒子数量。如果希望隐藏某个粒子,只能将其颜色的 alpha 值设为 0,而不能真正删除它。因此,在创建粒子系统时,必须预先规划好所有可能需要的粒子数量。
开始创建一个粒子系统,只需要这么多:
基础粒子系统创建
具体实现代码如下:
// 创建粒子几何体
var particleCount = 1800,
particles = new THREE.Geometry(),
pMaterial =
new THREE.ParticleBasicMaterial({
color: 0xFFFFFF,
size: 20
});
// 依次创建单个粒子
for(var p = 0; p < particleCount; p++) {
// 粒子范围在-250到250之间
var pX = Math.random() * 500 - 250,
pY = Math.random() * 500 - 250,
pZ = Math.random() * 500 - 250,
particle = new THREE.Vertex(
new THREE.Vector3(pX, pY, pZ)
);
// 将粒子加入粒子几何体
particles.vertices.push(particle);
}
// 创建粒子系统
var particleSystem =
new THREE.ParticleSystem(
particles,
pMaterial);
// 将粒子系统加入场景
scene.addChild(particleSystem); 如果你运行:
1. 你会发现粒子呈现为方形
2. 粒子保持静止不动
我们将逐一解决这两个问题。
2.风格
在创建粒子基本材质时,我们传入了颜色和尺寸。为了更精细地控制粒子的外观,我们可以传入一张纹理图片。
由于粒子默认以方形绘制,因此应使用方形纹理图片以获得最佳视觉效果。为了增强视觉冲击力,我将使用加法混合模式,但这要求纹理图片的背景为黑色而非透明。目前加法混合与透明材质尚不兼容,但这不影响最终呈现的精美效果。
接下来,我们更新粒子基本材质和粒子系统,加入加法混合下的透明粒子效果。你也可以使用我提供的粒子图片资源。
粒子样式与渲染优化
相关代码如下:
// 创建粒子基本材质
var pMaterial =
new THREE.ParticleBasicMaterial({
color: 0xFFFFFF,
size: 20,
map: THREE.ImageUtils.loadTexture(
"images/particle.png"
),
blending: THREE.AdditiveBlending,
transparent: true
});
// 允许粒子系统对粒子排序,以达到我们想要的效果
particleSystem.sortParticles = true; 效果已明显改善。现在,让我们引入物理机制,让粒子动起来。
3.引入物理
默认情况下,粒子系统在三维空间中是静止的。为了让它们运动起来,我计划让粒子绕 y 轴旋转。由于粒子在三个轴上的范围均为 -250 到 250,绕 y 轴旋转即意味着它们围绕系统中心旋转。
假设你已在类似上一篇着色器教程中的位置设置了帧循环代码,我们只需添加以下逻辑:
粒子运动与物理模拟
具体实现如下:
// 帧循环
function update() {
// 增加一点旋转量
particleSystem.rotation.y += 0.01;
// 绘制粒子系统
renderer.render(scene, camera);
// 设置下一次刷新帧时对update的调用
requestAnimFrame(update);
} 接下来,我们定义单个粒子的运动(注意:之前的旋转是整个粒子系统的运动)。我们将模拟简单的雨滴效果,
这包含一下几步:1. 给每一个粒子赋一个初始为0的速度
2. 在每一帧中,为每一个粒子赋一个随机的重力加速度
3. 在每一帧中,通过加速度更新速度,通过速度更新位置
4. 当一个粒子运动出了视线,重新设置初始位置和速度
听起来步骤繁多,但实际代码量很少。首先,在创建粒子时,我们为每个粒子添加一个水平速度:
具体代码如下:
// 为每个粒子创建一个水平运动速度
particle.velocity = new THREE.Vector3(
0, // x
-Math.random(), // y: 随机数
0); // z 随后,在帧循环中遍历每个粒子,当粒子离开屏幕底部需要重置时,更新其位置和速度。
实现代码如下:
// 帧循环
function update() {
// 增加旋转量
particleSystem.rotation.y += 0.01;
var pCount = particleCount;
while(pCount--) {
// 获取单个粒子
var particle = particles.vertices[pCount];
// 检查是否需要重置
if(particle.position.y < -200) {
particle.position.y = 200;
particle.velocity.y = 0;
}
// 用随机数更新水平速度分量,并根据速度更新位置
particle.velocity.y -= Math.random() * .1;
particle.position.addSelf(
particle.velocity);
}
// 告诉粒子系统我们改变了粒子位置
particleSystem.geometry.__dirtyVertices = true;
// 画
renderer.render(scene, camera);
// 设置下一次调用
requestAnimFrame(update);
} 虽然效果尚显朴素,但这展示了实现粒子运动的基本方法。你可以在此基础上创建更精彩的粒子特效。
这里有一个重要的性能警告:在帧循环中遍历所有粒子是一种较为粗放的处理方式。如果帧循环中执行过多 CPU 密集型操作(不同于 GPU 的并发处理),浏览器会出现卡顿。特别是当使用 requestAnimationFrame 试图每秒刷新 60 次时,务必优化代码,尽量减少帧循环内的计算量。
4.小结
粒子效果极具吸引力,相信你现在已掌握在 Three.js 中添加粒子特效的方法。希望这些内容能助你顺利开发,如同之前的教程一样实用!
同样,这里提供源码下载,欢迎反馈你的使用体验!
JavaScript零基础入门:从环境搭建到运行第一段代码
2026-11-05 15:29:58
HTML链接中javascript:void(0)的作用及现代替代方案
2026-11-05 10:07:47
在线调试 JS 时怎么引入 jQuery 或 Vue 等第三方库
2026-11-05 08:53:56
原生JavaScript实现简易颜色选择器原理与代码
2026-11-03 23:22:19
JS原生表单序列化:FormData与URLSearchParams用法详解
2026-11-03 23:13:21
