前言
啊咧咧,從大學畢業開始,有一段時間沒有更新過博客了,很懷念當初邊學習邊寫博客的時光。今天打開博客網站看着各位大神通過文字來分享自己的技術心得,也手癢了,決定也來一篇!
說完上面的話,感覺自己像是大佬一樣。嘿嘿,然而本篇文章還是一個小白文,就是Shader Graph
的入門知識,一個簡單的物體溶解效果,意在幫助新手了解Shader Graph
這個工具。效果如下圖,如果你感興趣,可以看看后面的實現方式,然后來試試吧!
注:本項目Unity
版本為2021.1.12f1c1
一,配置環境
為了使用Shader Graph
這個工具,我們首先需要配置一下開發環境,由於目前的Shader Graph
一般應用在Urp
或Hdrp
的可編程渲染管線模板下,所以我們要在項目中使用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 lit
與Sprite UnLit
則多應用於2D場景Workflow
:有鏡面(Specular
)與金屬度(Metallic
)Surface
:Transparent
(透明)、Opaque
(不透明)Alpha Clip
:透明通道裁切(小於該值的透明通道歸零)
在創建完Universal
后,可以發現在節點編輯區出現了最終的輸出面板
物體溶解效果原理
實現物體的溶解效果,在本項目中是通過修改物體材質的透明度實現的,既物體材質的Alpha
通道,但是如何修改才能確保物體准確的溶解呢。
要實現這樣的效果,需要通過一個關鍵的節點來實現該功能:
Simple Noise
(噪波節點):根據UV
生成簡單的噪波,可以利用其隨機的確定物體不同位置的透明度,而且如果仔細觀察噪波圖,會發現透明度高與透明度低的地方是漸變的,而不是截斷的(要理解這一含義,可以從水波的效果來思考,任意相鄰的兩點之間是連續的,而不可能存在橫截面)
為什么噪波的分布是漸變的,可以通過官方文檔看出:
- 在兩個決定的UV坐標點之間的的噪波強度的計算為插值計算,而不是隨機產生:
到這里,你可能不太理解,這樣一張噪波圖為什么能做到溶解的效果,如果僅僅通過其來改變物體的透明度,怎么形成變化的溶解呢
其實很簡單,首先我們定義一個從零到一變化的值,然后利用這個值對噪波圖進行處理,高於這個值的區域設置其Alpha
為一,而低於這個值的區域則為零,這樣,隨着這個值的不斷增大,直到大於一的時候,物體透明的區域逐漸增大至全部。這一過程就是實現溶解的方式
可以舉這樣的一個例子,白蛇傳中水漫金山,你從一張等高圖中看到的場景是什么樣子的呢,水慢慢的占滿了整個地圖,如何占據的呢,就是根據一條條等高線逐漸的蔓延:
類似如圖,噪波圖里面的透明度也會形成一條條這樣的線,在溶解時,透明度小的線先消失,直到最大為1的線消失。
節點介紹
如果你看了上面的介紹,有可能會覺得很麻煩。我要如何修改Alpha呀,這怎么可能去使用一個值來分割出來不同的透明度區域,而且還要歸一或者歸零。
如果你有這些問題哈哈哈,那說明你真的是新手,Shader Graph
作為一個專門編輯Shader
的工具,為我們封裝了許多許多的方法來幫助我們開發,在本案例中,會有幾個節點很方便的幫助我們來實現這樣的效果:
Time
:可以幫助我們生成一個變化的數值Step
:本質上是一個bool類型判斷節點,但是返回的是0或1,而且判斷條件也是比較兩個數值的大小Remap
:用來重新映射一個區間范圍,比如說將從0到10的數字映射到從0到1add
:加法Multiply
:乘法
不多廢話了,簡簡單單的一個溶解效果,結果讓我說了這么多廢話
實現
如果你對原理不感興趣,上面全是廢話,下面直接開始效果實現的教程
1,更改Universal選項
前面我們添加了一個Active Targets,但是你會在Fragment(片元着色器)中發現沒有Alpha通道,而我們要對透明通道進行裁切,所以我們需要在Universal中將Alpha Clip中勾選上:
如上圖,我們在右邊設置完畢后,左邊的Fragment
會多出兩個輸入項,一個是Alpha
用來控制透明度,而另外一個Alpha Clip Threshold(1)
則是我們上文說到的實現截斷功能的輸入。當Alpha
小於Alpha Clip Threshold(1)
時,則物體會直接透明,若大於該值時,不處理
注意:
- 如果是不透明物體,不要嘗試將Surface選項更改為Transparent(透明),如果設置為透明,物體會未溶解部分會出現半透明的情況
2,為物體添加材質
首先說明一下如何添加一個輸入:在變量添加區域點擊加號,即可添加一個變量,變量的類型有Float
、Color
、Texture
等等
創建一個Texture
輸入變量,拖入到節點編輯區,點擊后可以在屬性調整區添加一張貼圖。並連接一個材質節點Sample Texture 2D
節點,連接好后,將該節點的輸出連至Base Color(3)
,如圖:
3,溶解效果的實現
之前說過,溶解效果需要一張噪波圖與一個0到1的變化的數值(通過Time
節點的Sine Time
產生,同時使用),具體的連線如圖:
注:
Sine
節點本質是一個Sin
函數,我們知道sin
函數是一個y值為-1到1的一個循環的曲線,x是由Unity
的Time
來決定的,所以會隨着時間變化持續的輸出-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
很明顯的優勢就是可以對於效果原理的理解很形象,能夠更好幫助初級開發者的學習渲染的知識。如果你和我一樣也是一個小白,也嘗試去學習一下吧!