Unity Shader入門教程(二) :實現頂點和片元著色器之間的通訊
阿新 • • 發佈:2018-12-15
這篇文章將介紹Pass{}內的程式碼的編寫。我們先看如下Unity Shader程式碼:(此文部分採自《unity shader入門精要》)
關於頂點著色器和片元著色器不懂的學習可以自行搜尋概念的意思,這裡就不介紹了。
Shader "Custom/myTest" { SubShader { Pass{ CGPROGRAM //申明頂點著色器函式 #pragma vertex vert //申明片元著色器函式 #pragma fragment frag //使用一個結構體來定義頂點著色器的輸入 struct a2v{ //POSITION語義告訴Unity,用模型空間的頂點座標填充vertex變數 float4 vertex : POSITION; //NORMAL語義告訴Unity,用模型空間的法向量方向填充normal變數 float3 normal : NORMAL; //TEXCOORD0語義告訴Unity,用模型的第一套紋理座標填充texcoord變數 float4 texcoord : TEXCOORD0; }; //如果沒有自定義的結構體,則可寫成float4 vert(float4 v : POSITION) : SV_POSITION float4 vert(a2v v) : SV_POSITION{ //使用v.vertex來訪問模型空間的頂點座標 return UnityObjectToClipPos(v.vertex); } float4 frag() : SV_Target{ return fixed4(1.0, 1.0, 1.0, 1.0); //fixed4(r, g, b, a),取值範圍為[0,1] } ENDCG } } FallBack "Diffuse" }
其中POSITION、NORMAL等大寫的語義代表CG/HLSL語義,告訴GPU以怎樣的方式進行渲染。該程式碼就表示了頂點/片元著色器以怎樣的方式進行渲染。然而在實踐中,我們往往希望從頂點著色器輸出一些資料,例如把模型的法線、紋理座標等傳遞給片元著色器,這就需要再定義一個新的結構體。修改後程式碼如下:
Shader "Custom/myTest" { SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag struct a2v{ float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; //使用一個結構體來定義頂點著色器的輸出 struct v2f{ //SV_POSITION語義告訴Unity,pos裡面包含了頂點在裁切空間中的位置資訊 float4 pos : SV_POSITION; //COLOR0語義可以用於儲存顏色資訊 fixed3 color : COLOR0; }; v2f vert(a2v v){ v2f o; o.pos = UnityObjectToClipPos(v.vertex); //v.normal包含了頂點的法線方向,其分量範圍在[-1.0,1.0] //下面的程式碼把分量範圍對映到了[0.0, 1.0] //儲存到o.color中傳遞給片元著色器 o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5); return o; } fixed4 frag(v2f i) : SV_Target{ //將插值後的i.color顯示到螢幕上 return fixed4(i.color, 1.0); } ENDCG } } FallBack "Diffuse" }
在上面程式碼中,頂點著色器的輸出結構中,必須包含一個變數,它的語義是SV_POSITION。否則,渲染器將無法得到裁切空間中的頂點座標,也就無法將頂點渲染到螢幕上。COLOR0語義中的資料則可以由使用者自己定義,但一般是儲存顏色。