Niagara as a GPU Compute PlatformNiagara 作为 GPU 计算平台

While Niagara is primarily known as a visual effects system, its true power for engineers is that it exposes a node-graph programmable GPU Compute pipeline without requiring raw HLSL shader code. Think of Niagara as a high-level interface to GPU Compute shaders — you define the GPU work via visual scripting graphs and Data Interfaces, and Niagara compiles them to efficient Compute dispatches.

虽然 Niagara 主要以视觉效果系统著称,但对工程师来说,其真正的强大之处在于它无需原始 HLSL 着色器代码就能暴露节点图可编程 GPU 计算管线。将 Niagara 视为 GPU Compute 着色器的高级接口——通过可视化脚本图和数据接口定义 GPU 工作,Niagara 将其编译为高效的 Compute 分发。

System Architecture系统架构

UNiagaraSystem ← Asset: contains emitters + system parameters └── UNiagaraEmitter ← Template for particles; has scripts + renderers ├── UNiagaraScript ← Compiled GPU/CPU script (= compiled Compute shader) │ ├── Spawn ← Runs once per particle birth │ ├── Update ← Runs every frame for all particles │ └── Simulation Stage (optional) ← Custom iteration order └── NiagaraRenderer ← Meshes, ribbons, sprites drawn from particle data FNiagaraSystemInstance ← Runtime: one instance per NiagaraComponent └── FNiagaraEmitterInstance ← Per-emitter runtime state ├── FNiagaraDataBuffer ← GPU buffer holding particle attribute data └── GPUSimulation tick → dispatched as RDG Compute pass

Simulation Stages — Custom GPU Iteration仿真阶段 — 自定义 GPU 迭代

Simulation Stages (introduced in UE 4.26) are the key feature that makes Niagara useful for non-particle GPU work. They allow you to define additional Compute passes that run as part of the particle system tick, but instead of iterating over particles, they can iterate over:

仿真阶段(UE 4.26 引入)是使 Niagara 用于非粒子 GPU 工作的关键特性。它们允许定义额外的计算通道,作为粒子系统 Tick 的一部分运行,但不是遍历粒子,而是可以遍历:

// UNiagaraSimulationStageBase (NiagaraSimulationStageBase.h)
// Key properties:
UPROPERTY()
FNiagaraVariableBase IterationSource;  // What to iterate over (particles/grid/etc.)

UPROPERTY()
int32 NumIterations = 1;             // How many times to run this stage per tick

UPROPERTY()
bool bSpawnOnly = false;               // Only runs on particle spawn frames

// At runtime: each enabled simulation stage compiles to one Compute dispatch
// Stages execute in order: Spawn → [CustomStage0] → Update → [CustomStage1] → ...

Data Interfaces — Bridging C++ and GPU Scripts数据接口 — 桥接 C++ 和 GPU 脚本

Data Interfaces (DI) are the mechanism Niagara uses to give GPU scripts access to external data: scene textures, physics, skeletal meshes, custom C++ data. Each DI provides:

数据接口(DI)是 Niagara 用来让 GPU 脚本访问外部数据的机制:场景纹理、物理、骨骼网格、自定义 C++ 数据。每个 DI 提供:

Grid2D/3D — GPU Simulation Without ParticlesGrid2D/3D — 无粒子的 GPU 仿真

The Grid2D and Grid3D Data Interfaces are the most powerful for custom simulation. They expose persistent GPU textures (float, float4, float vectors) that retain their values between frames — enabling iterative simulations like Navier-Stokes fluid, SPH, heat diffusion, etc.

Grid2D 和 Grid3D 数据接口是自定义仿真中最强大的。它们暴露持久 GPU 纹理(float、float4、float 向量),在帧之间保留其值——实现像 Navier-Stokes 流体、SPH、热扩散等迭代仿真。

// Example: 2D fluid simulation setup in Niagara
//
// System has NO particles. Instead it uses Simulation Stages over Grid2D:
//
// Stage 0: "Advect" — for each (x,y) in 128×128 grid
//   → Read velocity from Grid2D_Velocity
//   → Sample density at advected position
//   → Write new density to Grid2D_Density
//
// Stage 1: "Divergence" — Compute divergence for pressure solve
//   → Read velocity field
//   → Write divergence to Grid2D_Divergence
//
// Stage 2: "Pressure Jacobi" (repeated N times) — pressure solve
//   → Iterative Jacobi relaxation over Grid2D_Pressure
//
// Stage 3: "Projection" — subtract pressure gradient from velocity
//   → Makes velocity field divergence-free
//
// Result: a real-time 2D fluid simulation entirely on GPU,
// visualized by sampling Grid2D_Density in a material

GPU Particle ReadbackGPU 粒子回读

Reading particle data back from GPU to CPU is expensive (stalls the pipeline). Niagara provides two mechanisms:

从 GPU 读回粒子数据到 CPU 很昂贵(会停滞管线)。Niagara 提供两种机制:

Custom Data Interface — C++ Side自定义数据接口 — C++ 侧

// Creating a custom Data Interface that exposes your compute data to Niagara:
UCLASS()
class UMyCustomNiagaraDI : public UNiagaraDataInterface
{
    GENERATED_BODY()
public:
    // 1. Declare the HLSL functions this DI provides to scripts
    virtual void GetFunctions(TArray<FNiagaraFunctionSignature>& OutFunctions) override;

    // 2. Generate HLSL code that implements those functions
    virtual bool GetFunctionHLSL(const FNiagaraDataInterfaceGPUParamInfo& ParamInfo,
                               const FNiagaraDataInterfaceGeneratedFunction& FunctionInfo,
                               int FunctionInstanceIndex, FString& OutHLSL) override;

    // 3. Bind GPU parameters (buffers, textures) before each Compute dispatch
    virtual bool CopyToInternal(UNiagaraDataInterface* Destination) const override;

    // C++ data:
    UPROPERTY(EditAnywhere)
    float MyParameter = 1.0f;
};

Use Cases: Fluids, Crowds, Physics使用场景:流体、群体、物理

Use Case使用场景Niagara FeatureNiagara 特性Notes说明
2D/3D fluid2D/3D 流体Simulation Stage + Grid2D/3DNavier-Stokes, smoke, fire — fully GPU-residentNavier-Stokes、烟雾、火焰——完全 GPU 驻留
Crowd simulation群体仿真Neighbor Grid 3D + particle updateSPH-based steering, separation forces, 100K+ agents基于 SPH 的转向、分离力,10 万以上角色
GPU physics debrisGPU 物理碎片Particle Simulation StageVerlet integration, collision response with GBuffer depthVerlet 积分,与 GBuffer 深度的碰撞响应
Procedural animation程序化动画Grid3D + skeletal mesh DIGPU-driven clothing, tentacles, vinesGPU 驱动的布料、触手、藤蔓
Custom VFX data自定义特效数据Custom Data InterfaceExpose game state to Niagara scripts (HP bars, team data)向 Niagara 脚本暴露游戏状态(血条、队伍数据)

Source Navigation源码导航

Unreal Engine 5.6 · Engine/Plugins/FX/Niagara/
Source analysis · For learning purposes