[官方培训]09-UE粒子基础 肖月 Epic 笔记

发布时间 2023-10-02 15:58:10作者: Tcohneyn

UE粒子基础

我们将讨论Niagara的

  • 基础操作和框架
    • Module>Emitter>System
    • Game thread.Render thread
    • Custom Module
    • Sequencer,Debugger
  • Data Sharing
    • Attribute,Data Interface
    • 场景交互,碰撞
    • 粒子间交互 Event,Attribute Reader
  • Niagara Fluid
    • Grid Collections
    • Gas Example

基础操作和框架

  1. 效果预览
  2. 调节参数
  3. 时间轴
  4. 做数据准备的地方,这里分层级的罗列出了该系统参与结算的所有属性,旁边的数字就是它在当前系统中所引用的次数。
  5. 系统总览是我们组装特效的地方

在这里插入图片描述

一个特效在Niagara系统中是由多层Emitter(发射器)堆叠而成的。一个Emitter是控制着行为逻辑相同的一组粒子或一种效果,而Emiter的内部粒子的每一帧具体执行了哪些操作或者它行为逻辑的方式是以Module节点网络的方式来定义的。

核心Niagara组件

在Niagara视觉特效处理系统中,共有四个核心组件:

  • 系统(System)
  • 发射器(Emitter)
  • 模块(Module)
  • 参数(Parameter)

系统(System)

Niagara系统是一种容器,可以放入你要构建该效果的所有内容。在这个系统中,你可以搭建不同的构建块来实现总体效果。

你可以修改一些系统级的行为,这些修改随后将应用到该效果中所有内容。

Niagara系统设置

系统编辑器中的 时间轴(Timeline) 面板将显示系统中包含的发射器,并且可以用于管理这些发射器。

发射器(Emitter)

发射器可用来在Niagara系统中生成粒子。发射器将控制粒子的生成、粒子在生命周期中的遭遇,以及粒子的外观和行为。

发射器位于堆栈中。在该堆栈中有几个组,而在组中可以放置用于实现各个任务的模块。 组如下所示。

发射器组

  1. 发射器生成(Emitter Spawn)

    此组将定义在CPU上首次创建发射器时将会发生什么。使用此组可以定义初始设置和默认值。

  2. 发射器更新(Emitter Update)

    此组将定义CPU上每一帧发生的发射器级模块。如果你希望粒子在每一帧上持续生成,可以使用此组来定义粒子的生成。

  3. 粒子生成(Particle Spawn)

    当粒子生成时,每个粒子将调用一次此组。此时你可能需要定义粒子的初始化细节,例如粒子的生成位置、粒子的颜色、大小和其他特征。

  4. 粒子更新(Particle Update)

    每一帧上的每个粒子都会调用此组。你需要在此处定义在粒子生命周期中将会逐帧更改的所有特征。例如,粒子的颜色会随着时间逐渐变化。或者,粒子受到各种力的影响,例如重力、旋度噪点或点吸引。你甚至可能需要让粒子随着时间改变大小。

  5. 事件处理器(Event Handler)

    在事件处理器组中,你可以在一个或多个用于定义特定数据的发射器中创建"生成"事件。然后,你可以在用于触发某个行为以响应该生成的事件的其他发射器中创建"侦听"事件。

  6. 渲染(Render)

    最后一个组是渲染组。你可以在此处定义粒子的显示,以及为粒子设置一个或多个渲染器。如果要定义3D模型作为粒子的基础以便在这个基础上应用材质,那么你可能需要使用网格体渲染器。或者,你可能需要使用Sprite渲染器并将粒子定义为2D Sprite。我们提供了很多不同的渲染器来供你选择和试用。

模块

模块是Niagara中效果的基础构建块。你可以将模块添加到组中来形成堆栈。模块按照自上而下的顺序处理。

发射器模块

你可以将模块视为能够执行某些数学运算的容器。你需要将数据传送到模块中,然后在模块中对该数据执行一些数学运算,然后在模块结束时将该数据重新写出。

