簡介
在Unity Shader Graph可以利用Node的堆砌達到許多大自然界裡的現象,之前介紹的雨水波動以及草的搖晃皆是用Shader Graph就可以用一個材質球就完成了,今天要介紹的是利用簡單的模型製作模擬雲霧的效果,而這個Shader更可以改變使用方法讓他變成湖水、海浪、瀑布等等自然界常見的狀態,這次的實驗利用2km的模型並配合Shader Graph讓模型沒有任何的貼圖就可以達到雲霧的效果。
Step 1 . 因為製作雲霧的時候我們需要一個非常大的模型以及非常多的面數才有辦法讓Shader Graph 控制,因為這次的時間是做成天空上的雲霧,這個圓形扁平的模型直徑足足需要真實世界上2KM大小來製作,這邊就不多做模型上的建模說明,想要玩看看的朋友可以到以下連結下載Fbx模型直接製作。

Step 2 . 再來我們直接將Fbx匯入Unity後開始製作ShaderGraph,因為這次主要是用到color 跟 Vertex Position 兩個通道,所以我們製作HDRP的Unilt Shader。

首先我們先建立一個Gradient Noise當作雲霧的貼圖,接著需要Tiling And Offset當作調整用的Node,接著給他一的Position控制UV的位置,串好這三個Node以後我們把拉串到Color看看。

Save Asset進去Scene看一下貼圖的狀況,發現這個狀況非常地糟,整個Noise的貼圖只往同一個方向在跑,這是不對的。

Step 3 . 接著我們來改一下整個UV的Axis , 先製作一個Rotate About Axis Node,再製作一個Vector 4 Node 變成屬性以利控,並串入Split並將Split的A通道串接到 Rotate About Axis 的Rotation 讓他變成90度,串接好以後我們來看一下。

這邊直接調整W的數值就可以發現整個貼圖從直線的狀態變成了正常的Noise狀態。


Step 4 . 不免俗的這是一個動態的Shader Graph 當然少不了Time Node,我們可以先製作一個Time Node 以及 Vector 1 屬性來控制,關於時間的兩個node串好給Multiply Node並串到原本的Tiling and offset 的 Offset通道就可以看到貼圖開始動起來了。
因為我們的模型尺寸有2 km這麼大,所以貼圖的尺寸也是需要調整的,我們這邊一樣給他一個Vector 1 屬性來控制Gradient Noise的Scale,這邊先將scale設定為0.1 看起來比較符合真實世界的尺寸。


Step 5. 再來我們來解決Vertex Position,主要是要讓Vertex的Value為 0 跟1 之間,首先新增一個Position Node 並將Space改為 Object,接著新增Normal Vector Node並將Space改為Object,將 Vector Node 串到Multiply的A通道並將 Gradient Noise 串到 Multiply的B通,接著新增一個Add Node 並將 Position Node 串到A通道而剛剛的 Multiply 串到Add的B通道,最後就可以串到 Vertex Position 的輸出了。

接著我們需要一個屬性來控制Normal Hieght,先製作一個Vector 1 屬性串到新增的Multiply B通道,並將剛剛作好的 Multiply 串進來重新串到Add B 通道 ,這樣我們就可以控制Normal Hieght了。

串好Normal以後就可以看到原本平面的Noise變成了有立體感的動態貼圖了。

Step 6 . 因為自然界的雲霧不會這麼單調,所以我們這邊需要另外一個Noise,直接複製原本製作好的 Gradient Noise 以及 Tiling and offset 這兩個Node, Tiling and offset 接收原本Axis Node的UV,而 Gradient Noise 則接收原本建立好的Noise Scale屬性,並新增一個Divide Node串到color。

最後我們還需要調整一下Vertex offset,將先前的 Divide Node 串到Multiply B通道讓 Vertex Position也接收到兩個Noise的資訊。


Step 6. 目前看起來的波動太過smooth,我們需要讓我們的雲看起來更像山峰一樣一團一團可口棉花糖的樣子,這樣才會像雲霧,目前看起來比較像海浪之類的波動。

首先我們先建立一個Vector 4的屬性 Node ,接著利用Split Node分裂出兩個Vector 2的屬性,這邊用Combine Node來作為2個通道的接收器,
第一個Combine – Split R Channel to Combine R Channel
Split G Channel to Combine G Channel
第二個Combine – Split B Channel to Combine R Channel
Split A Channel to Combine G Channel
接著兩個Combine Node 利用RG通道分別連接Remap的In Min Max 以及 Out Min Max通道。

