
Three.js 实现超酷炫的火焰粒子效果!附完整源码
📸 效果预览

🚀 在线演示
🤔 前言
相信大家对火焰效果都不陌生,在游戏和影视中经常能看到逼真的火焰动画。
该实现基于 Three.js 和 WebGL 着色器,利用 Simplex 噪声算法模拟火焰的湍流效果,通过射线穿射采样实现体积渲染,最终呈现出非常逼真的火焰效果。
💻 核心代码解析
第一步:自定义火焰着色器材质
该实现的核心是一个继承自 THREE.ShaderMaterial 的 FireMaterial 类:
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class FireMaterial extends THREE.ShaderMaterial {
constructor() {
super({
defines: { ITERATIONS: '10', OCTIVES: '3' },
uniforms: {
fireTex: { type: 't', value: null }, // 火焰纹理
time: { type: 'f', value: 0.0 }, // 时间
seed: { type: 'f', value: 0.0 }, // 随机种子
invModelMatrix: { type: 'm4', value: null }, // 逆模型矩阵
scale: { type: 'v3', value: null }, // 缩放
noiseScale: { type: 'v4', value: new THREE.Vector4(1, 2, 1, 0.3) },
magnitude: { type: 'f', value: 2.5 }, // 湍流强度
lacunarity: { type: 'f', value: 3.0 }, // 间隙度
gain: { type: 'f', value: 0.6 } // 增益
},
// ... 着色器代码
})
}
}
第二步:Simplex 噪声算法
片段着色器中实现了完整的 Simplex 3D 噪声函数,这是生成自然火焰效果的关键:
glsl
1
2
3
4
5
6
7
8
9
10
11
// Simplex噪声主函数
float snoise(vec3 v) {
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// 计算网格角点
vec3 i = floor(v + dot(v, C.yyy));
vec3 x0 = v - i + dot(i, C.xxx);
// ... 计算其他角点和梯度
// 返回归一化的噪声值
return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
}
第三步:湍流函数实现
通过多层噪声叠加产生复杂的湍流效果:
glsl
1
2
3
4
5
6
7
8
9
10
11
float turbulence(vec3 p) {
float sum = 0.0;
float freq = 1.0;
float amp = 1.0;
for(int i = 0; i < OCTIVES; i++) {
sum += abs(snoise(p * freq)) * amp;
freq *= lacunarity; // 频率倍增
amp *= gain; // 振幅衰减
}
return sum;
}
第四步:火焰采样与射线穿射
核心渲染逻辑采用射线穿射采样技术:
glsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void main() {
vec3 rayPos = vWorldPos;
vec3 rayDir = normalize(rayPos - cameraPosition);
float rayLen = 0.0288 * length(scale.xyz);
vec4 col = vec4(0.0);
// 多次采样累积颜色
for(int i = 0; i < ITERATIONS; i++) {
rayPos += rayDir * rayLen;
vec3 lp = localize(rayPos);
lp.y += 0.5;
lp.xz *= 2.0;
col += samplerFire(lp, noiseScale);
}
col.a = col.r;
gl_FragColor = col;
}
第五步:Fire 类封装
将火焰逻辑封装为可复用的类:
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Fire extends THREE.Mesh {
constructor(scale = 7) {
const geometry = new THREE.BoxGeometry();
const material = new FireMaterial();
super(geometry, material);
this.scale.set(scale, scale, scale);
this.material.transparent = true;
this.material.depthWrite = false;
this.material.depthTest = false;
}
update(time) {
this.updateMatrixWorld();
this.material.uniforms.invModelMatrix.value.copy(this.matrixWorld).invert();
this.material.uniforms.time.value = time;
}
}
🔍 关键技术点总结
| 技术点 | 作用 | 掌握难度 |
|---|---|---|
| Simplex 噪声 | 生成自然的随机图案 | ⭐⭐⭐ |
| 湍流函数 | 多层噪声叠加产生复杂效果 | ⭐⭐⭐ |
| 射线穿射采样 | 实现体积渲染效果 | ⭐⭐⭐ |
| 自定义着色器材质 | 完全控制渲染流程 | ⭐⭐ |
| 透明混合 | 正确处理火焰透明度 | ⭐⭐ |
🔧 常见问题
问题1:火焰看起来不够自然
原因:噪声参数设置不当,导致火焰形态过于规律
解决思路:调整 noiseScale、magnitude、lacunarity 和 gain 参数,找到合适的组合
问题2:性能较差
原因:ITERATIONS 和 OCTIVES 值过高,导致计算量过大
解决思路:降低迭代次数,或使用纹理噪声替代实时计算
🎁 完整源码
完整源码请参考在线演示页面,打开浏览器开发者工具即可查看。
📌 总结
通过这篇文章,我们学习了:
- 如何使用 Simplex 噪声生成自然的火焰效果
- 如何实现湍流函数模拟火焰的不规则运动
- 如何使用射线穿射采样实现体积渲染
- 如何封装自定义 Three.js 类
💡 扩展思路
如果你想让这个效果更酷炫,可以尝试:
- 添加火焰发光效果(使用 bloom 后期处理)
- 添加烟雾粒子系统配合火焰
- 实现火焰与场景物体的交互(如光照影响)
- 添加声音效果增强沉浸感
🙏 感谢
感谢你看到这里!如果这篇文章对你有帮助,别忘了点个赞👍,收藏一下⭐,转发给更多需要的人!
有什么问题,欢迎在评论区留言讨论~







京公网安备 11010502038735号
💬 评论区
评论功能即将上线,敬请期待!