模块是使用高级着色语言(HLSL)进行构建的,但是可以使用节点在图表中以可视方式进行构建。你可以创建函数(包括输入),或者写入到某个数值或参数贴图中。你甚至可以使用图表中的 CustomHLSL 节点,以内联方式编写HLSL代码。

你可以双击Niagara中发射器内部的模块,以查看在模块内部发生的数学运算。你甚至可以复制和创建自己的模块。例如,双击"添加速度(Add Velocity)"模块来查看其内部,则可以看到数据流。

img

脚本首先检索输入 - 速度输入和坐标空间。然后获取粒子的当前速度,以及输入的比例因子。然后,输入速度随之进行调整,变换到正确的坐标空间中,并添加到粒子的当前速度上。该工作完成后,新的粒子速度将会写出,以便于堆栈中其他需要速度信息的任何模块都可以检索该速度。

所有模块都使用这种基础方法构建,但是部分模块的内部数学运算更加复杂。

参数和参数类型

参数 在Niagara模拟中,是一种数据的抽象化。系统会将参数 类型 分配给参数,以定义参数所表示的数据。参数分为四种类型:

  • 图元(Primitive) :这种类型的参数将定义具有各种精度和通道宽度的数值数据。
  • 枚举(Enum) :这种类型的参数将定义一组固定的指定值,并认定其中一个指定值。
  • 结构体(Struct) :这种类型的参数将定义一组合并的图元和枚举类型。
  • 数据接口(Data Interfaces) :这种类型的参数将定义能够从外部数据源提供数据的函数。此类参数可能是来自UE4其他部件的数据,或者是来自外部应用的数据。

参数

点击 加号 图标 (+) 并选择 直接设置新参数或现有参数(Set new or existing parameter directly) ,可以将自定义参数模块添加到发射器。这会将 设置参数(Set Parameter) 模块添加到堆栈。点击 设置参数(Set Parameter) 模块上的 加号 图标 (+) 即可设置现有参数,点击 创建新参数(Create New Parameter) 即可设置新参数。

Impact 案例:效果分层

在这里插入图片描述

生命周期

整体的system到Emitter再到各个partice在运行时都有自己的生命周期。

生命周期除了在时间轴上控制,我们创建System和Emitter时引擎会默认在各个层级下添加State生命周期管理模块。

  • System State

System State控制着整个特效包的存活周期,循环逻辑。

在这里插入图片描述

非活动响应(Inactive Response)

此设置确定当发射器进入非活动状态时会发生什么状况。非活动意味着发射器处于休眠状态,且不再能够生成或管理粒子。选项包括:

  • 完成(Complete):粒子完成任务,然后终止发射器。

  • 终止(Kill):立即终止发射器和粒子。

  • 继续(Continue):发射器停用,但在系统关闭前不会消亡。

循环行为(Loop Behavior)

此选项确定发射器的行为。你可以从下述选项中进行选择:

  • 一次(Once):发射器播放动画一次。
  • 多次(Multiple):发射器以固定次数播放动画。
  • 无限(Infinite):发射器无限次数地播放动画。

在这里插入图片描述

循环时长(Loop Duration)

此参数确定循环持续多长时间。

循环延迟(Loop Delay)

发射器延迟发射的时间。

  • Emitter State

Life Cycle Mode(生命周期模式)

此设置确定是由发射器本身还是由拥有发射器的系统管理生命周期(循环、存在时间和消亡)。设置包括:

  • 系统(System):当你选择此选项后,所属系统将计算所有生命周期功能。在大多数情况下,让系统计算生命周期可提高优化程度。选择此选项将隐藏其他字段。

  • 自身(Self):当你选择此选项后,发射器本身将计算所有生命周期功能。自身模式下设置与 System State相同。

  • Partice State

控制粒子年龄的增长和它的死亡

Stage 执行阶段

Niagara按粒子的每一帧迭代的次数和顺序的不同拆分出了不同的stage执行阶段。

