在14年年初的時候,曾經給自己定下了今年要實現的三個目標,其中之一就是學會編寫自己的Shader,並能夠投入到實際的項目應用之中。現在,轉眼間日歷已經翻到了6月份,而自己關於Shader的學習,還停留在三天打魚兩天曬網的零碎學習狀態,自己心裡很是著急。平時的工作任務多,擠掉了自己的學習時間是一方面。但更重要的,還是因為自己沒有制定一個穩步的計劃,來監督自己利用一切可以利用的時間完成學習的內容,相反,自己做的太過隨意了。所以,繼續以博文的形式來督促自己的學習,把關於shader學習的點滴都記錄下來,並制定自己的學習進度計劃,在規定的時間節點,必須完成計劃的內容。邁出這一步,算是一個開始——Unity ShaderLab基礎學習記錄。
Unity 使用自定義的ShaderLab來組織Shader的內容,並針對不同的平台進行編譯。在Unity自定義的ShaderLab中,通過SurfaceShader結構封裝了能處理不同的照明及陰影,同時還能在Unity的兩個渲染路徑(Forward和Deferred)下正常工作的極具復雜性的Shader。SurfaceShader的基本結構如下所示:
Shader"Custom/NewShader" {
Properties {
// 一些屬性,Shader的數據接口
}
SubShader {
// SubShader包裝了一個渲染方案,這是我們編寫Shader時的主陣地
}
SubShader {
// SubShader可有多個,這是為了能夠讓我們編寫的Shader適應不同的顯卡
}
FallBack "Diffuse"
}
我們在Properties塊中能夠定義的全部屬性,如下所示:
Properties {
_Texture ("Texture",2D) = "white" {} // 圖片(紋理)形式的屬性
_Color ("Color",Color) = (1, 1, 1, 1) // 顏色屬性
_Cube ("3D Map",Cube) = "white" {} //3D紋理,需要6張圖片
_Vector ("Vector4",Vector) = (1, 1, 1, 1) // 4個元素的向量
_Float ("Float",float) = 1.0 //浮點數
_Range ("Range", range(-10,10)) = 1.0 // 限定范圍的浮點數
}
在Unity的ShaderLab所提供的結構中,Shader的邏輯代碼部分,都位於SubShader中的GLSLPROGRAM—ENDGLSL部分(GLSL語言),或者是CGPROGRAM—ENDCG部分(Cg/HLSL語言),我們可以選擇不同的著色器語言來進行編寫。
以上在Properties塊中定義的屬性,必須在邏輯代碼塊中(即GLSLPROGRAM—ENDGLSL或CGPROGRAM—ENDCG部分)再聲明一次才能使用。它們在Cg代碼中的聲明方式如下:
CGPROGRAM
sampler2D _Texture;
float4 _Color;
samplerCUBE _Cube;
float4 _Vector;
float _Float;
float _Range;
… …
ENDCG
要格外注意的一點是,在Cg代碼塊中聲明的變量名稱必須與Properties塊中變量的名稱保持一致,否則會提示錯誤。
綜上所述,一個SurfaceShader的完整代碼為:
Shader"Custom/NewShader" {
Properties {
_MainTex("Texture",2D) = "white" {} // 圖片(紋理)形式的屬性
}
SubShader {
Tags {"RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inoutSurfaceOutput o) {
half4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
這也是在Unity中創建Shader的默認模板。關於這個默認的Shader模板中的一些內容,我在下一篇記錄中會再進行分析,第一篇就到這裡了: )