?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上的各位大神~
推薦閱讀: