在沒有接觸Unity3D Shader 之前,總感覺shader特別神奇,因為聽說是對渲染流水線進行編程,就是對GPU進行編程。聽着特別高大上。這不,最近剛剛接觸Shader,學了幾個小案例,然后本文作為學習筆記將這個小案例的實現記錄下來。
筆者也是剛開始學習shader 沒幾天。在剛開始學shader 的時候,剛覺shader好難,面對shader一些奇怪的語法和一些語義,有點讓人頭疼。學着感覺一頭霧水,因為在學一些小案例之前還需要學習(復習)一些數學知識,因為涉及到坐標空間的轉換,所以看了很多矩陣運算和其他的一些數學知識。
我想很多學shader的人和我一樣吧,剛開始接觸shader的時候,發覺好難,我覺是因為沒有實現過一些小案例,所以讓shader披上了一層神秘的面紗。等實現了一些小案例就會發現,原來這東東是這樣玩的···
接下來我們就來實現一個小案例,效果如下圖:
然后來看看實現這種效果的過程
1.首先我們先建立一個測試項目,然后創建一個material(材質) 和 shader ,在場景中創建一個球體和膠囊體。
2.把創建的shader賦給材質:
3.接下來就打開編輯器對shader進行編輯。
在此之前我們先來簡單了解以下shader框架
Shader "Custom/myshader"{ Properties { // 屬性 } Subshader { // 用於實現效果 } }
簡單了解過后,我們在Properties區域添加我們所需要的屬性
Properties { _Color("Base Color",color)=(1,1,1,1) _MainTex("Base(RGB)",2D) = "white"{} }
屬性將會顯示在材質的屬性面板上,我們就可以通過面板對上面兩個屬性進行值的變換。為了讓美術和程序員合作,在shader中屬性的定義就是作為一個接口,程序員定義這個接口讓美術來調節渲染效果。
然后來看shader的核心部分,Subshader
Subshader { Tags{"Queue" = "transparent" "RenderType" = "transparent" "IgoreProjector" = "true" } // 定義渲染所需要的一些標簽,讀者可以去查閱其他資料進行了解,在此不再累述 Blend SrcAlpha oneMinusSrcAlpha // 混合 pass // 渲染通道 注:一個Subshader里可以有多個pass { CGPROGRAM // 開始CG代碼 #pragma vertex vert // 重點,對頂點vert函數進行聲明 #pragma fragment frag // 對片元frag函數進行聲明 #include "UnityCG.cginc" // 引入需要的文件(就像C++語言里的include一樣) sampler2D _MainTex; // 變量名稱要和properties中的變量名稱相同,這個變量就有值了。 float4 _Color; // 同上 struct v2f // 結構體的定義是為了 vert 到 frag 的過度 { float4 pos : POSITION; float4 uv : TEXCOORD; float4 col :COLOR; }; v2f vert(appdata_base v) // appdata_base 來自於UnityCG.cginc { v2f o; o.pos = UnityObjectToClipPos(v.vertex); // 坐標空間的轉換 o.uv = v.texcoord; o.col.xyz = v.normal*0.5+0.5; // 法線的取值范圍是-1到1 所以先乘0.5讓范圍到-0.5到0.5 ,在加上0.5,就符合顏色的取值范圍了。 o.col.w = 1.0; return o; } half4 frag(v2f i) :COLOR { half4 h = i.col; // 賦值顏色 return h; } ENDCG // 結束CG代碼 }
寫的很簡要,不過對於對shader有一小點了解的讀者來說可以理解了。
以下是完整源碼:
Shader "Custom/myshader"{ Properties { _Color("Base Color",color)=(1,1,1,1) _MainTex("Base(RGB)",2D) = "white"{} } Subshader { Tags{"Queue" = "transparent" "RenderType" = "transparent" "IgoreProjector" = "true" } Blend SrcAlpha oneMinusSrcAlpha pass { Cull off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float4 _Color; struct v2f { float4 pos : POSITION; float4 uv : TEXCOORD; float4 col :COLOR; }; v2f vert(appdata_base v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.texcoord; o.col.xyz = v.normal*0.5+0.5; o.col.w = 1.0; return o; } half4 frag(v2f i) :COLOR { half4 h = i.col; return h; } ENDCG } } }