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

前言

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

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

注:本项目Unity版本为2021.1.12f1c1

一,配置环境

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

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

创建方式为打开Unity Hub,然后点击创建,选择Urp模板创建即可:
在这里插入图片描述

第二种:

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

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

在这里插入图片描述
如图所示,通过搜索Universal RP,可以找到Urp的插件,通过左下角的安装按钮可以将其导入到项目中,然后需要对项目的渲染管线进行一系列的配置,具体的配置可以查看之前的文章:

文章链接:

二,创建一个Shader Graph文件

完成上面的环境配置后,就可以在project面板右键选择创建,然后选择Shader,并在其中找到Blank Shader Graph(注意,我使用的是2021.1.12f1c1版本的Unity,更早版本可能没有这个选项,可以选择PBR Shader)并点击创建一个Shader Graph
在这里插入图片描述
命名为Dissolve,创建完成后,我们可以在编辑器中找到一个与刚刚创建的Shader Graph命名相同的窗口,接下来就可以在这里面实现一些连连看的操作了。

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

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

在这里插入图片描述
四个具体区域:

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

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

添加ActiveTargets

在属性调整区域(Graph Inspector)里面选择Graph Setting中找到Active Empty,初始时我们可以看到上面显示List is Empty,很明显,我们需要新建一个,点击加号添加一个Universal,就可以在下面的内容中调整我们需要的Shader类型属性:
在这里插入图片描述
如果你经常为模型调整材质,相信你对这些参数一定不会陌生,如果你不了解也没有关系,下面列出一些关键的参数来帮助你去调整自己的Shader:

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

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

物体溶解效果原理

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

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

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

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

  • 在两个决定的UV坐标点之间的的噪波强度的计算为插值计算,而不是随机产生:在这里插入图片描述

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

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

可以举这样的一个例子,白蛇传中水漫金山,你从一张等高图中看到的场景是什么样子的呢,水慢慢的占满了整个地图,如何占据的呢,就是根据一条条等高线逐渐的蔓延:
在这里插入图片描述
类似如图,噪波图里面的透明度也会形成一条条这样的线,在溶解时,透明度小的线先消失,直到最大为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中勾选上:在这里插入图片描述

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

注意:

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

2,为物体添加材质

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

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

3,溶解效果的实现

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

在这里插入图片描述

  • Sine节点本质是一个Sin函数,我们知道sin函数是一个y值为-1到1的一个循环的曲线,x是由UnityTime来决定的,所以会随着时间变化持续的输出-1到1在这里插入图片描述

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

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

4,为溶解边缘加高光

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

好像是边缘没有光呢,没错,由于溶解边缘没有光,质感下降了许多,通过下面的操作,可以为其添加一些边缘光:
在这里插入图片描述
在上面的图示中,添加了一个Color类型的输入变量,用来控制边缘的颜色,而添加的三个节点,在前面有介绍,第一个就是Add按钮,在溶解的边缘的透明度的数值加一即为未溶解的边缘,类似于等高图,目前溶解到五千米,我加一米,即五千零一米,刚好是溶解的边缘,接下来通过一个Step节点 判断需要亮度的范围(即小于五千零一米的所有区域输出为1),这样透明区间到五千零一米之间就会有一圈亮的区域

5,通过脚本调用该效果

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

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

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

	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;
        }        
    }

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

结束

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

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

posted @ 2021-07-29 09:56  心之凌儿  阅读(1284)  评论(0编辑  收藏  举报