本篇主要写一下扫光(Scanning)以及全息影像(Hologram)的特效的基本 Shader 思路。也会简单介绍一点 Shader 的基础。
我们主要会用 Unity Asset Store 中的 Amplify Shader Editor 。这是一个界面与 UE 不能说有点相似只能说一模一样的节点化编程界面,个人觉得比 Unity 自带的 Shader Graph 要好用直观很多。(https://assetstore.unity.com/packages/tools/visual-scripting/amplify-shader-editor-68570)
我会从一个 URP 的基本项目开始做起,然后写一些关于扫光特效背后的惯用思路。先建一个 URP 项目,然后打个大概像下面这样的光就行。我用的引擎版本是 2022.3.7f1。
扫光
基本界面
先从 Package Manager 里面导入 Amplify Shader Editor 并安装。然后就可以像下面这样右键 Create > Amplify Shader 来创建一个新的 Shader 文件。如果是 URP 的话,我们从 Universal 的 Lit 开始。
我们会看到下面这样的界面。与 UE 不能说有点相似,只能说一毛一样。
基本快捷键
首先,确保一下 Shader Type 是 Universal/Lit。其他的我们需要改的时候再改。
右键点击空白处,可以呼出 Search 面板,可以搜到能用的所有节点。
按住键盘上的数字 1 键,然后鼠标左键点击空白处,就可以制作一个 Float 节点。
点击这个节点可以到左侧面板看到这个节点的相关信息。
在这里:
- Type:可以设置成 Property。如果是 Property的话,我们就可以在引擎中的 Inspector 里面去修改这个数值。否则就只是 Shader 中才能看到的变量。
- Name:修改变量的名字。但是注意,比如你把这个变量改名为SomeVariable,之后如果在C#脚本中使用material.SetFloat() 的话,要记得这个变量实际的名字是 _SomeVariable,在这个名字前面有个下划线。
- Min/Max:修改其中一个就可以把这个数值变成一个带滑竿的数值。
- Default Value:这个变量的初始数值。
一些基本快捷键
与按住 1 类似点左键制作 Float 类似:
- 按住 2:制作 2D 向量(Vector2)。
- 按住 3:制作 3D 向量。
- 按住 4:制作 4D 向量。
- 按住 5:制作 Color (本质也是一个 Vector4)。
- 按住 T:制作 TextureSample 节点(用来放贴图)。
有一些进行数值计算的节点也比较常用:
- 按住 M:Multiply,乘法
- 按住 A:Add,加法
- 按住 S:Subtract,减法
- 按住 D:Divide,除法
- 按住 E:Power,次方
- 按住 O:One Minus, 进行 1-Input 计算。
好,到这里 ASE 的基本操作就差不多了,剩下的就是用图形化节点处理程序思维的事情了。
菲涅尔边缘光
咱们从用 ASE 制作上一篇笔记的边缘光效果开始。先习惯 ASE 的操作。
回顾一下边缘光的计算。首先是 NdotV 向量的使用:
N:是指世界坐标系下的顶点法线向量。
V:是指观测方向的向量(View Direction)。
两个向量都应该是单位向量。那么显然,如果这两个向量的点乘结果越接近0(也就是垂直),我们就越不应该能看到这个顶点。因此,处于一个物体边缘的那些顶点,应该是NdotV取值最小的点。那么,越靠近边缘,1-NdotV 就越应该接近1。
先验证这个想法。
首先,用 World Normal 节点和 View Direction 节点,先获得 N 和 V 两个向量。然后用点乘操作(dot,也可以按住键盘上右 shift 左边的那个句号键)将其相乘。点开 dot 节点右上角的小三角可以看到,确实,NdotV的结果是中间亮,边缘黑,与我们分析一致。
然后使用 One Minus 节点,对其进行取反。
已经有边缘变白的效果了。但是,为了严谨,我们希望 NdotV 最终的取值在 0 到 1 之间,所以我们用一个 Clamp 来确保这个,再取反。
好的,已经差不多了。如果我们希望让中间黑的部分较大,边缘更清晰更明显,我们可以认为是希望让一个黑的值更黑。在 ASE 的颜色显示模式中,黑色代表接近 0,白色代表接近 1. 那么什么操作可以让灰色变得更黑呢?也就是让一个零点几的数字变得更小——我们可以使用求次方的方法。
对 One Minus 的结果再求一次次方,就可以很明显地看到只有边缘的白色才非常明显了。这就已经是很清晰的边缘光了。
最后,我们想再调节边缘光的亮度,那么就是让一个接近白色的光变得更白。要让一个零点几的数字变得更接近1,我们就只需要再乘以一个常数就行了。
记得将这里出现的所有常数都记成 Property,以便我们在 Inspector 中修改。
现在我们已经有一个有关边缘所在位置的 0-1 的信息了(这个 Multiply 材质球中的结果,黑色的部分就是计算结果为 0 的部分,白色的结果就是计算结果为 1 的部分)。由此,如果我们想要这个边缘光有颜色,我们只需要给它乘以一个颜色值就行了。
至此,边缘光的计算已经完成。我们将其实际地输出到主节点上。
思考一下,黑色的部分是透明的部分,有色部分是边缘光的部分,所以我们要把 最后一个 Multiply 球的结果接到 Alpha 通道(管理透明度的部分),以及 Emission 通道(负责发光的部分)。
点击左上角如下图所示的图标,开始进行一次保存和 Compile。
别忘了到屏幕左边面板处找到 Surface,将其从 Opaque 调成 Transparent。在 Blend 模式中,URP 的默认模板带了4个混合模式,可以自己尝试一下选择哪个。最终我们选择的应该是 Premultiply。
到 Unity 中,我们先新建一个材质球,然后将其 Shader 修改为我们写的 Shader。然后附到物体上看看最后的效果。还是挺不错的。
回到 ASE 中,我们找到一个节点叫 Fresnel。这个节点其实就干了我们前面几个节点计算边缘和增强强度的过程,所以以后就可以直接用 Fresnel 来计算边缘光了。
加一些节点给边缘光更多的调整空间,比如分内外两层颜色,让边缘光有一个更平滑的过度和更多的色彩取向。
【Tip】选中多个节点按 C 就可以建组并且加评论。
效果还不错。(我这边做了 PostProcess 所以有 Bloom 效果)
扫光
下面开始做扫光特效。
首先我们需要一个扫光贴图。这个贴图就是扫下来一道一道杠的时候,那个一道杠的贴图。用一些中间是亮色两边是的黑色的贴图就行,比如(https://blog.csdn.net/lsccsl/article/details/118091355)
建议自己画一个也行,很快。
逻辑原理
扫光的本质就是将这个贴图在物体的 UV 贴图上上下移动,只不过我们希望这个贴图是在世界空间下移动,而不是在物体空间内。所以我们要针对世界空间采样,然后基于时间,让它在y轴上上下移动。
节点
首先先用以下几个节点实现在时间上移动的方法。正确连接时,ScanLightTexture上的图就应该已经在纵轴上移动了。
然后想想,这个黑色贴图中黑色的部分是不透明的,蓝色的部分是发光的,所以黑色的部分得去 Alpha通道,蓝色的部分得去 Emission 通道,因此把这个和之前的 Rim Light 加起来,连好。
回去看小人。
确实有光在身上乱窜,但是位置不对,很乱。这是因为采样没有做对。因为我们现在使用的 Texture Coordinates 依然是 UV 坐标,只要这个人不是横向展开的 UV 贴图,那么这个扫光贴图就会在身上乱跑。
所以我们要去用世界坐标来代替 Texture Coordinates 这个节点。
我们用 World Position 节点,外加一个 Append 节点获得 XY 平面的二维坐标,再增加二维速度值,以达到扫光贴图在XY平面走的效果。
此时,扫光就正常在 XY 平面上上下移动了。
参考:
GAMES 101, https://www.bilibili.com/video/BV1X7411F744/?spm_id_from=333.337.search-card.all.click
【TA入门】CS0103:半透明渲染与纹理动画, https://www.bilibili.com/video/BV1eN41127E4/?spm_id_from=333.999.0.0&vd_source=bb8b9452f6005d9ceb22019ade04d80f
Computer Graphics (15462), http://15462.courses.cs.cmu.edu/fall2020/
Comments