本来打算还是在Unity里使用Amplify Shader Editor进行逻辑讲解的,但是最新版本的Unity一直下载不上,旧版本又被我卸载了,索性直接使用Unreal讲解吧。
没用过Unreal的朋友也不要怕,这一篇文章只是讲解Shader效果的实现逻辑,使用什么工具并不重要。能理解效果的实现逻辑,并按照逻辑编写出Shader代码才是我们的目标。
好了,废话不多说了,我们开始进入正题。
Shader效果背景
不知读者朋友们有没有玩过生化危机7。我当时玩的时候,给我印象最深刻的一个画面就是:打开冰箱,盘子里有腐烂的剩菜剩饭,然后上面还蠕动着蛆虫。这个画面在我脑海里久久不能忘却,以至于两年后的今天,我决定跟大家分享一下这个Shader效果。
有的读者可能要问了,这种蠕动效果用模型+循环动画就可以实现了,为什么非要用Shader呢。没错,确实动画就可以实现。但是从可扩展性上来讲Shader更有优势。我们可以修改开放的参数产生多种不同效果,扩展性更广,所以这种效果还是交给Shader来实现吧。
为了避免给大家造成任何不适,我并没有真的还原生化危机7里的肮脏盘子,而是从网上找了一张比较唯美的图片作为贴图使用。以下是最终效果,请仔细看那只蛆虫。
Shader效果:蠕动的蛆虫
资源准备
一张有蛆虫的贴图:
BaseColor
表示蛆虫位置的Mask
Mask
为了节省资源,我把两张贴图合成了一张tga贴图,其中Mask作为alpha通道。
一张用于扰乱UV的Noise法线贴图,或者你也可以称它为FlowMap
Noise
逻辑讲解
本效果的整体思路是:以不停平移的Noise法线来扰乱正常的纹理坐标,使蛆虫所在位置的UV产生不停的扭曲,因此在贴图采样的时候会采集到蛆虫其它位置的像素,从而实现蛆虫不停蠕动的效果。
Noise的UV
1.纹理坐标乘以Noise Scale参数,用于控制Noise法线的平铺数量,连接到Panner节点的Coordinate上。
2.Time变量乘以Speed参数用于控制速度,连接到Panner节点的Time上。
3.Panner节点(与Amplify Shader Editor中的Panner节点类似)用于实现UV平移的效果,链接到Noise法线的UV上
当平移速度不变的情况下,贴图的平铺数量越高,UV平移速度看起来会越慢;相反,贴图的平铺数量越低,UV的平移速度看起来会越快。为了避免这个问题,我们先把Time变量乘上Noise Scale参数,使平移速度跟平铺数量产生正比的关联,然后再与Speed参数相乘。
合并UV
1.因为UV是二维数组,所以我们使用Mask节点(与Amplify Shader Editor中的Component Mask节点类似)获取Noise法线的RG通道,把三维降为二维
2.乘2减1,是为了将数值范围[0, 1]映射到范围[-1, 1]。这个算法很常用,Unity中称之为Unpack,大家要记住了
3.乘以Range参数,用于控制Noise法线的强度。Range参数之所以除以了1000,是因为默认强度太大了,而我们只需要一点点Noise就足够了。
4.乘以贴图的alpha通道,为了使只有蛆虫的位置有Noise,而其他位置为0
5.然后与正常的纹理坐标相加,连接到贴图的UV上
开放的所有参数
材质参数
1.Noise Scale用于控制Noise的平铺数量,进而控制蛆虫扭动部位的大小
2.Range用于控制扭动的幅度有多大
3.Speed用于控制扭动的速度
读者朋友们如果感兴趣,可以按照以上逻辑还原生化危机7里恶心的盘子画面,只需要画对了蛆虫位置的Mask即可。
下次再有时间,我会在Unity中编写Shader代码,实现本篇教程中的效果。