前言

啊咧咧,从大学毕业开始,有一段时间没有更新过博客了,很怀念当初边学习边写博客的时光。今天打开博客网站看着各位大神通过文字来分享自己的技术心得,也手痒了,决定也来一篇!

说完上面的话,感觉自己像是大佬一样。嘿嘿,然而本篇文章还是一个小白文,就是​​Shader Graph​​的入门知识,一个简单的物体溶解效果,意在帮助新手了解​​Shader Graph​​这个工具。效果如下图,如果你感兴趣,可以看看后面的实现方式,然后来试试吧!

Unity 使用Shader Graph实现物体溶解效果_Unity

注:本项目​​Unity​​版本为​​2021.1.12f1c1​

一,配置环境

为了使用​​Shader Graph​​这个工具,我们首先需要配置一下开发环境,由于目前的​​Shader Graph​​一般应用在​​Urp​​或​​Hdrp​​的可编程渲染管线模板下,所以我们要在项目中使用​​Urp​​或者​​Hdrp​​插件,具体的配置方法有下面两种

第一种:

在我们创建项目时,通过​​Unity Hub​​直接创建一个由Unity官方提供的​​Urp​​或者​​Hdrp​​的模板。

创建方式为打开​​Unity Hub​​,然后点击创建,选择​​Urp​​模板创建即可:

Unity 使用Shader Graph实现物体溶解效果_Unity_02

第二种:

点击​​Unity​​编辑器导航栏的​​Window​​菜单,并在其中找到​​Package Manager​​点击,即可打开资源包管理器面板,我们可以在这里面管理项目中的插件,或者安装一些​​Unity​​官方提供给我们的插件。

在本案例中,我们需要安装一个名为​​Universal RP​​的插件

Unity 使用Shader Graph实现物体溶解效果_渲染管线_03

如图所示,通过搜索​​Universal RP​​​,可以找到​​Urp​​的插件,通过左下角的安装按钮可以将其导入到项目中,然后需要对项目的渲染管线进行一系列的配置

二,创建一个Shader Graph文件

完成上面的环境配置后,就可以在project面板右键选择创建,然后选择Shader,并在其中找到​​Blank Shader Graph​​(注意,我使用的是​​2021.1.12f1c1​​版本的​​Unity​​,更早版本可能没有这个选项,可以选择​​PBR Shader​​)并点击创建一个​​Shader Graph​​:

Unity 使用Shader Graph实现物体溶解效果_Unity_04

命名为​​Dissolve​​,创建完成后,我们可以在编辑器中找到一个与刚刚创建的​​Shader Graph​​命名相同的窗口,接下来就可以在这里面实现一些连连看的操作了。

三,通过Shader Graph编写一个Shader ,实现物体溶解效果

在创建完之后,可以在窗口中看到下面图片中的一些内容,大概可以分为四个内容区域,我自己也对其进行了一些命名方便大家理解:

Unity 使用Shader Graph实现物体溶解效果_Unity_05

四个具体区域:

  • 变量添加区域:这个区域就是为我们添加一些输入变量,就像C#变量的​​public int i​​一样创建一个变量​​i​​,然后就可以在​​Inspecter​​面板对该变量进行调整
  • 属性调整区域:这个区域有点类似于​​Inspecter​​面板,可以对变量添加区域的一些变量进行数量或者进行调整
  • 节点编辑区:是我们的主要的工作区域,通过创建与连接一个个节点来实现最终的效果
  • 预览区域:可以实时的看到我们的材质显示的效果

了解完整个​​Shader Graph​​面板的基本结构,就可以开始通过该功能来实现一些效果了,终于来到了正题。

添加ActiveTargets

在属性调整区域(​​Graph Inspector​​)里面选择​​Graph Setting​​中找到​​Active Empty​​,初始时我们可以看到上面显示​​List is Empty​​,很明显,我们需要新建一个,点击加号添加一个​​Universal​​,就可以在下面的内容中调整我们需要的​​Shader​​类型属性:

Unity 使用Shader Graph实现物体溶解效果_Shader_06

