找回密码
 立即注册
查看: 482|回复: 0

[简易教程] 如何制作逼真篝火特效 | Unity Visual Effect Graph系列教程 ...

[复制链接]
发表于 2022-2-24 09:30 | 显示全部楼层 |阅读模式
摘要

注意:本教程使用HDRP高清渲染管线

本教程基于Unity高级技术美术师 Thomas Iché 的视频教程撰写,Thomas的两个原始视频请查看Youtube网址:



  • https://www.youtube.com/watch?v=sNJ_SU20-o0
  • https://www.youtube.com/watch?v=xPW0l83mlOs

本文通过对一个写实类篝火效果制作的讲解,带大家一步步完成四个Visual Effect Graph粒子系统,并将它们组合在一起完成最终的篝火效果。

我们将一起学习以下知识点:

  • Context(上下文)和不同上下文的作用:Spawn,Initialize Particle,Update Particle和Out Particle上下文
  • Block(功能块),并学习了一些常用Block的用法,比如Turbulence,Force,Flipbook Player,Set Velocity Random等
  • 如何使用本地变量和全局变量
  • 如何通过Rendering Debugger窗口检查性能问题,并解决Overdraw性能问题

此教程为Visual Effect Graph系列教程的第一篇,之后我会陆续推出更多Visual Effect Graph特效相关的案例教程。

Unity HDRP VFX Graph篝效果
https://www.zhihu.com/video/1477574681499160576
1.1 创建Visual Effect Graph资源(Asset):
1.1.1 如图-1所示,在Project窗口创建一个Visual Effect Graph资源:右键打开菜单中选择Create > Visual Effects > Visual Effect Graph生成资源。并将它拖动到场景中。



图- 1

1.1.2 双击打开新建的特效资源文件。Visual Effect Graph已经在当前的特效资源文件中预设了一个默认的粒子系统,我们先看一下这个默认粒子系统是由哪些部分组成的。
1.1.2.1 默认的模板粒子系统:
当我们新建一个Visual Effect Graph资源时,Unity会使用一个模板为我们创建一个默认的粒子系统。这里面会包含如图-2所示的节点图。
整个粒子系统的执行方向是从上往下的,也就是从Spawn(生成)上下文(Context)创造粒子开始执行,到Initialize Particle(初始化粒子)上下文,然后是Update Particle(更新粒子)上下文,最后到执行Output Particle Quad(输出四边形粒子用于显示最终粒子效果)上下文。我们会在后面了解到各个上下文的作用。
另一个需要说明的是:在一个Visual Effect Graph中至少会存在一个粒子系统,但是大多数情况下会存在多个粒子系统。假设我们要制作一个篝火的效果,它可能会存在:烟雾粒子系统,火焰粒子系统,用于表现火焰中随机出现的小火星粒子系统,还有比如因为火焰的高温导致空气扭曲的粒子系统等。



图- 2

我们可以把虚线框中的System字样通过鼠标左键双击修改文字,比如改成如图-3所示的“My System”。这可以在多个粒子系统并存的情况下起到区分的作用。



图- 3

1.1.2.2 Spawn上下文(Context):



图- 4

我们使用上下文(Context)来定义整个特效中某一个阶段的计算阶段,比如生成新的粒子,更新现有粒子的状态等。
因为一个Visual Effect Graph就是由一个或者多个粒子系统组成的系统,所以它的最基本功能就是喷射粒子。不管是一次性喷出来,还是随着时间流逝按照一定速度喷射出来,本质上我们是要通过控制这些粒子来实现各种效果。因此,作为一个特效的起始点,Spawn这个上下文(如图-4所示)的工作就是定义粒子喷射的形式(一次性喷还是在几个循环里面喷完),以及喷射的速度,每次喷射前需要的延迟(Delay)等属性,然后按照这些设置来生成粒子。
在Spawn上下文的最后,Visual Effect Graph通过Spawn Event连接到下一个上下文Initialize Particle。
1.1.2.3 Initialize Particle(初始化粒子)上下文:
初始化粒子上下文的作用是初始化在Spawn上下文中生成的粒子上的各项属性。它的的基本作用(如图所示)如下:

  • 通过Capacity(容量)控制粒子的总数。如图所示,这里的数值32是此粒子系统能够生成的最大粒子总数。即使你在Spawn中设置了更高的数值,最终的粒子总数以这里为准。
  • Bounds(边界框):在这里可以控制当前粒子以什么位置为中心(Center),以及边界框的大小(Size)。
请注意:图中的Capacity和Bounds参数是无法删除的,但是下面的Set Velocity Random(设置随机速度)和Set Lifetime Random(设置随机生命值)代码块(我们称为Block),是可以被删除的。
我们可以为上下文(Context)添加各种适用的代码块(Block),像堆积木一样堆起来。包含这些代码块的上下文会按照从上到下的顺序执行这些代码块,比如图-5中会先执行Set Velocity Random代码块为每个粒子指定一个随机的速度值,然后再通过Set Lifetime Random为每个粒子指定一个随机的生命值。



图- 5

1.1.2.4 Update Particle(更新粒子)上下文:
如图-6所示,在此上下文中我们加入了一个名为Turbulence(湍流)的代码块,它可以生成一个噪声场,用于控制每个粒子的运动速度。通过这个湍流代码块,我们可以为一堆粒子添加看似自然的湍流运动。
在更新粒子上下文中,Visual Effect Graph每帧都会在所有粒子上应用包含在当前上下文中的所有代码块,并按照从上到下的顺序应用这些代码块。除了动态改变每个粒子的位置信息,我们也可以改变颜色,生命值等属性。



图- 6

1.1.2.5 Output Particle Quad上下文:
粒子系统最后一个上下文的作用是进行粒子的输出显示。如果我们把Update Particle上下文和Output Particle Quad上下文之间的链接断开,可以看到场景中的粒子将不再被渲染。
与初始化上下文一样,负责输出显示的上下文也有一部分固定的属性设置,比如Color Mapping,Uv Mode等。我们也可以添加如图-7所示的Orient: Face Camera Plane代码块,Set Size over Life代码块和Set Color over Life代码块。我们将会在后面的实例讲解中用到这些代码块。



图- 7

除了在默认的模板粒子系统中使用的Output Particle Quad上下文,还有很多其他与Output有关的上下文,它们可用于显示不同类型的粒子效果,比如我们可以使用Output Particle Lit Sphere把每个粒子渲染成一个3D圆球(如图-8所示),而且这些圆球粒子会受到场景中光照的影响。



图- 8

1.2 创造烟雾粒子系统:
以下我们来了解如何制作烟雾粒子效果。
1.2.1 首先我们要在Output上下文中选择一个纹理作为Main Texture,这里选择SimpleSmoke纹理。SimpleSmoke纹理包含在Visual Effect Graph包提供的示例纹理库中。具体设置如图-9所示。



图- 9

不过如图-10所示,目前看上去并不像烟雾,而是一团团棉絮样的东西。



图- 10

1.2.2 因为烟雾上升的路径是较为垂直向上的,所以要改变目前随机飘散的棉絮团状的烟雾效果,我们要在初始化(Initialize)上下文中改变烟雾的初始移动速度。也就是要在初始化上下文的Set Velocity Random(设置粒子随机速度)块中进行设置。将粒子随即速度值如图-11所示进行设置:



图- 11

因为我们选择的是Per-component(每个组件),所以X,Y,Z三个轴向都会通过A和B的值来单独计算一个随机数值。比如X轴的速度会用-0.1和0.1来取一个随机值,Y轴的速度会用0.8和1来取一个随机值,Z轴的速度则会用-0.1和0.2来取一个随机值。这三个轴的随机值一起控制初始化阶段每个粒子的初始移动速度。
值得注意的是:Set Velocity Random这个功能块其实是Set Attribute(设置属性)中的一个属性控制块(用于控制粒子移动速度)。如果你在Visual Effect Graph里面搜索,其实找不到Set Velocity Random这个块,你只能在文档的Node Library > Block > Attribute层级下找到Set这个词条(如图-12所示)。



图- 12

如果你选中Set Velocity Random这个块,可以在Inspector窗口中调整更多的参数,如图-13所示:



图- 13

展开图-14中的Attribute(属性)选择框,可以看到除了velocity外,我们还可以选择一长串其他的参数,比如color(颜色),alpha(透明值),position(位置)等。如果你在这里为Attribute选择position,那么Visual Effect Graph中原先显示为Set Velocity Random块就会改名为Set Position Random,块中的参数也会发生相应改变。



图- 14

1.2.3 目前烟雾的上升距离有限,这时因为目前每个粒子的生命值(Lifetime)在1到3秒之间,到达生命值以后粒子就消失了。
我们可以通过增大生命值来达到让粒子活的更长久的目的,从而让烟雾升的更高。如图-15所示,将Set Lifetime Random(设置随机生命值)的参数A设置为6,B设置为8,也就是初始化时每个粒子的生命值为6秒到8秒之间的一个数值,最少活6秒,最大活8秒。
点击键盘上的F5键可以刷新特效的运行,让它重新开始运行。



图- 15

不过增大了生命值之后会出现如图-16所示的地面和上升粒子之间的空白区域。这时因为当粒子的生命值增大以后,粒子的总数很快达到了在Capacity参数中设置的上限,在老的粒子还未死亡的前提是无法生成新粒子的,所以就导致了粒子和地面之间空白区域的出现。



图- 16

1.2.4 为了解决上述隔空的问题,我们要降低粒子的生成速度和Initialize Particle初始化粒子上下文中的Capacity(容量)数值。
我们把Constant Spawn Rate中的Rate数值改为4,如图-17所示:



图- 17

把Capacity数值改为32,如图-18所示:



图- 18

修改完成以后我们可以看到烟雾和地面之间的空白区域问题解决了,因为现在的设置会每秒产生4个粒子,在粒子的最大生命值(8秒)结束之前,老的一波粒子会消失,新的一波粒子得以生成。
1.2.5 不过目前烟雾粒子形状较小,所以我们接下去要调整烟雾粒子的大小,让这些粒子看上去像真正的烟雾。
我们可以在Output Particle Quad(输出方形粒子)上下文中调整烟雾粒子大小,具体步骤如图-19所示:



图- 19

1) 在Set Size over Life(随生命值设置粒子大小)块中,打开Size相关的曲线图。
2) 在曲线图底部选择第二个曲线,这一曲线会以线性方式增加/减少数值。
3) 拖动设置绿色曲线最左边点的数值为0.5。
4) 拖动设置绿色曲线最右边点的数值为1.5。
曲线图中我们可以看到绿色曲线的四周有四条蓝色直线,你可以通过鼠标左键框选绿线得到这四条蓝色直线。然后你就可以通过选中并移动蓝色直线来调整绿色曲线起始点和结束点的相关数值。
调整粒子大小以后的效果如图-20所示:



图- 20

1.2.6 上述步骤让我们的烟雾看上去更真实一些了,但是目前的问题也很明显:这个烟雾并不真实。原因是我们给每一个烟雾粒子使用的都是同一张烟雾纹理,所以一团团的烟雾看上去很重复。为了解决这个重复的问题,我们接下去要用到Flipbook(动画翻页书)功能。
首先我们要把现在用的SimpleSmoke纹理替换成一个纹理图集WispySmoke03b_8x8(如图-21所示)。这个纹理图集包含了一系列烟雾效果关键帧,Flipbook功能可以拿这个纹理图集逐帧播放动画,让每一个烟雾粒子动起来。



图- 21

不过如图-22所示,现在的效果显然不是我们想要的:



图- 22

我们要设置正确的UV模式,以及根据纹理图集的行和列数量来设置Flipbook的相关参数。请按照如图-23所示设置相关参数。

  • Uv Mode(UV模式)设置成Flipbook Blend(动画翻页书混合模式)。
  • Flip Book Size(动画翻页书大小)中按照纹理图集的行和列8x8来设置x和y数值。
这时可以看到之前的显示问题消失了。



图- 23

为了让纹理图集中的关键帧播放起来,我们要在Update Particle上下文中添加Flipbook功能块,如图-24所示。然后将Mode(模式)从默认的Constant(不变的)改为Curve Over Life(根据生命值控制播放帧率曲线)。



图- 24

在默认的Constant模式下,动画翻页书的Frame Rate(播放帧率)始终为25帧每秒,因此不管烟雾在哪个生命阶段,烟雾粒子动画的播放速度是一样的,这会让烟雾动画看上去自始自终都是一样的。
真实的烟雾在生命阶段的后面部分,因为烟雾扩散会让烟雾变化的越来越慢(也就是动画播放书的播放速度越来越慢)。当我们选择Curve Over Life这种模式时,烟雾粒子在各个生命阶段的动画播放速度就可以用曲线来控制。
如图-25所示,这条曲线的最左边代表烟雾粒子生成的时候,它的动画播放帧率为25帧每秒,最右边为烟雾粒子死亡时,我们设置它的动画播放帧率为2帧每秒。



图- 25

1.2.7 现在的烟雾效果比之前有很大的进步,不过在烟雾粒子上还是可以看出一些重复。要解决重复的问题,我们可以对粒子做一些改变。
首先我们在生成粒子的时候为每个粒子设置一个随机角度,具体设置如图-26所示:



图- 26

在Initialize Particle上下文中点击键盘上的空格键,然后搜索到Set Angle(设置角度)块并将它添加到Initialize Particle上下文中。
选中Set Angle功能块,在Inspector界面的Random(随机)参数中选择Uniform模式。可以看到Set Angle功能块中原本只有一个角度参数变成了两个参数,分别标为A和B。此处的A和B分别代表最小角度数值和最大角度数值,用于设定最终随机角度值的取值范围。
接着在Set Angle功能块中为Channels参数选择Z,并在B参数中输入360。这样粒子生成的时候,每个粒子的旋转Z轴数值会被赋值一个0到360度的随机数值。
1.2.8 如图-27所示,因为我们在Flipbook中使用的纹理图集包含预先计算好的光照信息,并且现在的输出上下文为Output Particle Quad,这一输出上下文是不支持粒子上的光照计算的,所以在当前场景中烟雾效果无法匹配场景中的光照信息。



图- 27

要让场景中的灯光正确照亮烟雾粒子,我们首先要把输出上下文改为支持光照计算的Output Particle HDRP Lit Quad,如图-28所示鼠标右键点击当前的输出上下文,然后选择Convert Output(转变输出)。接着如图- 所示,选择Output Particle HDRP Lit Quad作为输出上下文。



图- 28

然后要在Output Particle HDRP Lit Quad上下文中按照图- 所示设置参数:

  • 因为现在的粒子实际上就是一个个平面,如果要让这些粒子看上去更接近圆球状的话,我们要在Inspector窗口启用Normal Bending(法线弯曲),并在输出上下文界面控制Normal Bending Factor数值(如图-29所示)。



图- 29

我们可以从表-1中看到在没有为Base Color Map关联纹理图集时,不同的Normal Bending Factor数值让粒子有很不一样的表现。



表- 1


  • 然后,把Use Base Color Map(使用基础颜色贴图)从Color and Alpha改为Alpha,意思是原先我们会使用纹理图集中的颜色+Alpha信息,现在只使用Alpha信息,这样我们就可以剔除颜色通道中原先包含的光照信息了。
1.2.9 我们的烟雾效果目前并不会受到场景中月光的影响,如果你旋转场景中的平行光,可以看到烟雾的亮度不会发生任何变化。要改变这种形态,如图-30所示,我们要将烟雾粒子目前的材质类型从Standard(标准)改为Translucent(半透明)。



图- 30