串接好以後我們來做輸出,首先將Absolute Node的out 連接到原本Vertex offset群組裡面的Multiply B 通道,並將 Absolute Node的out 連接到 Unlit Master 的Color 通道。

串接好以後我們回到Scene可以看到整個雲霧比較像山峰的樣子,並且因為有用了Vector 4 的屬性,我們可以直接修改Remap的數值,可以調整整個雲霧的高低差了。

Step 7. 再來我們來製作雲的顏色,因為雲的顏色不是只有一個顏色而已,所以我們首先製作兩個color屬性,分別為Valley 以及 Peak兩種顏色,並新增一個Lerp Node接收A、B兩個通道,接著Lerp T通道則接受 Absolute Node 的Out即可。

儲存好Asset以後,這時候回到Scene調整Color屬性就發現整個雲的顏色可以自由地調整了,我這邊用了比較誇張的顏色看一下兩邊顏色大致上的位置在哪給大家看一下。

Step 8. 因為我們的雲霧一直都是0到1之間的數值,但現在看起來比較像直線的smooth 所以這邊要調整一下這邊的狀況。

首先我們需要一個Smooth step Node來串接,並將 Absolute Node 的輸出到 Smooth step Node 的 In通道,接著我們來做兩個vector 1 屬性來調整Noise Edge,而 Smooth step Node 的輸出一樣要給Vertex offset的Multiply B通道,以及一樣連接到 Unlit Master 的Color 通道。

串接好以後Save Asset 回到Scene 可以調整一下Edge的屬性讓雲霧看起來自然一些。

Step 8. 接著我們需要讓雲霧看起來要更蓬鬆,首先建立一個Power Node ,我們需要可以控制的屬性所以建立一個Vector 1 Node串連到Power B通道,接著要從Noise 那邊的Divide 拉出來串連一個Saturate Node ,這邊 Saturate Node 主要是要讓數值不會因為power Node而超過0、1之間,串接好以後power Node的out串到原本的Remap In通道。

串好以後我們來調整看看Power的屬性調整就可以看到整個蓬鬆度出來了,而且可以調整整個雲霧的power ,看起來是不是越來越像雲了呢?

Step 9. 因為我們的雲有2km這麼大,目前的動態看起來大家都是一致的在運動,所以我們需要一個最基底的Noise來控制整個雲團,首先在新增一個 Gradient Noise 並且一樣給他一個Tiling and Offset ,接著用原本Projection裡面的Rotate About Axis 控制UV,這邊一樣做一個Vector 1 屬性來控制速度,另外則是在做一個 Vector 1 屬性來控制 scale。

然後我們新增一個Add作為媒介,串聯noise mod 的Smooth Step當作A通道,而原本的基底noise先暫時當B通道,接著一樣要改變vertex串到multiply的B通道,因為顏色要跟著原本的color所以串接到colorize裡的Lerp T通道。

這時候可以看到雲霧除了原本個別的以外還多了一個一整個大型的雲霧在波動。

接著我們新增幾個node來控制base Noise 的強度以及combine所有的noise,首先我們先新增一個Vector 1 屬性當作控制強度的Node,在新增一個Add node接收Vector 1 的資訊,接著新增multiply以及add node,這邊的Vector 1 Node一樣要控制新增的 multiply 數值,最後在做一個 Divide當作所有資訊的媒介, Divide 分別連結colorize的Lerp T通道以及 vertex串到multiply的B通道。

這邊可以看到強度的改變

Step 10 . 因為正常的雲在天空上都會有光,但是目前我們的雲看起來是黯淡無光的,所以這邊要給他一個Emission,首先製作一個Vecor 1 屬性當作控Emission的強度,接著做一個Multiply 接收原本Colorize Lerp的輸出,最後將 Multiply 的輸出給Emission即可控制。

回到Scene調整Emission的強度可以發現真的越來越像真實的雲霧了。

稍微做了一點調整後看起來好像還可以,但是雲霧的感覺還是沒有很到位。

小結:
這邊的練習為整個雲霧的基底模型以及貼圖等設定,因為目前的練習還無法讓雲霧看起來像真的霧氣的感覺,下一篇會繼續朝著這個方向前進,另外因為也尚未將skybox以及太陽光的效果調整好,所以目前做出來的是基本的波動以及形狀顏色等等。
Reference: https://www.youtube.com/watch?v=Y7r5n5TsX_E&list=PLVmb_qp6XRczuNNbmr_nSPVUH3OOTrkjB&index=7