本文基于欧拉视角下的流体模拟方案,结合Unreal Engine 5.4.4的Niagara系统,实现了一套完整的3D风场/力场解决方案。文章将NS方程拆解为工程可实现的模块,详细阐述了从基础架构搭建到各项物理模拟的计算过程。
NS方程的工程化拆解
在欧拉视角下,流体模拟围绕角色Actor周围的Space进行计算。NS方程在工程实践中可拆分为以下四项:
- 外力项:对速度场施加外部输入(如角色运动产生的速度)。
- 扩散项:处理Cell单元间的流体交换与粘性扩散。
- 对流项:采用半拉格朗日法回溯,使流体沿自身方向运动。
- 投射项:通过压力场修正速度,确保流体的不可压缩性,传递粒子间的挤压效应。
Niagara实现流程与关键技术
1. 基础架构搭建
使用UE 5.4.4引擎,创建Empty粒子模板并切换为GPU模拟。关键配置如下:
- 用户参数:添加Texture Render Target (RT) 和 int32分辨率参数。
- Grid3D设置:利用Grid3D作为3D网格集存储数据。在Emitter Attributes中创建RT并与User Parameter关联。
- RT格式:为确保精度及支持RGB数据,设置为RTF RGBA16F。
- 分辨率同步:由于UE5版本限制,需编写暂存模块(Transient Module)动态调整RT分辨率,使其与Grid3D的Cell分布保持一致。
2. Grid3D与RT的数据映射
建立专门的Stage将Grid数据写入RT。Grid3D的每一层对应RT的一个切片,坐标换算逻辑为 (x, z * resolution + y)。通过此映射关系,完成3D网格数据到2D纹理的转换。
3. 外力项:角色速度输入
核心目标是将角色Mesh或Physics Asset的速度写入速度场。
- 坐标转换:将Grid Cell索引转换为世界坐标
cellWorldPosition = (float3(x,y,z) / res) * Size + WorldPosition。 - 中心对齐:为使角色位于模拟框中心,需调整模拟框的世界坐标。若模拟框尺寸为S,角色位于原点,则模拟框原点应偏移
-S/2。 - 数据传递:通过Niagara Object获取角色Actor引用,读取其Physics Asset速度,并排除位于Mesh内部的Cell。
4. 扩散项实现
扩散项模拟浓度/速度向周围低值区域的渗透。采用离散拉普拉斯算子,3D环境下需考虑6个邻居方向。
HLSL核心逻辑:
// 计算系数 a = dt * diff * N * N * N
// 获取自身及上下左右前后6个邻居的速度值
// diffusion = (V_self + a * (Sum_Neighbors)) / (1 + 6 * a);
5. 对流项:半拉格朗日法
采用半拉格朗日法进行逆向追踪:计算当前格点在上一时刻的位置,并通过三线性插值获取该位置的速度值。
步骤:
- 逆向计算位置:
x = i - dt * U(同理计算y, z)。 - 边界钳制:
clamp(x, 0.5, N + 0.5)。 - 三线性插值:根据逆向位置周围8个顶点的值进行加权平均。
6. 投影项:散度、压力与速度修正
为保证流体不可压缩性,需通过求解泊松方程计算压力场,并据此修正速度场。
- 计算散度:基于相邻Cell的速度差计算散度场
Div。 - 计算压力:迭代求解压力场,公式近似为邻居压力平均值加上散度项。
- 修正速度:利用压力梯度修正速度,
U -= (PU0 - PU1) / (h * factor),消除发散分量。
7. 扩展功能
模拟场跟随角色
通过蓝图传递角色的WorldPosition和Velocity至Niagara,并在HLSL中对Grid数据进行相应的位移插值,实现风场随角色移动。
粒子采样流体RT
为实现落叶等交互效果,粒子需采样流体RT。方法是将粒子世界坐标转换到模拟空间,归一化后构建UV坐标,对RT进行采样以获取当前位置的风速和方向。
总结
通过上述步骤,可在Niagara中构建出一套基于GPU加速的3D流体模拟系统。关键在于正确建立Grid3D与RT的映射关系,以及准确实现NS方程的各项离散化计算。建议参考官方2D流体案例以加深理解。
作者:在野
原文来源:知乎

