Notifications
Article
使用ShaderGraph制作Dissolve效果
Published 6 months ago
294
0
使用ShaderGraph制作Dissolve效果
伴随着Unity2018.1的正式发布,许多重要的功能也正式跟开发者见面了,我们今天要介绍的Shader Graph就是其中之一。Shader Graph为开发者提供了一套图像化的Shader 开发环境,它通过连接节点图的方式来实现Shader逻辑,既省去了编码调试的繁琐,也不用在代码编辑窗口和Unity之间来回切换查看效果。可以说,Shader Graph的推出,又再一次为Shader开发进行了提速。在上一次的官方直播课程中,我们已经为大家介绍了Shader Graph的安装和使用,也介绍了一些实例来帮助大家熟悉Shader Graph的功能。这一次,我们将通过一篇短文为大家介绍如何用Shader Graph来实现消融特效。
消融特效是一种在游戏中非常常见的特效,我们常常在物体消失的时候使用这样的特效,当然也可以用在物体出现的时候。下面两张图分别表示了两种不同的消融效果,左边一张是表面不规则的消融,右边一张是按照特定的方向消融。接下来,我们就会介绍这两种不同效果的实现。

1. 不规则消融

这个效果的实现主要包括两个步骤,首先就是让物体的表面无规则的消失,就像冰块消融在地上一样。然后就是绘制边缘,有的消融效果会有明显的边缘,比如被火点燃的报纸,燃烧和未燃烧部分有一个明显的边界。接下来我们就分别实现这两个部分。
1)实现表面消融
这个功能的实现应该说还是比较容易的,主要是利用一张噪音贴图来映射表面的Alpha值,然后通过控制AlphaTest的值来控制表面区域的显示。由于噪音贴图的不规则性,当AphaTest的值从0到1变化的时候,物体就会逐步无规则的消失掉。ShaderGraph的节点图如下图所示:

其中噪音贴图我们使用了ShaderGraph内置的SimpleNoise节点,这是一种程序化生成的噪音贴图。同时,我们通过属性节点DissolveAmount作为AlphaClipTreshhold的输入,这样我们就可以在游戏中用脚本来控制物体消融的动画。

2)绘制消融边缘
首先我们需要找到这个边缘区域,从上面的步骤中可以看到,噪音贴图中小于DissolveAmount的区域即是被剪裁的区域,如果稍微增加一点DissolveAmount,我们就可以得到和显示部分重叠的区域。如下图所示:


上图中圆形部分可以看作被剪裁区域,橙色圆圈外部的扩展部分可视为边缘区域。下面我们就来看下ShaderGraph中的具体实现:

首先我们增加了一个EdgeSize的属性节点,并设定值为0.05,大小可以根据实际效果进行调整。然后我们用DissolveAmount 加上 EdgeSize 后再减去噪音值,得到扩展后的剪裁区域。之后利用Step函数把这部分区域的值都变为1,最后再乘以边缘颜色。经过以上步骤我们就初步实现了带边缘的消融效果。

以上效果在场景中添加了Unity Postprocessing Stack的Bloom效果,所以颜色显得更加光亮。


对于一些燃烧的效果,边缘可能需要渐变色。我们可以利用一张渐变色贴图来进行颜色采样:


实现上和之前稍有不同,对于扩展后的剪裁区域,我们不再是直接利用Step把值都变为1,因为我们需要利用这部分的渐变数值进行贴图采样。由于这部分的数值偏小,不能直接对应到渐变色贴图的uv坐标,所以在采样之前对数值进行了倍数放大。实际节点图如下所示:


运行效果:


2. 沿固定方向的消融效果


除了不规则的消融,沿固定方向的消融效果也比较常见。和之前利用噪音贴图来映射Alpha值不同的是,我们需要根据位置来映射Alpha值。比如我们溶解的方向是自上而下溶解,那么我们需要表面像素的Alpha值从低往上映射到[0,1]区间。如下图所示,我们主要通过两步来实现了这个映射,首先,利用点积把坐标映射到溶解的方向,当前所取方向为(0,1,0)。通过这一步,坐标被映射到[-1,1]这个区间。然后再利用remap把坐标映射到[0,1]区间。


接下来是添加边缘色。首先需要确定边缘区域,我们还是通过扩展一点剪裁区域作为边缘,如下图所示:


表示为公式即:
step(MappedAlpha - EdgeSize, DissolveAmount)

其中MappedAlpha是上一步计算的Alpha映射值,EdgeSize表示边缘的大小。通过上述公式,我们可以找到扩展的剪裁区域。确定好边缘区域,我们需要进行上色。在本例中,我们使用了像素风格的边缘效果。为了实现像素风格的边缘,我们需要把uv映射到一张像素风格的贴图上,这个例子中,我们直接使用了计算的方式。公式如下:
FinalColor = step( 0.5, randomRange( floor( uv * k ) ) ) * InColor
通过把uv乘以一个倍数k,再进行floor运算,可以把uv映射到[0,1,……,k-1]的整数数列上,这样就可以把连续值进行离散化。从而实现像素风格的边缘效果。具体实现如下图所示:



运行效果:


3. 总结

通过以上介绍,我们可以看到消融效果主要是通过AlphaTest技术来控制表面区域的显示,因此我们需要针对不同的效果实现不同的Alpha映射,对于不规则消融,我们使用噪音贴图来映射;对于方向性的消融,我们使用坐标转换的方式进行映射。另外,使用Shader Graph来实现,整个中间过程都暴露在你面前,因此可以很方便的对于效果进行调整,比如边缘的宽度,颜色,以及像素方块的大小等等。后续,我们还会继续介绍基于ShaderGraph开发的效果,帮助大家更多的了解这个新的功能。

Tags:
ChengLiang
Product EvangeList - Educator
7
Comments