如果你经常为模型调整材质,相信你对这些参数一定不会陌生,如果你不了解也没有关系,下面列出一些关键的参数来帮助你去调整自己的Shader:

  • ​Material​​:有四个选项​​Lit​​(受光:接受光照影响)、​​UnLit​​(不受光照影响,UI元素常常是​​UnLit​​)、​​Sprite lit​​与​​Sprite UnLit​​则多应用于2D场景
  • ​Workflow​​:有镜面(​​Specular​​)与金属度(​​Metallic​​)
  • ​Surface​​:​​Transparent​​(透明)、​​Opaque​​(不透明)
  • ​Alpha Clip​​:透明通道裁切(小于该值的透明通道归零)

在创建完​​Universal​​后,可以发现在节点编辑区出现了最终的输出面板

物体溶解效果原理

实现物体的溶解效果,在本项目中是通过修改物体材质的透明度实现的,既物体材质的​​Alpha​​通道,但是如何修改才能确保物体准确的溶解呢。

要实现这样的效果,需要通过一个关键的节点来实现该功能:

  • ​Simple Noise​​(噪波节点):根据​​UV​​生成简单的噪波,可以利用其随机的确定物体不同位置的透明度,而且如果仔细观察噪波图,会发现透明度高与透明度低的地方是渐变的,而不是截断的(要理解这一含义,可以从水波的效果来思考,任意相邻的两点之间是连续的,而不可能存在横截面)

为什么噪波的分布是渐变的,可以通过官方文档看出:

  • 在两个决定的UV坐标点之间的的噪波强度的计算为插值计算,而不是随机产生:Unity 使用Shader Graph实现物体溶解效果_Shader Graph_07

到这里,你可能不太理解,这样一张噪波图为什么能做到溶解的效果,如果仅仅通过其来改变物体的透明度,怎么形成变化的溶解呢

其实很简单,首先我们定义一个从零到一变化的值,然后利用这个值对噪波图进行处理,高于这个值的区域设置其​​Alpha​​为一,而低于这个值的区域则为零,这样,随着这个值的不断增大,直到大于一的时候,物体透明的区域逐渐增大至全部。这一过程就是实现溶解的方式

可以举这样的一个例子,白蛇传中水漫金山,你从一张等高图中看到的场景是什么样子的呢,水慢慢的占满了整个地图,如何占据的呢,就是根据一条条等高线逐渐的蔓延:

Unity 使用Shader Graph实现物体溶解效果_溶解_08

类似如图,噪波图里面的透明度也会形成一条条这样的线,在溶解时,透明度小的线先消失,直到最大为1的线消失。

节点介绍

如果你看了上面的介绍,有可能会觉得很麻烦。我要如何修改Alpha呀,这怎么可能去使用一个值来分割出来不同的透明度区域,而且还要归一或者归零。

如果你有这些问题哈哈哈,那说明你真的是新手,​​Shader Graph​​作为一个专门编辑​​Shader​​ 的工具,为我们封装了许多许多的方法来帮助我们开发,在本案例中,会有几个节点很方便的帮助我们来实现这样的效果:

  • ​Time​​:可以帮助我们生成一个变化的数值
  • ​Step​​:本质上是一个bool类型判断节点,但是返回的是0或1,而且判断条件也是比较两个数值的大小
  • ​Remap​​:用来重新映射一个区间范围,比如说将从0到10的数字映射到从0到1
  • ​add​​:加法
  • ​Multiply​​:乘法

不多废话了,简简单单的一个溶解效果,结果让我说了这么多废话

实现

如果你对原理不感兴趣,上面全是废话,下面直接开始效果实现的教程

1,更改Universal选项

前面我们添加了一个Active Targets,但是你会在Fragment(片元着色器)中发现没有Alpha通道,而我们要对透明通道进行裁切,所以我们需要在Universal中将Alpha Clip中勾选上:Unity 使用Shader Graph实现物体溶解效果_溶解_09

如上图,我们在右边设置完毕后,左边的​​Fragment​​会多出两个输入项,一个是​​Alpha​​用来控制透明度,而另外一个​​Alpha Clip Threshold(1)​​则是我们上文说到的实现截断功能的输入。当​​Alpha​​小于​​Alpha Clip Threshold(1)​​时,则物体会直接透明,若大于该值时,不处理

注意:

  • 如果是不透明物体,不要尝试将Surface选项更改为Transparent(透明),如果设置为透明,物体会未溶解部分会出现半透明的情况

