Unity Shader 一個最簡單的頂點/片元着色器


Shader "Custom/Chapter5-SimpleShader" {

	SubShader {
		Pass{
			CGPROGRAM

      // 兩條非常重要的編譯指令
			#pragma vertex vert // 定點着色器
			#pragma fragment frag // 片元着色器

      // 這一步是把頂點坐標從模型空間轉換到裁剪空間
			float4 vert(float4 v : POSITION) : SV_POSITION {
				return mul(UNITY_MATRIX_MVP, v);
			}

			fixed4 frag() : SV_Target{
				return fixed4(1.0,1.0,1.0,1.0);
			}

			ENDCG
		}
	}
}

  1. vert , 頂點着色器代碼, 逐頂點執行, 函數的輸入 v 包含了這個頂點的位置, 返回值是該頂點在裁剪空間中的位置, POSITION : 把模型的頂點坐標填充到輸入參數中, SV_POSITION : 頂點着色器的輸出是裁剪空間中的頂點坐標
  2. frag , SV_Target : 把用戶的輸出顏色存儲到一個渲染目標中, 這里將輸出到默認的幀緩存中, 片元着色器輸出的顏色的每個分量范圍是[0,1].

使用結構體來定義頂點着色器的輸入參數

struct a2v {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
};
  • 使用 POSITION 語義得到了模型的頂點位置坐標;
  • 使用 NORMAL 表示是模型空間的法線方向;
  • 使用 TEXCOORD0 表示模型空間的第一套紋理;
SubShader {
		Pass{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

      //  a2v 把數據從應用階段傳到頂點着色器
			struct a2v{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};

			float4 vert(a2v v) : SV_POSITION {
				return mul(UNITY_MATRIX_MVP, v.vertex);
			}

			fixed4 frag() : SV_Target{
				return fixed4(1.0,1.0,1.0,1.0);
			}

			ENDCG
		}
	}

填充到 POSITION / TANGENT / NORMAL 這些語句中的數據是從哪里來的呢? 在 Unity 中, 它們是由使用該材質 Mesh Render 組件提供的, 在每幀調用 Draw Call 的時候, Mesh Render 組件會把它負責渲染的模型數據發送給 Unity Shader.

一個模型通常包括了一組三角面片, 每個三角面片由三個頂點組成, 每個頂點又包含了一些數據, 例如頂點位置 / 法線 / 切線 / 紋理坐標 / 頂點顏色等

頂點着色器和片元着色器之間的通信 #

我們希望從頂點着色器中輸出一些數據傳遞給片元着色器, 比如模型的法線 / 紋理坐標等數據, 這就涉及到頂點/片元着色器之間的通信.
我們可以再定義一個結構體用來定義頂點着色器的輸出

Shader "Custom/Shader002" {

	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 語義告訴 Unity 用於存儲顏色信息
				fixed3 color : COLOR0;
			};

			v2f vert(a2v v) {
				// 生命輸出結構
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				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
		}
	}
}

End.

→ 源碼 GitHub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM