自制游戏引擎 - 粒子系统
作为游戏引擎渲染逻辑模块内的一个常见功能,粒子频繁的创建/销毁需要做好内存管理,内存池,AoS(Array of Struct) or SoA(Struct of Array)。同时更新的粒子数量如果很大,需要考虑SIMD指令优化,使用多线程,或者是实现GPU粒子。本文会记录新开发的游戏引擎内粒子系统的设计思路。
中间件
- Effekseer : MIT开源
- https://effekseer.github.io/en/
- 与我们的游戏引擎对接
- 图形API
- 复杂度在于跨平台游戏引擎并不是固定的DirectX或者OpenGL,我们需要对接引擎RHI的每一个渲染后端
- 资源转换
- Textures
- Shaders
- effekseer的shader跨平台方案是人工编写DirectX11,通过glslang搭建的工具去生成其他语言
- bgfx的方案则是基于glsl语法改造的新语言,所以我们需要转译effekseer的shader代码到bgfx里
- 上述工作的开发已经由云风的团队开了个头,我们可以考虑使用他们的方案一起维护:https://github.com/cloudwu/efkbgfx
- 图形API
- PopcornFX
- https://www.popcornfx.com/
- 地平线5,暗黑破坏神二,马里奥赛车,帝国时代三
- 按月商业付费
选用中间件的好处是我们无需去开发粒子编辑器以及相应的工具链,也无需游戏项目组招美术特效人员进行特殊培训,只需要完全游戏引擎的对接工作。另外,中间件如果使用较广的话,游戏项目可以导入它们现成的大量资源到游戏引擎中使用,测试。
运行时
- 内存布局
- SoA vs AoS
- SoA可以节省掉多余的内存,如果某个粒子不需要某个属性,而AoS则必须全部持有
- SoA索引数据比较麻烦,需要能从某个粒子ID在不同类型的数据数组中索引到对应的数组,以及数据数组也可能因为粒子更新产生空洞,而AoS则方便查询
- SoA vs AoS
- 运算
- Stateful vs Stateless
- 举个例子,Stateful指的是粒子会存储当前位置在内存中,Stateless则是粒子每次都根据度过的时间计算当前位置
- 某些公式可能无法使用Stateless的方式,但Stateless能节省内存
- Stateful vs Stateless
- CPU粒子
- 优先实现,对于游戏项目来说同屏粒子数量的规模大多数时候用不上GPU粒子的方案
- 多线程
- SIMD优化
- GPU粒子
- 补充实现,用于加速同屏大量粒子的情况
功能对比,参考
可以去跟一些开源引擎的实现方案进行对比
- Unreal Engine
- Niagara Particle Systems
参考链接
- Parallel Techniques in Modeling Particle Systems Using Vulkan* API https://www.intel.com/content/www/us/en/developer/articles/technical/parallel-techniques-in-modeling-particle-systems-using-vulkan-api.html?wapkw=Particle%20System
- CPU Particle Systems : https://alextardif.com/Particles.html
- effekseer 的 shader 转译 https://blog.codingnow.com/2022/03/effekseer_shader.html#more
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.