2,为物体添加材质

首先说明一下如何添加一个输入:在变量添加区域点击加号,即可添加一个变量,变量的类型有​​Float​​、​​Color​​、​​Texture​​等等

创建一个​​Texture​​ 输入变量,拖入到节点编辑区,点击后可以在属性调整区添加一张贴图。并连接一个材质节点​​Sample Texture 2D​​节点,连接好后,将该节点的输出连至​​Base Color(3)​​,如图:

Unity 使用Shader Graph实现物体溶解效果_渲染管线_10

3,溶解效果的实现

之前说过,溶解效果需要一张噪波图与一个0到1的变化的数值(通过​​Time​​节点的​​Sine Time​​产生,同时使用),具体的连线如图:

Unity 使用Shader Graph实现物体溶解效果_渲染管线_11

  • ​Sine​​节点本质是一个​​Sin​​函数,我们知道​​sin​​函数是一个y值为-1到1的一个循环的曲线,x是由​​Unity​​的​​Time​​来决定的,所以会随着时间变化持续的输出-1到1Unity 使用Shader Graph实现物体溶解效果_Shader_12

如果你观察了预览区,你就可以发现,预览小球已经有了溶解的效果,What?这么简单?仅仅三四个节点,就可以实现一个高级的溶解效果。

这就是​​Shader Graph​​的优势,对于一些比较成熟的效果有着比较高的封装性,只需要简单的拖拽就可以完美的实现,但是不够灵活,对于一些创造性的活动就需要大量的工作

4,为溶解边缘加高光

完成上一步后,似乎和卖家秀不太一样呀,好像缺了点什么?

好像是边缘没有光呢,没错,由于溶解边缘没有光,质感下降了许多,通过下面的操作,可以为其添加一些边缘光:

Unity 使用Shader Graph实现物体溶解效果_渲染管线_13

在上面的图示中,添加了一个​​Color​​类型的输入变量,用来控制边缘的颜色,而添加的三个节点,在前面有介绍,第一个就是​​Add​​按钮,在溶解的边缘的透明度的数值加一即为未溶解的边缘,类似于等高图,目前溶解到五千米,我加一米,即五千零一米,刚好是溶解的边缘,接下来通过一个​​Step​​节点 判断需要亮度的范围(即小于五千零一米的所有区域输出为1),这样透明区间到五千零一米之间就会有一圈亮的区域

5,通过脚本调用该效果

实现这样的溶解效果后,可以作为一个角色死亡时的特效,但是该怎么去实现这杨的功能呢,本案例就提供一个简单的脚本来应用这样的效果。

由于角色的死亡是一次事件的触发,我们使用Sin函数来循环溶解该物体毫无意义,因此我们定义一个float变量输入作为从显示到完全溶解的控制变量。

Unity 使用Shader Graph实现物体溶解效果_渲染管线_14

通过改变这一变量来控制物体的溶解过程,具体的脚本实现方式为:

    public Material material;
public void Start()
{
//获取修改材质溶解度的变量并设置初始值
id = Shader.PropertyToID("TestNum");
material.SetFloat(id, 0);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(DestroyCube());
}
}
IEnumerator DestroyCube()
{
int n = 2000;
float num = 0;
Mathf.Sin(Time.time);
while (n>0)
{
num = Mathf.Lerp(num, 1,0.001f);
material.SetFloat(id, num);
n--;
yield return null;
}
}


编写上面的脚本,挂载到任一物体上面,并将刚刚创建好的材质拖入即可,这样就可以实现一个由事件驱动的溶解效果,如图点击空格键后效果:

Unity 使用Shader Graph实现物体溶解效果_Shader_15

结束

​Shader Graph​​对于不会编程写​​Shader​​的人很友好,通过简单的学习就可以实现一些很酷炫的效果,但是相比来说,还是没有编程实现那样的灵活。并且效果的性能完全是自己不可控的,取决与​​Unity​​官方的性能优化,这样来讲,适配性就低很多。

不过​​Shaer Graph​​很明显的优势就是可以对于效果原理的理解很形象,能够更好帮助初级开发者的学习渲染的知识。如果你和我一样也是一个小白,也尝试去学习一下吧!