把Lighting(光照)下的材质类型改为Translucent以后,烟雾的颜色变成了绿色。这是因为我们还没有为此材质关联一个Diffusion Profile Asset所导致的(绿色是告诉我们当前的材质类型缺乏匹配的Diffusion Profile)。Diffusion Profile的作用是为半透明材质提供配置信息,比如光进入物体表面以后的散射距离(Scattering Distance),折射率(Index of Refraction)。
我们可以通过顶部菜单 Assets > Create > Rendering > HDRP Diffusion Profile在Project窗口中创建一个Diffusion Profile文件,然后关联到输出上下文的Diffusion Profile Asset参数中。Diffusion Profile参数设置可以参考图-31。



图- 31

在关联完以后,烟雾还是绿色的,这是因为我们还没有将新创建的Smoke Diffusion Profile与当前项目相关联,所以我们要点击提示信息右侧的Fix按钮完成这个关联(如图-32所示)。



图- 32

完成关联以后如果旋转Scene窗口,可以看到烟雾在不同方向上受到平行光的影响是不一样的。
最后,烟雾总是偏黑灰色,所以我们要在输出上下文的Set Color over Life功能块中将颜色设置为灰黑色,如图-33所示。



图- 33

最终烟雾效果如图-34所示:



图- 34

1.3 创造火焰粒子系统:
之前我们说过,一个Visual Effect Graph效果通常由多个粒子系统组成,火焰粒子系统是我们需要创建的第二个粒子系统。按照以下步骤完成火焰的创建:
1.3.1 在VFX_Bonfire这个Graph中的空白处右键点击,在弹出菜单中选择Create Node,然后在弹出界面中选择System分类,最后选择Simple Particle System(如图-35所示)。这会为我们创建一个马上可用的简单粒子系统。



图- 35

1.3.2 在Output Particle Quad上下文中做如图-36所示的修改:

  • Uv Mode设置为Flipbook Blend,这样我们可以在Update Particle上下文中使用Flipbook Player来播放Main Texture中关联的纹理图集动画。
  • 在Main Texture中关联Flame03_16x4纹理图集,并设置Flip Book Size为x=16和y=4。



图- 36

1.3.3 在Update Particle上下文中添加Flipbook Player功能块。如图-37所示,我们可以在Scene窗口看到,火焰粒子往上飞舞,飞舞过程中播放火焰燃烧的动画。



图- 37

1.3.4 为了解决火焰粒子群魔乱舞的问题,我们要在Initialize Particle上下文中移除Set Velocity Random功能块(如图-38所示)。这样的话就不会在粒子生成的时候,为每个粒子设置一个随机速度了。



图- 38

然后我们要在Initialize Particle上下文中创建Set Position (Shape: AABox) 功能块。选中Initialize Particle上下文,点击空格键,在弹出界面中输入aa,如图-39所示。



图- 39

然后如图-40所示,将Set Position块的默认Position Mode从Shape改为Volume,这样我们的火焰就会在指定Volume(体积)中充满整个空间。通过Scene窗口控件调整火焰的体积。调整满意以后,点击Visual Effect Graph界面的Save按钮保存,场景中的火焰粒子效果会被刷新并重新生成所有粒子。



图- 40

1.3.5 可以看到,目前单独的火焰粒子太小,因此我们要先把它们的尺寸弄的大一些。我们可以在Output Particle Quad上下文中的Set Size over Life块中进行设置。如图-41所示,我们可以通过调整曲线来控制火焰粒子从生成到死亡的大小。



图- 41

不过,通过Set Size over Life来调整火焰粒子的大小时,我们只能控制粒子的整体大小,也就是说无法控制每个粒子在单个方向上的大小。
如果我们仔细看一下所用的Flame03_16x4这个纹理图集(如图-42所示),可以发现每个火焰动画关键帧的图片其实是Y轴方向比X轴方向要大。因此我们还要找到一个方法,把火焰粒子的Y轴方向放大。



图- 42

1.3.6 我们可以通过在输出上下文中添加Set Scale块来实现让粒子的Y轴比X轴更大的目的。如图-43所示,我们添加了Set Scale块,并将Channels参数设置为Y,因此我们可以控制每个粒子Y轴的大小。这里我们设置为1.5,也就是Y轴比X轴大50%。当然,我们也可以将Channels参数设置为X,然后将X设置为0.5,也可以得到类似的效果(只是火焰粒子的整体大小会缩小)。



图- 43

调整完以后可以看到火焰钻到地下去了(如图-44所示)。这是因为火焰粒子的中心点(Pivot)处于粒子中央的位置。



图- 44

我们可以为输出上下文再添加一个Set Pivot块,用于调整火焰粒子的中心点(Pivot)。如图-45所示,我们将Channels参数设置为Y,Pivot数值设置为-0.4,我们的火焰效果就被整体提到靠近地面的位置了。



图- 45

1.3.7 当前的火焰粒子数量太多,火焰看上去太大,因此我们需要减少火焰粒子的数量。
如图-46所示,我们把Constant Spawn Rate中的Rate数值设置为4(减少到原来的四分之一),把Initialize Particle上下文中的Capacity数值设置为8(也是减少到原来的四分之一)。然后选中Initialize Particle上下文,并在Scene窗口中将包围盒的大小调整到与火焰大小基本一致。



图- 46

我们回到之前的烟雾效果,选中Initialize Particle上下文,然后在场景中调节烟雾效果的包围盒高度,如图-47所示。如果我们不把烟雾包围盒的高度增加到超过烟雾消失的高度,那么当烟雾包围盒不在场景相机的范围之内时,烟雾将不再被渲染。



图- 47

1.3.8 如图-48所示,目前的火焰粒子播放时会出现火焰被地面切断的显示效果,这显然不是我们想要的。



图- 48

解决方法如图-49所示:在输出上下文中启用Use Soft Particle(使用软粒子)功能,然后将Soft Particle Fade Distance设置为0.2(米),也就是把软粒子的消失距离设置为20厘米。



图- 49

1.3.9 我们的火焰中心还不够亮,边缘不够红。我们可以按照如图-50所示,调整输出上下文中的Set Color over Life功能块中的Color参数。



图- 50

具体做法是在HDR Gradient Editor界面,分别选中左下角和右下角的小图标,然后再HDR Color颜色选择界面分别设置一个大红色,并把Intensity(强度)数值调大到7左右。可以看到火焰中心产生了高亮效果,火焰边缘变得更红了。
1.3.10 目前地面上还没有被火焰照亮,一个最简单的方法是在火焰中间放一盏Point Light(点光源)。如图-51所示,创建一个Realtime(实时)模式的点光源,并放在火焰中间。



图- 51

1.3.11 现在我们来进一步处理烟雾的效果。我们可以使用Normal Map(法线贴图)为烟雾增加立体感。图-52所示为没有为烟雾添加法线贴图功能时的烟雾效果,烟雾没有立体感,感觉没有受到火焰亮度多大影响。



图- 52

按照如图-53所示为烟雾启用Use Normal Map(使用法线贴图)功能以后,可以看到烟雾的立体感马上出来了。如果我们移动上一个步骤中添加的点光源,可以看到烟雾效果还会随之变化。



图- 53

1.3.12 接着我们要在场景中添加一些自然力量,比如风对烟雾的影响。如图-54所示,我们在烟雾粒子效果中的Update上下文中添加一个Force功能块。模式设置为Relative(相对的),这样我们可以分别控制Velocity(速度)和Drag(拖拽)参数。在火焰粒子系统中,我们把Flipbook Player的Frame Rate从25增加到50。这是因为在我们为烟雾添加风的影响以后,烟雾移动的速度更快了,但是我们火焰燃烧的速度因为只有25帧每秒的播放速度,所以看上去很慢。因此我们要通过增加火焰动画的播放帧率,让火焰看上去燃烧的更快。



图- 54

1.4 改进篝火效果:
我们在前面的步骤中完成了烟雾和火焰效果的制作,不过还有很多可以提升的地方。现在我们来一步一步的完成效果提升的工作。
1.4.1 效果预热:第一个要做的事情是为整个粒子效果做“预热”。如果我们现在从头播放粒子效果,可以看到火焰和烟雾都是从无到有慢慢生成的,这显然不是我们想要的效果。我们想要让这些效果一开始就存在,而不是从零生成。
我们可以在Project窗口中选中需要预热的粒子效果,如图-55所示。然后在Inspector窗口中的Initial state(起始状态)中,把PreWarm Total Time(预热总时长)设置为5(秒),PreWarm Step Count(预热步数)设置为30(步)。



图- 55

完成上述设置以后,如果我们再到Visual Effect Graph按F5键刷新,可以看到Scene窗口的篝火效果不再从无到有生成了,而是会预先生成烟雾和火焰效果。
1.4.2 改进火焰效果:
当前的火焰效果来自Flame03_16x4这张纹理图集中的火焰颜色,关键帧动画,外加后面再Set Color over Life块中增大的HDR Color的Intensity(强度)值。这让我们看到了发光的火焰动画效果。
不过,如果我们把Scene窗口的后处理效果和光照效果移除(如图-56所示),然后把Set Color over Life块中的Color参数中额外添加的红色与增大的HDR强度值设为0,可以看到因为火焰纹理图集的分辨率以及图集中关键帧图片本身的颜色影响,火焰看上去并不真实。而且在图- 中左侧Scene窗口中,可以看到火焰边缘因为没有在Color参数中添加额外的边缘红色,边缘消失时渐变成了灰色,整个火焰忽然变暗了。



图- 56

为了解决上述问题,我们可以做两件事情:

  • 使用只包含黑白信息的纹理图集来表现火焰动画
  • 使用颜色渐变(Gradient)来控制火焰颜色
这样做的好处是动画与颜色分离,我们可以精确控制火焰的颜色了。
首先把输出上下文中的Main Texture纹理图集替换成如图-57所示的Flame03-hollow-temperature_16x5。



图- 57

我们会得到如图- 所示的黑白火焰效果,具体设置请参考图中指示。请注意Flip Book Size要设置成与纹理图集相同的16X5的列数和行数。
接着如图-58所示,我们把Color Mapping(颜色映射)从Default(默认)改为Gradient Mapped(渐变映射)。可以看到输出上下文中出现了一个新的参数Gradient(渐变),这里可以创建一个渐变色用于控制火焰从中心到外围的颜色和HDR强度。这个颜色和HDR强度会乘以纹理图集中的黑白色(代表0-1之间的数值),得到最终的火焰颜色和亮度。



图- 58

如图-59所示,我们在这里使用的Gradient渐变色,从右到左代表火焰的中心到边缘。最右侧的黄色+HDR强度为6.5,可以让我们获得火焰中心最亮的颜色和亮度;最左侧的黑色代表火焰最终消失的颜色和亮度。中间的四档则分别代表火焰强度由强转弱的渐变过程。



图- 59

如果你不清楚火焰颜色从最强到最弱的颜色变化,可以参考图-60中的颜色变化。你可以自由设定火焰在不同渐变档中使用的HDR强度数值,只要做到从右到左HDR强度值逐渐降低,看上去转换自然即可。



图- 60

图-61中是到目前位置的效果。



图- 61

以下视频是最终完成以后的效果(在火焰下方添加了一堆木头模型):

最终完成以后的效果
https://www.zhihu.com/video/1477581180077445120
1.5 创造火焰热力扭曲效果:
我们将在这个步骤创建火焰热力对空气产生的扭曲效果。
火焰是高温等离子体,会加热它所影响的局部空气,空气受热后密度变小,然后与周围冷空气形成微型对流。因为温度不同的空气折射率不同,所以会让光线发生不同程度的折射,因此就看到了扭曲效果。(上述信息来自“百度知道”)
1.5.1 创建简单粒子系统:
如图-62和图-63所示,创建一个简单粒子系统。



图- 62



图- 63

将粒子发射速率(Rate)从默认的16个降低到8个,将粒子总数(Capacity)从32个降低到16个。因为我们要模拟的扭曲效果是一整片区域的,所以并不需要很多粒子来参与模拟。
1.5.2 调整粒子随机速率和位置:
接着我们来调整粒子的随机速率和起始位置(如图- 所示):

  • 在Initialize Particle上下文中将Set Velocity Random(设置随机速率)按照图-64中数值进行设置。
  • 添加Set Position(设置位置)块,设置X为0.3,设置Y为0.8。这样我们可以把扭曲粒子系统放到火焰顶部偏向风吹的方向。



图- 64

1.5.3 修改输出上下文:
为了渲染扭曲粒子效果,我们要把输出上下文修改成支持扭曲效果的输出上下文Output Particle HDRP Distortion Quad。
如图-65所示,在现有输出上下文中右键点击弹出菜单中选择Convert Output(转换输出),然后再相应菜单中选择Output Particle HDRP Distortion Quad选项。



图- 65

然后我们为这个输出上下文指定一个渲染扭曲动画效果用的纹理图集WispySmoke03b_8x8_distortion(如图-66所示)。



图- 66

我们可以通过图-67来解释这张纹理图集的作用:

  • 在Uv Mode中切换成Flipbook Blend模式,然后Flip Book Size修改成X=8和Y=8。这样我们就可以正常播放扭曲动画了。
  • 这种纹理图集的三个通道中,R(红色通道)用于控制Distortion Scale中X轴的大小,G(绿色通道)用于控制Distortion Scale中Y轴的大小,而B(蓝色通道)则用于控制Blur Scale的大小(也就是扭曲效果的强烈程度)。



图- 67

然后如图-68所示,为Update Particle上下文添加Flipbook Player,并把Frame Rate(帧率)数值调整为55,与火焰动画的播放帧率一致。   



图- 68

然后我们通过调整Set Size over Life块中的Size(大小)参数让我们的扭曲面积增大,如图-69所示。如果后面感觉扭曲的面积不够大,可以再通过这条曲线来进一步放大。



图- 69

如图-70所示,调整Distortion Scale和Blur Scale以获得最终效果。



图- 70

1.6 创造小火星粒子系统:
1.6.1 创建Simple Swan Particle System:
现在我们来创建火焰上偶尔会爆发出的小火星的效果。与之前的三个粒子效果一样,我们需要为它创建一个单独的粒子系统。不过这次我们不再用简单粒子系统,而是用一个更复杂的Simple Swan Particle System来作为起始粒子系统(创建时所用菜单如图-71所示)。



图- 71

如图-72所示,这个系统的粒子数量非常之多,而且在Update Particle上下文中已经添加了Turbulence(湍流)这个功能块,让粒子可以产生自然的扰动效果。在输出上下文中的Set Color over Life块中也已经添加了一个渐变色,用于控制粒子群从中央向边缘的颜色过渡效果。



图- 72

1.6.2 调整粒子发射参数:
接下去我们调整一下粒子的数量和发射形状等参数。如图-73所示,我们先把粒子的生成速率降低到250个。可以看到在Initialize Particle上下文中的Add Position块中,我们的粒子是从一个圆球表面发射出来的,我们可以展开Arc Sphere参数组,调整Sphere > Transform下面的Position(位置)参数为X=0.1和Y=0.35。这会调整当前发射粒子的圆球形状在火焰中位置。然后调整Radius(半径)数值为0.2米,也就是缩小粒子发射圆球的大小。可以看到现在粒子数量减少了,发射的范围也变小了。



图- 73

