每日编程实践: CPU粒子系统 - 火焰与烟雾模拟
CPU粒子系统 - 火焰与烟雾模拟
粒子系统是游戏引擎和实时渲染的核心技术之一。今天从零实现一个完整的 CPU 粒子系统,模拟真实的火焰、烟雾和飞散火星效果。
效果预览
火焰稳定状态(3秒预热后)

时序演变(四帧对比)

从左到右:粒子系统从少到多,逐渐形成稳定火焰形态
项目目标
实现一个功能完整的 CPU 粒子系统,具有:
- 三种粒子类型:火焰、烟雾、火星
- 物理模拟:浮力、重力、湍流、阻尼
- 软粒子渲染:高斯衰减 + 加法/Alpha 混合
- 颜色生命周期:从热核心到消散的完整颜色渐变
系统架构
粒子结构
每个粒子持有以下状态:
1 | struct Particle { |
三类粒子的差异
| 属性 | 火焰 FIRE | 烟雾 SMOKE | 火星 EMBER |
|---|---|---|---|
| 混合模式 | 加法 | Alpha | 加法 |
| 浮力 | 强(正比于 life) | 弱 | 无 |
| 重力 | 无 | 无 | 有 |
| 寿命 | 1.5-3 秒 | 3-5 秒 | 1-3 秒 |
| 大小变化 | 先增后减(sin 曲线) | 持续增大 | 不变 |
核心技术
1. 颜色生命周期渐变
火焰的颜色随生命值(life: 1→0)变化,模拟真实火焰从热核心到消散的过程:
1 | life=1.0 → 蓝白 (1.0, 1.0, 1.0) ← 刚出生(最热) |
1 | Color getFireColor(float life) { |
2. 软粒子渲染(高斯衰减)
避免粒子边缘的硬切割,使用高斯函数产生平滑的边缘衰减:
1 | float t = dist / radius; |
t=0(中心):falloff = 1.0(最亮)t=0.5(半径):falloff ≈ 0.47t=1.0(边缘):falloff ≈ 0.05(几乎透明)
3. 加法混合(火焰叠加)
多个粒子叠加时,亮度相加而不是覆盖,自然形成明亮的火焰核心:
1 | if (additive) { |
这是为什么很多粒子重叠区域会变得极亮(接近白色),就像真实火焰核心一样。
4. 湍流噪声
使用简单的哈希噪声制造自然的湍流效果,让火焰自然摇曳:
1 | // 哈希噪声 [-1, 1] |
关键:每个粒子有独立的 turbSeed,使得同一位置的不同粒子受到不同的湍流影响,避免整体同步摇摆。
5. 粒子大小的生命周期变化
火焰粒子的大小使用 sin 曲线,模拟”先膨胀后缩小”的效果:
1 | // life 从 1→0,sin(π×life) 在 life=0.5 时最大 |
物理模拟细节
力的组合
1 | case ParticleType::FIRE: { |
分层渲染策略
按 SMOKE → FIRE → EMBER 顺序渲染:
- 烟雾:在最底层,Alpha 混合
- 火焰:覆盖在烟雾之上,加法混合发光
- 火星:在最顶层,加法混合,最小但最亮
量化验证结果
1 | 高亮像素(亮度>200): 23,604 个 ✅ |
性能表现
1 | 粒子总数(稳定后): 202 |
仅 0.1 秒完成 3 秒的模拟 + 渲染,CPU 粒子系统在不需要实时性时非常高效。
经验总结
- 加法混合是火焰渲染的核心:不需要复杂的体积渲染,简单的粒子加法叠加就能产生令人信服的发光效果
- 独立的湍流种子很重要:如果所有粒子共享同一湍流相位,火焰会整体同步摆动,看起来很假
- 分层渲染:先渲染低层的 Alpha 混合烟雾,再渲染加法混合的火焰,视觉效果正确
- 高斯衰减软边界:粒子边缘的平滑过渡是”软粒子”外观的关键,没有它粒子看起来像圆饼干
- 噪声的时间维度:
noise(x, y, time)让湍流随时间变化,产生流动感
下一步扩展
- GPU 粒子系统:使用 Compute Shader 将模拟移至 GPU,支持百万级粒子
- 3D 粒子:当前是 2D 投影,可以扩展为真正的 3D 空间粒子
- 碰撞响应:粒子与场景几何体的碰撞和反弹
- 粒子图集:使用精灵图(Sprite Sheet)替代程序化圆形,更丰富的视觉效果
代码仓库
GitHub: daily-coding-practice/2026/03/03-04-Particle-System-Fire-Smoke
完成时间: 2026-03-04 05:32
迭代次数: 1次(一次编译通过)
代码行数: ~600行 C++
编译器: g++ (C++17, -O2)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Chiuhou 技术博客!










