Unreal Engine 5.7
Particle GPUCompute Script
Particle GPUCompute Script 是 Emitter 的 HLSL 代码。
代码结构
1. 全局参数与数据结构
- Engine & Emitter 变量: 如
Engine_DeltaTime,Engine_Time,Emitter_Age等内置系统变量及其前一帧的值(带PREV_前缀)。 - 外部常量缓冲区 (
FNiagaraExternalParameters): 包含了用户自定义或暴露的外部参数,例如User_WindDir(风向)和Emitter_SpawnRate。 - 参数映射结构体 (
FParamMap0及其子结构): 这是 Niagara 的核心数据总线。它将图表中的所有变量(Local, User, Particles, Emitter, Engine 等)打包成结构体。 FSimulationContext: 模拟上下文结构体,它根据当前的SimulationStageIndex宏,包含对应阶段所需的FParamMap0数据。
2. Niagara 模块函数、节点函数定义
模块函数
这部分对应的是能直接添加到列表中的模块,如常见的Initialize Particle、Shape Location、Scratch Pad Module等,此外还有Custom HLSL,它们都以_Func_ 结尾。
节点函数
这部分对应的是模块中的节点,如 RT 的 Load Render Target Value、Grid2D 的
Set Float Value等。
3. 各个函数的实现
- 模块函数:这部分函数会使用宏
#if ((SimulationStageIndex == ?))根据不同的阶段控制代码是否编译。 - 阶段函数:同上
- 节点函数:这部分没用使用宏控制,也就是说理论上是全局可见、可调用的。
- 其他内置工具函数:同上
4. Compute Shader 主函数
包括一些初始化逻辑函数、数据传输与存储函数和一个名为SimulateMainComputeCS的主函数。
一些发现
节点函数 与 跨阶段调用
节点函数没用使用宏控制编译,也就是说理论上是全局可见、可调用的。例如,在阶段1中使用了节点A生成了函数A,那么就可以在阶段2中使用Custom HLSL直接调用函数A。参考
值得注意的是,一些与资源关联的函数,如 Grid2D 的 Set Float Value 节点,其生成的函数是直接硬编码了对应的 Grid2D 对象。此时若跨阶段调用,必须确保该阶段已将该对象传入,并进行了相应的读写操作。例如,在该阶段只对该 Grid2D 对象进行了读操作,那么就无法跨阶段调用 Set Float Value 节点的函数。
为什么呢?一些个人的猜想,未验证:虽然这些函数、资源声明都在同一个 HLSL 源码里,但是在 C++ 端绑定的资源不尽相同(