Shader Graph -玩壞自定義Node

Shader Graph -玩壞自定義Node

來自專欄 Tech & Art17 人贊了文章

shadergraph 推出大半年了,第一次試用了一下,感覺Bug還很多,比起shader forge ,

unity自帶的graph還在上深階段,對多pass的控制還是很迷,還有很多功能沒有實現 。

一 . 好好玩玩 shader graph

shader graph的教程很多,知乎也有很多,隨便看兩篇就基本熟練了 ,下面我們玩點刺激的。

翻了一下之前在shader toy 上找的什麼簡單的教程看看 。

找到一個不錯的公式

void MyCustomFunction_float(float2 st, float pct, out float Out){ Out = smoothstep( pct-0.02, pct, st.y) - smoothstep( pct, pct+0.02, st.y);}

pct是x軸 ,st是uv 我么取y 軸 : 這是個畫函數線的公式,我們用shader graph 試試連接:

很出奇的,他居然報bug:

很迷 , 所以 :

何不把這個直接封裝成函數呢?

二. 基礎node實現:

然後這篇文章探究一下 Shader Graph 自定義node的實現 ,unity官方有一篇

Shader Graph著色器視圖自定義節點API:Code Function Node?

forum.china.unity3d.com

參考這一篇之後,並做了一些效果 ,讓shader更好玩 ~

基本的實現思路就是,創建一個c#腳本,然後通過反射機制,獲取我們定義的信息,動態生成Shader代碼,作為一個函數,嵌入到原本的shader中,通過shaderGraph源碼,了解到我們原來寫的是CGPROGRAM , 現在換成了 HLSLPROGRAM ,emm 有點意思 。

展示一段pass :

Pass { Tags{"LightMode" = "DepthOnly"} ZWrite On Cull Back ColorMask 0 HLSLPROGRAM // Required to compile gles 2.0 with standard srp library #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma target 2.0 #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment // ------------------------------------- // Material Keywords #pragma shader_feature _ALPHATEST_ON //-------------------------------------- // GPU Instancing #pragma multi_compile_instancing #include "LWRP/ShaderLibrary/InputSurfaceUnlit.hlsl" #include "LWRP/ShaderLibrary/LightweightPassDepthOnly.hlsl" ENDHLSL }

嵌入模板上面的教程也有說,我再簡單總結一下:

unity 通過 GetFunctionToConvert() 介面回調 ,執行一個通過字元串獲取函數名的方法,找到我們要嵌入的代碼

protected override MethodInfo GetFunctionToConvert() { return GetType().GetMethod("MyCustomFunction", BindingFlags.Static | BindingFlags.NonPublic); }

然後這個MyCustomFunction方法就是自己寫了,參數是我么的接入點和接出點了:

static string MyCustomFunction( [Slot(0, Binding.None)] Vector2 st, [Slot(1, Binding.None)] Vector1 pct, [Slot(2, Binding.None)] out Vector1 Out) { return @"{Out = smoothstep( pct-0.02, pct, st.y) - smoothstep( pct, pct+0.02, st.y);}"; }

好了 ,我們再進來 ,創建一個自定義的node,這下就好玩了:

第一個參數找一個uv ,第二個參數傳入 uv的x 就行 :

這就是最基本的 y = x 的函數圖像了。

再試試其他的:

y=sin(x)

因為定義域的原因,顯示不全,我們可以調整他的頻率,

無論是改變坐標,還是調整函數參數,都可以做出我么想要的函數來,函數變得可視化了,

當然,我們也可以做出更多的函數圖像:

三. 把uv坐標變化到極坐標:

我們之前寫過的自定義node,再來寫一次:

傳入一個UV ,傳出一個RA ,R表示長度,A表示角度。

但是,很快我就發現了另一個問題,轉化坐標,中間要求一個中間變數,但是返回值卻只有一條語句:

static string RectToPolarFunction( [Slot(0, Binding.MeshUV0)] Vector2 st, [Slot(1, Binding.None)] out Vector2 Out) { Out = Vector2.zero; return @" { vec2 pos = vec2(0.5,0.5) - st ; Out = float2(length(pos)*2.0,atan2(pos.y,pos.x)); } "; }

但是,這樣寫會報錯,pos未被定義 ??

怎麼辦試了各種寫法,還是沒解決。

臨近崩潰,我想,去github看看unity官方的shader graph源碼 。找了一會兒,還真有

卧槽,這寫法牛壞了啊 :

{precision} f ;

等價於

float f ;

還是unity騷。

我就仿照寫了:

static string RectToPolarFunction( [Slot(0, Binding.MeshUV0)] Vector2 st, [Slot(1, Binding.None)] out Vector2 Out) { Out = Vector2.zero; return @" { {precision}2 pos = {precision}2(0.5,0.5) - st ; Out = float2(length(pos)*2.0,atan2(pos.y,pos.x)); } "; }

還真管用~~

四.在極坐標下畫圖形:

直接傳入uv

這可視化,厲害厲害。。

我們試試簡單的cos函數:

可以控制乘法數量,控制邊的個數:

改改uv坐標,還可以轉起來。

好了,該去睡覺了~

大神與弱雞的區別就是,頭腦里一大推的公式,用到的時候隨手就能拿來~

在此致敬shadertoy上的各位大神~


推薦閱讀:

Unity2018 Shader Graph 學習筆記(三) 使用Fresnel Effect實現邊緣光
Unity2018 Shader Graph 學習筆記(七) 使用法線擾動的基礎水面的實現
Unity2018 Shader Graph 學習筆記(五) 讓UV動起來——UV下的節點以及傳送門效果的實現
ShadeGraph節點詳解1:Artistic Nodes

TAG:Unity遊戲引擎 | shader | 著色器 |