BlueRoseNote/03-UnrealEngine/VisualEffect/Niagara Module笔记.md

4.7 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
Niagara Module笔记 2024-02-20 11:14:46

前言

不论Niagara Emitter有多少的ModuleModule里有多少的脚本脚本中写了多少东西。我们当然要抓住本质数据其都是更新某个渲染器所需要的必要参数也就是如下图所示的信息。 也就是说只有这些信息是每个渲染器所需要的其会传递给渲染线程并最终提交渲染。任何其他参数仅仅为中间变量。因此我们首先关心的是这个数据是存储在什么地方的。由于一个Emitter可以拥有多个不同的Renderer。因此其本身存储在Emitter级别而不是在Renderer级别。 因此我们最终传递给渲染线程的数据存储在每个Emitter实例FNiagaraEmitterInstance的FNiagaraDataSet身上。不论是GPU粒子还是CPU粒子。

Module 变量类型

  • InputModule输入的变量。
  • Local单帧内存在的变量。
  • Particle粒子级别持久存在的变量。
  • Emitter发射器级别持久存在的变量。
  • Engine引擎提供的只读变量。

粒子属性读取

在Module中在ParticleAttributeReader中可以读取对应的例子属性。引用的数据的方式有两种粒子的ID或者Index索引。但是难就难在最初的我不太了解这两个是啥。大致知道是某种编号。ID的话倒是了解一点但不知道它结果分为Index 和Acquire Tag组合在一起的。

PS.Niagara Debugger工具可以用于检查粒子ID以及对应变量的变化情况。

其他

  1. 发射器固定粒子ID:勾选发射器上RequiresPersistentIDs选项即可固定。
  2. ExportParticleDataToBlueprint可以输出CPU或者GPU变量
    1. 在该节点上添加蓝图变量名。之后在蓝图的BeginPlay()设置这个变量为该蓝图类。之后实现ReceiveParticleData接口。
    2. GPU 粒子数据导出是通过从 GPU 内存回读的方式进行的。这需要不可预知的非固定帧数,通常为 1-2 帧。
    3. GPU 回读性能受限于回读缓冲区的大小。建议使用最小值的 GPU 固定大小分配来捕捉特定帧中可能发生的所有事件。任何超过固定大小的事件都将无法发送。
  3. Window - GeneratedCode可以看到生成出的HLSL代码。

Particle的Module都是c++级别写死的。基本位于Engine\Source\Runtime\Engine\Classes\Particles目录。基类为UParticleModuleNiagara的Module都是蓝图资产引擎自带的都在 Engine\Plugins\FX\Niagara\Content\Modules。基类为UNiagaraScript

  • UNiagaraScriptBase定义了一些编译相关的接口。ModifyCompilationEnvironment()、ShouldCompile()以及获取模拟元数据接口GetSimulationStageMetaData()。
  • UNiagaraScript排除掉Editor相关函数主要的函数为
    • IsXXXScript()系列判断函数。
    • 相关接口PreSave、Serialize、PostLoad基类接口实现。
    • FNiagaraVMExecutableData相关
    • 编译相关。
    • 其他。

Niagara里面的相关类型

DataInterface

基类为UNiagaraDataInterface。

  • UNiagaraDataInterface2DArrayTexture
  • UNiagaraDataInterfaceVirtualTexture

Texture相关Module

  • Textures
    • SampleTexture
    • SamplePseudoVolumeTexture
    • SubUV_TextureSample
    • WorldAlignedTextureSample
  • SubUV
    • SubUVAnimation
    • V2
      • SubUVAnimation

生成的代码

int2			Emitter_SampleTexture_Texture_TextureSize;
int				Emitter_SampleTexture_Texture_MipLevels;
Texture2D		Emitter_SampleTexture_Texture_Texture;
SamplerState	Emitter_SampleTexture_Texture_TextureSampler;
void SampleTexture2D_Emitter_SampleTexture_Texture(in float2 UV, in float MipLevel, out float4 OutValue)
{
	OutValue = Emitter_SampleTexture_Texture_Texture.SampleLevel(Emitter_SampleTexture_Texture_TextureSampler, UV, MipLevel);
}


void SampleTexture_Emitter_Func_(inout FSimulationContext Context)
{
    float4 SampleTexture2D_Emitter_SampleTexture_TextureOutput_Value;
    SampleTexture2D_Emitter_SampleTexture_Texture(Context.MapSpawn.SampleTexture.UV, Constants_Emitter_SampleTexture_MipLevel, SampleTexture2D_Emitter_SampleTexture_TextureOutput_Value);
    Context.MapSpawn.OUTPUT_VAR.SampleTexture.SampledColor = SampleTexture2D_Emitter_SampleTexture_TextureOutput_Value;
    Context.MapSpawn.OUTPUT_VAR.SampleTexture.SamplerUV = Context.MapSpawn.SampleTexture.UV;
    Context.MapSpawn.Particles.SampleTexture.SampledColor = SampleTexture2D_Emitter_SampleTexture_TextureOutput_Value;
    Context.MapSpawn.Particles.SampleTexture.SamplerUV = Context.MapSpawn.SampleTexture.UV;
}