1.6.3 调整粒子的运动:
目前的小火星粒子效果还是按照Update Particle上下文中的Turbulence块来进行湍流的运动,所以我们要做如图-74所示的修改,让小火星的效果更像现实世界中的效果,具体步骤说明如下:
1) 在Update Particle上下文中添加一个Force功能块,并将它拖动到Turbulence之上。这样Force会在Turbulence之前运行。
2) 我们将Force的参数设置为X=0,Y=0.5,Z=0。意思是小火星粒子会向上飞行。
3) Turbulence块的Intensity(强度)参数默认是1,也即100%作用在粒子上,这样会导致湍流作用对粒子的效果超过Force块给粒子向上的动力,因此我们要把这里的Intensity数值设置为0.5,减少湍流效果对粒子的影响力。
4) Turbulence块的Noise Type(噪声类型)为Perlin(柏林噪声),如果要让当前粒子拥有一个向上的且变化的噪声效果,我们可以为Field Transform > Position的Y轴数值关联一个Total Time的Operate(操作)节点。这个节点会为Y轴数值提供当前效果自开始运行以来过去的总时长。也就是能够为Y轴提供一个一直变化的数值,从而让Turbulence块拥有一直变化的噪声,然后驱动粒子多样的变化。



图- 74

1.6.4 转变粒子生成方式:
如图-75所示,目前粒子生成的方式为持续生成。



图- 75

我们要将持续生成改成过一段随机时间生成随机数量的火星粒子。如图-76所示,鼠标右键点击Spawn上下文,在弹出菜单中选择 Create Block > Spawn > Single Burst (Spawn),创建一个Single Burst(单次爆发)功能块。



图- 76

接着修改单次生成块的参数,如图-77所示,将单次生成模式改成Periodic(间歇生成模式),并设置Spawn Mode(生成模式)为Random(随机),并设置随机数量为5~10之间,也就是说每次生成的粒子数量会在5~10个之间。



图- 77

1.6.5 调整粒子的随机向上速度和大小:
目前的火星粒子生成以后,它们的速度是由Update Particle上下文中的Force和Turbulence所控制的。为了让这些粒子有一个初始的向上的动能,我们可以在Initialize Particle上下文中添加一个Set Velocity Random的块,并设置Y轴数值。再添加一个Set Size Random的块,设置最小值为0.05,最大值为0.1。这样可以将火星弄小一些(如图-78所示)。设置完成以后可以看到,小火星们拥有的随机的初始向上速度和大小。



图- 78

1.6.6 调整火焰的扭曲大小和强度:
目前火焰对空气的扭曲模糊效果太过强烈,因此我们要将当前的火焰扭曲效果减弱一些。如图-79所示调整Distortion粒子效果中的相关参数。



图- 79

1.6.7 调整火星的数量:
如果你觉得从火焰里面间歇蹦出的火星太多,其中一个控制方法是在Periodic Burst块中将Delay Mode(延迟模式)改为Random(随机)。示例设置如图-80所示。



图- 80

1.7 使用参数动态控制特效:
当前的小火星粒子只是往上飞舞,并没有按照场景中烟雾受到的风场的影响。如果要让火星粒子的飞行方向与风场的方向大概一致,我们要从烟雾粒子系统的Update Particle上下文中拷贝Force块到小火星粒子系统的Update Particle上下文中去,并且找到一个方法可以通过一个参数来控制烟雾系统和火星系统的风场数值。
1.7.1 拷贝Force功能块:
如图-81所示,我们可以直接从烟雾系统中拷贝一份Force功能块到火星系统中。拷贝完可以看到火星粒子的飞行方向开始跟烟雾的方向一致了。



图- 81

1.7.2 创建本地变量用于同时控制两个Force块:
我们可以通过创建一个本地变量同时控制两个Force块中的Velocity(速度)参数,而不用每次都要手动调节两个Force块中的Velocity数值。
如图-82所示,在创建节点的界面输入vector作为搜索关键字,在搜索结果中选择Vector3 (Operator Inline)。



图- 82

然后我们会得到一个新的叫做Vector3的节点,如图-83所示。我们可以右键点击这个新节点,然后选择Convert to Property(转换到属性),这会让Vector3成为一个本地变量。



图- 83

同时这个本地变量也会出现在VFX Graph界面的Blackboard(黑板)上(如图-84所示)。如果你的VFX Graph界面没有打开黑板窗口,可以点击VFX Graph窗口右上角的Blackboard按钮打开。图- 中的Vector3本地变量已经被改名为了Wind Velocity(风速),并连接到了火星粒子系统的Update Particle上下文中的Force块上的Velocity参数上。



图- 84

接着,我们可以将Wind Velocity节点复制一份,然后将它与烟雾系统的Force块上的Velocity参数相连接(如图-85所示)。



图- 85

这样设置完成以后,我们就可以通过黑板上的Wind Velocity界面来同时控制烟雾粒子的火星粒子的风速了。
1.7.3 使用暴露在Inspector窗口的参数控制风速:
如果我们这时选中关联了篝火VFX Graph组件的物体,可以看到在Inspector窗口中的Visual Effect组件上并没有暴露在界面上的属性(如图-86所示)。



图- 86

我们可以在黑板上启用本地变量的Exposed选项,如图-87所示,启用以后就可以在Inspector看到Wind Velocity选项了。



图- 87

现在我们可以在Inspector界面直接控制烟雾粒子和火星粒子的风速了。
1.7.4 控制火星粒子的湍流强度:
在真实世界中,如果风速增大,除了火星粒子的移动速度增大以外,整个粒子系统的湍流强度也应该增强,反之亦然。但是目前我们在火星粒子系统中设置的湍流强度为固定的0.5。也就是说不管风速增强还是减弱,火星粒子系统的湍流强度是不变的。这显然是不符合自然现象的。
因此我们要用Wind Velocity(风速)来计算一个湍流的强度出来。如图-88所示,要控制火星粒子系统的Turbulence(湍流)的Intensity强度,我们需要为其提供一个浮点数值,但是我们的Wind Velocity却是一个Vector3数值,无法直接跟Intensity相连。
因此我们要通过Wind Velocity这个Vecotor3节点来计算实际的风速数值。而实际的风速可以通过计算Wind Velocity这个Vector3来获得它的magnitude(大小)来获得。
要从一个Vector3来获得它的magnitude(大小),我们可以通过Length节点来进行计算。最终获得的风速数值,会随着风速的增强而变大,随着风速的减弱而变小,也就达到了在风速增强/减弱的情况下让火星粒子系统的湍流强度变大/减小的目的。



图- 88

完成上述步骤以后,我们可以看到在风速增大/减弱时,火星粒子系统的湍流强度会随之增强/减弱。
1.8 粒子效果优化:
最后,我们来看一下如何优化已经完成的粒子效果。我们知道生成的粒子实际上是由一个个透明的平面加上纹理所组成的,因此我们肯定会有Overdraw(过度绘制)的问题。过度绘制会在渲染单个帧的时候在屏幕上多次绘制某个像素。再叠加我们的粒子起始是一个个透明的平面,通常它们还要做Alpha Blending这样的操作以获得更好的效果,因此对性能的影响就更大了。
HDRP里提供了Debug窗口用于查看当前场景的各种渲染情况。我们可以通过顶部菜单 Window > Analysis > Rendering Debugger打开Debug窗口(注:此菜单为Unity 2021.2中的位置。如果你使用的是其他Unity版本,Debug窗口的菜单可能在别的位置)。图-89中显示的是在打开的Rendering Debugger窗口中,选择Rendering界面,将Fullscreen Debug Mode(全屏Debug模式)从默认的None切换成TransparencyOverdraw模式。
我们可以看到与全屏Debug模式相关的Max Pixel Cost参数的默认设置为10,它的意思是如果屏幕上有10个或者以上数量的透明像素重叠的话,对应的像素就会用红色来着色。透明像素重叠的数量越少,相关像素的颜色越淡(蓝色)。由此我们可以知道,目前烟雾粒子效果的Overdraw问题很大,非常影响粒子效果的运行性能。
解决过度绘制的主要方法是减少重叠对象的数量,以及减小这些对象在屏幕上所占的比例。



图- 89

我们可以通过以下两个具体方法来减缓或者解决当前的Overdraw问题:
1.8.1 改变粒子的输出形状:
因为当前的Overdraw问题主要由占据屏幕空间最大面积的烟雾粒子效果所导致,所以我们可以先尝试改变烟雾的输出形状。
如图-90所示,在VFX Graph中选中烟雾粒子效果的Output Particle HDRP Lit Quad上下文,然后在Inspector窗口中的Primitive Type里选择Octagon(八角形)作为输出形状。



图- 90

可以看到原先的四边形(Quad)粒子变成了八边形的(Octagon)粒子。然后通过修改烟雾粒子系统的输出上下文中的Crop Factor(裁剪系数),可以看到系数数值越大,粒子的形状更接近星形(对比如图-91,图-92和图-93所示)。



图- 91



图- 92



图- 93

当然,Crop Factor数值设置的越大,烟雾效果越不真实。这是我们不想要的结果。不过即使我们不改变默认的Crop Factor,可以从图- 看出,我们的Overdraw情况已经有所改善。
接下去我们要用到第二个方法来解决Overdraw的问题。
1.8.2 使用LowResolution低分辨率的透明渲染:
第二个方法是如图-94所示,将烟雾粒子系统输出上下文的Transparent Render Queue从Default(默认)切换到LowResolution(低分辨率)。这时HDRP会使用之前一半的分辨率来渲染烟雾粒子效果。



图- 94

如果我们比较表-2中的两个效果,可以看出两者在烟雾表现上并没有很大区别,但是性能提升了很多(参考表-3中Profiler里优化前后的数值对比)。



表- 2



表- 3

当然,我们也可以针对火焰粒子系统做相同的修改,以获得更好的性能。图-95中是把火焰的Primitive Type从Quad改为Octagon,把Transparent Render Queue从Default改为LowResolution以后在Profiler中的性能表现。图-96为优化了烟雾和火焰两个粒子系统以后,在Rendering Debugger窗口看到的TransparencyOverdraw情况,可以看到基本上没有过度绘制的问题了。



图- 95



图- 96

1.9 结语:
本文通过对一个写实类篝火效果制作的讲解,带大家一步步完成了四个Visual Effect Graph粒子系统,并将它们组合在一起。我们一起学习了以下知识点:

  • Context(上下文)和不同上下文的作用:Spawn,Initialize Particle,Update Particle和Out Particle上下文
  • Block(功能块),并学习了一些常用Block的用法,比如Turbulence,Force,Flipbook Player,Set Velocity Random等
  • 如何使用本地变量和全局变量
  • 如何通过Rendering Debugger窗口检查性能问题,并解决Overdraw性能问题
此教程为我的系列Visual Effect Graph教程的第一篇,之后我会陆续推出更多Visual Effect Graph特效相关的案例教程。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-8 07:44 , Processed in 0.094248 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表