基础的stage有spawn初始化阶段,即指在出生时更新一次,还有update每帧更新阶段。除了这两个默认的,点击Emitter上方的添加stage按钮还有两个可选的。Smiulation Stage和Event 事件。

  • Event的更新频率是由具体的事件类型来控制的,比如发生碰撞或粒子死亡触发的事件。

  • Smiulation Stage是GPU粒子专用的可在每帧的tick(活动)下多次迭代。比如比较复杂的流体结算压力向的求解,TBD粒子的约束求解。每一帧都要多次迭代,才能解出当前状态的一个合理值。

碎块:动态控制

首先粒子的发射大都是在Emitter Update这个stage做的,常见的spawn模块有

  • Spawn Rate 每一帧以一定的频率持续发射
  • Spawn Burst Instaneous 指定具体的发射时刻和发射数量来发射

粒子的初始化阶段(Partice Spawn)

在粒子的初始化阶段(Partice Spawn),首先给了粒子的生命(Lifetime mode)一个随机值,然后还给了粒子的质量(Mass mode)一个随机值,质量的设置是一个很好的逻辑,因为后期在粒子的update阶段,不同的受力模型都可以通过质量反应到每个粒子的变化上去。

另外因为我们碎块是要instance特定的mesh形状上去,所以我们在初始化时又给了它初始的旋转一个随机。

初始速度的添加:add velocity这个模块提供的功能比较全
在这里插入图片描述

  • Linear Velocaty 线性方向速度

Velocity xyz 速度方向

Velocity speed Scale 速度比例 (和Velocity 是倍数的关系)

  • From Point 点发射速度 以一个中心做辐射状的速度发射

Velocity Speed 点速度强度

Constrain TO Radius 是否约束点速度的范围半径

启用之后:

radius Falloff near/far 衰减近/远

radius Falloff exponent 半径衰减指数 (0不进行点速度的约束衰减 数值越大约束点速度越大)

Offset 点速度的偏移值

  • IN Cone 圆锥力 在一个圆锥的范围内做初始速度的分布

Velocity Speed 速度力

distribution Along Cone axis 是否启用 力沿着锥形轴向分布 为0时全圆锥分布 为1时偏向于中心

speed Falloff Form Cone AXis 速度从圆锥轴下降

Random Seed 是否启用力的随机种子

Cone 属性

Cone Axis 圆锥形的朝向 XYZ

Cone angle 圆锥的角度大小

inner Cone angle 内锥角度大小 (为0时是)

Cone Angle Mode 圆锥角度模式(Degrees直接设置度数、Normalized Angle(0-1)归一化角度、Radians弧度)

粒子的更新阶段(Partice Update)

粒子的更新阶段(Partice Update)是粒子主要动态变化发生的阶段,最常用的模块是各种力的添加。

  • Drag(阻力) 碎块的初始速度通过随机的drag衰减下来,可以突出效果的爆破感。
  • Gravity Force(重力)
  • Collision Collision 是粒子和场景碰撞交互的模块,也是这个粒子中计算复杂度最高的一个模块。
  • Solve Force and Velocity 用前面分析出的受力速度更新粒子位置朝向。

碎块:渲染

Niagara中粒子的解算和渲染是完全解耦的,我们可以用一次解算结果驱动多个渲染。这个特性大大优化了粒子系统的性能。

具体演示看视频

碎块Instance类型

为了让每个碎块的形状不重复,我们会选几种不同的mesh形状随机Instance上去。

比如这个案例在DCC中做了四种不同的小碎块模型。

在这里插入图片描述

可以添加一个MeshIndex属性来控制当前粒子渲染的是哪个模型。
在这里插入图片描述

先把四个不同的mesh在Mesh Renderer中添加上。然后又因为在粒子的整个生命周期内,它选用的Instance模型不应该变化,我们就应该在初始化阶段指定这个属性值。把它直接拖到Partice Spawn上来进行指定。
在这里插入图片描述

修改index值可以看到instance的模型产生变化。我们可以添加一个自定义的模块去设定如何逐粒子的随机变化这个index。但更方便的是引擎提供了Dynamic Input这种机制。我们可以在每个模块的参数上,直接添加Input脚本。
在这里插入图片描述

比如我这里添加一个引擎提供的Random Int脚本,让每个粒子在0~3之间随机变化,可以看到每个粒子选的形状都不一样。

在这里插入图片描述
在这里插入图片描述

Material Binding

以上我们可以看出每种Renderer它Instance的渲染实体不同就需要不同的属性进行控制。Niagara通过Material Binding把这些属性传递到渲染系统当中。
在这里插入图片描述

Mesh Renderer由三维的向量(vector)来控制Mesh的缩放,也就是Scale Binding。朝向由Mesh Orientation Binding来控制。

而这里烟雾用到的Sprite Renderer用二维的向量(vector)来控制UV方向的大小,也就是Sprite Size Binding。用Sprite Faceing Binding和Sprite Alignment Binding两个向量来控制Sprite的朝向。

值得一提的是和影视领域不同,游戏实时交互环境下一般负担不起物理模型解算的Volume烟雾。因此常会用案例中这样朝向相机的Sprite切片播放预烘焙的烟雾动态序列来实现这种烟雾效果。

引擎提供了SubUV动画设置模块,并在Renderer里做了UV切割传递给材质。下面看一下这个Smoke的材质。除了UV的设置,粒子还通过Material Binding把Particle Color传了过来,用来控制渲染的颜色还有半透明。除了这些默认的Binding,比如速度,大小。引擎还提供了四个四维的向量(vector)来传递自定义的属性。
在这里插入图片描述

另外比较常见的Renderer还有目前只用于CPU的Ribbon Renderer,它可以根据粒子上的Ribbon id和Ribbon Link Order把粒子连成Spline,常用来做一些光束效果。

感兴趣可以看内容示例的Ribbon相关的案例。

除了这些基础的Render,我们还可以把灯光或者其它类型的Component甚至破碎系统的Geometry Collection Instance到粒子上。让Niagara可以控制场景中更多复杂的元素。
在这里插入图片描述

以上过了基础模块和Render的参数调整,下面再来看看如何在System层级上做参数控制,让各层Emitter元素联动起来,并可以放在场景中,从粒子系统外部做用户的参数控制。下面用第一人称关卡做了个简单的枪械Gameplay

案例具体看视频

Custom Module:Rolling Debris(自定义模块:丢碎块)

在影视特效项目中,比较近的景别下细节上通常会要求小碎块可以因为碰撞或运动轨迹的变化产生翻滚的效果,这里就以这个需求展开如何在Niagara中搭建自定义的Custom Module Script。
在这里插入图片描述

通过上面的效果来分析原理,在空中飞行状态下,我们可以由当前速度和前一帧速度叉乘得到,即图示蓝色的轴向
在这里插入图片描述

当两帧速度方向接近平行,这里的处理是这种情况下让碎块停止翻转,这样做的考量是速度方向变化不大,说明运动轨迹变化的曲率也很小。从观察体验来说,这种情况下发生翻滚的概率也挺小就直接做滑行处理了。

当碎块与场景发生碰撞,在接触面上发生翻滚时,另一个轴向的判断就容易多了。如图所示,直接用速度方向和碰撞面的法向来做叉乘得到这个旋转的轴向。
在这里插入图片描述

原理比较清晰了,下面演示具体看视频

Sequencer Control

比起Gameplay的控制在动画领域中,我们更常用到的是在镜头里进行调整,这里介绍如何在Sequencer控制粒子系统。

先把Niagara system actor添加进来还有Component track。Life Cycle track可以把Niagara的生命周期铺到Sequencer的时间轴上,控制它出现的时间段。但这里不能默认前后拖动看效果。
在这里插入图片描述

我们可以在Properties中把Age Update Mode改成Desired Age,这样就可以前后拖动看效果了。
在这里插入图片描述

另外所有User Parameters也暴露在Sequencer中,这里我们设置的ImpactDirection可以添加到track里给它k帧。可以看到变化。
在这里插入图片描述

Niagara Debugger

另外,调试粒子效果很重要的一步就是需要频繁的检查属性Debug。引擎提供了很全面的性能查看,信息展示的工具(Niagara Debugger)。我们可以在这里设置粒子的播放速度。慢速看动态的细节。除了System上的一些信息,还可以添加任意的粒子属性,检查它们的具体值。比如添加了前面Custom Module调整的MeshOrientation属性。可以看到会显示到每一个粒子的位置上。
在这里插入图片描述

小结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

具体描述看视频

Data Sharing

Expose Everything

  • 分层级的属性管理 Namespace 颜色不同的前缀为命名空间

在这里插入图片描述

  • 访问系统外部数据 Data Interface
    在这里插入图片描述

Namespace

  • System

    Age,loop,duration

  • Emitter

    Age,LocalSpace,Determinism

  • Particle

    Age,life,mass,position,velocity,orient,size...

需要注意的是这些按层级划分的命名空间,还可以通过Namespace Modifier加入一个子空间。Previous 这个Modifier可以获取粒子前一帧的值。也可以通过Initial 这个Modifier获取初始spawn阶段的粒子属性。
在这里插入图片描述

  • Engine

    只读

    delta,owner.velocity,owner.LODDistance

  • Transient

    临时的,不需要前后帧accumualte的数据

    force,drag...

  • Mouble

    Input,Output,Local

Data Interface

场景:

Static Mesh:Distance Field,Triangle

Skeletal Mesh:骨骼,Triangle

Landscape
在这里插入图片描述

+Vector Field,Spline等控制器

+Actor Component 访问到场景中任意actor的Transform信息。

这些都极大的方便我们的粒子系统和场景中不同的actor做联动,做交互。

在这里插入图片描述

渲染:

除了3D的场景,我们也可以获取到渲染管线的信息。

GBuffer,RenderTarget

通过采样GBuffer在粒子系统中添加一些后期效果,采样RenderTarget做一些Gameplay的交互等等。
在这里插入图片描述

外部资产:

Houdini Cache Data,Texture

我们可以把Houdini的离线解算效果保存成二进制的json文件,然后通过Houdini Niagara插件提供的接口在引擎粒子系统中重现这个Houdini的解算结果。
在这里插入图片描述

物理引擎:

Chaos Sim Data

也有接口,它可以响应Chaos Destruction中cluster约束的断裂或者是Impact碰撞事件。

在这里插入图片描述

学习地址

Particle Interaction:Attribute Reader

  • Data Interface CPU和GPU粒子都可以用,我们可以通过它索引自己或其它Emitter的所有粒子属性。
  • Particle.ID与Particle.UniqueID 两种索引方式

Particle.UniqueID它可以保证每一个粒子都有一个唯一值,但是在帧之间这个值可能由于新粒子的出生,旧粒子的死亡而发生变化。

而Particle.ID是可以保证唯一且在帧之间不变的粒子索引。它是一个专用的数据结构由两个int值构成,使用这个值需要在Emitter Properties勾上Requires Persistent IDs这个选项。

在这里插入图片描述
在这里插入图片描述

内容示例具体演示看视频

Particle Interaction:Event

  • CPU Only Stage,传递DataSet
  • Generator:
    • Collision Death Location
    • Event Send Rate
  • Event Handler:
    • 改变当前粒子的行为
    • spawn新粒子
      在这里插入图片描述

具体参考内容示例的Event实现的案例

Blueprint Interaction:Export

传递粒子属性到蓝图(去影响其它模块的功能)

性能代价比较高 ,但在离线领域会有应用

  • Data Interface:Export Particle Data
  • 蓝图Interface:Niagara Particle Callback Handler

具体看视频内容示例演示

Niagara:General VFX Platform

  • 行为逻辑可编程可自定义
  • GPU Computer Shader的节点编辑器
  • 可在粒子以外的其他Data Interface上迭代

Niagara Fluid

  • GPU加速的实时流体解算插件
  • Data Interface:Grid Collections
  • 流体解算:Custom Modules
  • Volume渲染:Ray Marching材质

学习地址

内容示例中有展示关卡

Gas调参

性能相关

  • Grid:精度,fit运动轨迹
  • Pressure Solve Iterations
    在这里插入图片描述

效果相关

  • Vorticity Confinement
    在这里插入图片描述

  • Turbulence
    在这里插入图片描述

学习地址

地址