The shader is miraculous,I love it!
本文知識總結於------------Unity Shader 入門精要--馮樂樂
1:
首先看一段代碼:
Shader "Unity Shader Book/Chapter 5/Simple Shader"
{
Properties //不是必有的
{
_MyTexture("Texture (RGB)",2D)="White"{}//圖片形式的屬性
}
SubShader{
Pass
{ Name "FIRST"//設置pass命名
//CGPROGRAM與ENDCG之間是CG代碼
CGPROGRAM
//下面兩句是編譯指令,用來告訴unity哪些是頂點着色器代碼,哪些是片元着色器代碼
#pragma vertex vert
#pragma fragment frag
//:POSITION和:SV_POSITION是CG中的語義,不能省略,用於告知系統用戶輸入輸出值格式
float4 vert(float4 v :POSITION):SV_POSITION
{
return mul (UNITY_MATRIX_MVP,v);//將頂點座標從模空間轉換到裁剪空間中,UNITY_MATRIX_MVP是內置轉換矩陣
}
//SV_Target是一個默認的語義,用於告訴渲染器,把用戶的輸出顏色存儲在幀緩存中
fixed4 frag():SV_Target
{
//這是一個顏色,每一個分量在0-1之間
return fixed4(1.0,1.0,0.5,1.0);
}
ENDCG
}
}
}
首先對程序進行分析:
1:vert函數頂點着色器,是逐頂點執行的。在vert函數中,POSITION相當於告訴unity把模型頂點座標填充到參數v中,而SV_POSITION表示這個函數輸出的是裁剪空間中的頂點座標。這個函數只有一句代碼:作用是將模型頂點座標轉換到裁剪空間中去。
2:frag函數是片元着色器,用於告訴渲染器,把用戶的輸出顏色存儲在幀緩存中。
注意:SV_POSITION是裁剪空間的頂點座標,其中的SV代表系統數值,在渲染流水線中有特殊的含義。(而對於POSITION,COLOR等語義,我們可以存儲任何變量到其修飾的變量中去)用SV_POSITION語義修飾頂點着色器的輸出變量,用系統數值描述的變量是不可以隨便賦值的,渲染引擎會把用SV_POSITION修飾過的變量經過光柵化後在屏幕中進行渲染。其中的UNITY_MATRIX_MVP是:內置模型視圖轉換矩陣,UNITY_MATRIX_MV:內置模型視圖矩陣。
2:
在上面代碼中,我們將模型頂點的位置座標作爲參數傳遞到轉換矩陣函數中,進行轉換,但如果我們想將模型其他的參數(紋理座標,法線座標等),轉換到裁剪空間去,難道在vert函數中設置很多個參數嗎?
不,我們的想法是,構造結構體a2v來存儲模型的屬性值。
代碼如下:
Shader "Unity Shader Book/Chapter 5/Simple Shader"
{
Properties
{
_MyTexture("Texture (RGB)",2D)="White"{}//圖片形式的屬性
_Color("Color Tint",Color)=(1.0,1.0,1.0,1.0)
}
SubShader{
Pass
{
//pass的名字可以在其他地方引用
Name "FIRST"
//CGPROGRAM與ENDCG之間是CG代碼
CGPROGRAM
//下面兩句是編譯指令,用來告訴unity哪些是頂點着色器代碼,哪些是片元着色器代碼
#pragma vertex vert
#pragma fragment frag
struct a2v
{
//模型空間中的頂點位置
float4 vertex :POSITION;
//頂點法線
float3 normal :NORMAL;
//紋理座標,這是用TEXCOORD0描述texcoord變量,TEXCOORD0表示第一組紋理
//unity會識別TEXCOORD0語義將模型的第一組紋理填充到texcoord中
float4 texcoord :TEXCOORD0;
};
//:POSITION和:SV_POSITION是CG中的語義,不能省略,用於告知系統用戶輸入值的格式,輸出值的格式
float4 vert(a2v v):SV_POSITION
{
return mul (UNITY_MATRIX_MVP,v.vertex);//將頂點座標從模空間轉換到裁剪空間中,UNITY_MATRIX_MVP是內置矩陣
}
//SV_Target是一個默認的語義,用於告訴渲染器,把用戶的輸出顏色存儲在幀緩存中
fixed4 frag():SV_Target
{
//這是一個顏色,每一個分量在0-1之間
return fixed4(1.0,1.0,0.5,1.0);
}
ENDCG
}
}
}
自定義結構體定義:struct StructName {
Type Name : Semantic ;
Type Name : Semantic ;
}; 就像這樣:struct v2f
{
float4 pos :SV_POSITION;
fixed3 color :COLOR0;
};
然後我們就可以在函數中通過結構體變量來引用結構體中的數據。如v.vertex。
3:在頂點着色器中我們輸出了法線,紋理座標等數據,而這些數據將輸入到片元着色器中,我們希望將這些數據也封裝到一個結構體中,於是我們定義v2f結構體來存儲頂點着色器的輸出。
代碼如下:
Shader "Unity Shader Book/Chapter 5/Simple Shader"
{
Properties
{
_MyTexture("Texture (RGB)",2D)="White"{}//圖片形式的屬性
_Color("Color Tint",Color)=(1.0,1.0,1.0,1.0)
}
SubShader{
Pass
{
//pass的名字可以在其他地方引用
Name "FIRST"
//CGPROGRAM與ENDCG之間是CG代碼
CGPROGRAM
//下面兩句是編譯指令,用來告訴unity哪些是頂點着色器代碼,哪些是片元着色器代碼
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct a2v
{
//模型空間中的頂點位置
float4 vertex :POSITION;
//頂點法線
float3 normal :NORMAL;
//紋理座標,這是用TEXCOORD0描述texcoord變量,TEXCOORD0表示第一組紋理
//unity會識別TEXCOORD0語義將模型的第一組紋理填充到texcoord中
float4 texcoord :TEXCOORD0;
};
struct v2f
{
float4 pos :SV_POSITION;//pos包含了頂點在裁剪空間中的位置信息
fixed3 color :COLOR0;//COLOR0可以用於存儲顏色信息
};
//:POSITION和:SV_POSITION是CG中的語義,不能省略,用於告知系統用戶輸入值的格式,輸出值的格式
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;
}
//SV_Target是一個默認的語義,用於告訴渲染器,把用戶的輸出顏色存儲在幀緩存中
fixed4 frag(v2f i):SV_Target
{
fixed3 c= i.color;
c *=_Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
v2f實現了頂點着色器與片元着色器之間的通信。
效果截圖: Properties中Texture屬性面板: