最簡單的Shader:
Shader "Chan/Shader_5_All" {
Properties
{
//面板定義屬性
_Color("Color Tint",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
//定義了頂點着色器函數
//pragma vertex name 一般頂點着色器函數名用vert
#pragma vertex vert
//定義了片元着色器函數
//pragma vertex name 一般頂點着色器函數名用frag
#pragma fragment frag
//在CG代碼中,定義一個屬性名稱和類型都匹配的變量
fixed4 _Color;
//1.爲了訪問模型數據,定義一個數據結構,然後用語義告訴系統,每個值需要用什麼數據填充
//2.這個數據結構作爲頂點着色器的輸入(下邊的a2v v)
//3.語義中的數據由使用了該材質的Mesh Render提供 每幀調用Draw Call時候,Mesh Render會把需要渲染的模型數據發送給Shader
struct a2v
{
//語義獲取模型空間下的頂點
float4 vertex:POSITION;
//語義獲取模型空間下的法線
float3 normal:NORMAL;
//語義獲取模型的第一套紋理座標
float4 texcoord:TEXCOORD0;
};
//定義一個數據結構,用於從頂點着色器傳數據給片元着色器
struct v2f
{
//1.通過語義,知道pos是裁剪空間下的頂點座標數據
//2.必須有SV_POSITION,否則片元着色器得不到頂點座標,無法渲染
float4 pos:SV_POSITION;
//通過語義,知道color變量用於存儲顏色信息
float3 color:COLOR0;
};
//頂點着色器函數名
v2f vert(a2v v)
{
//申明結構(頂點着色器像片元着色器傳遞數據的數據結構)
v2f o;
//Shader內置函數 將頂點座標從模型空間變換到裁剪空間下
o.pos = UnityObjectToClipPos(v.vertex);
//隨便計算一個顏色值,賦值給color
o.color = v.normal * 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
}
}
}
Unity內置包含文件:
路徑 = Unity安裝路勁下的CGIncludes文件夾下。
.cginc文件中定義了一些常用變量和幫助函數。使用#include指令可包含文件,方便使用。
常用包含文件:
文件名 | 描述 |
UnityCG.cginc | 包含了最常用的幫助函數,宏和結構體等 |
UnityShaderVariables.cginc |
在編譯Unity_Shader時,會被自動包含進來,包含了許多內置的全局變量,如 UNITY_MATIRX_MVP等 |
Lighting.cginc | 包含了各種內置的光照模型,如果編寫的是Surface Shader,會自動包含進來 |
HLSLSupport.cginc | 在編譯Unity Shader時,會被自動包含進來,聲明瞭很多用於跨平臺編譯的宏和定義 |
UnityCG.cginc中常用的結構體
名稱 | 描述 | 包含的變量 |
appdata_base | 可用於頂點着色器的輸入 | 頂點位置,頂點法線,第一組紋理座標 |
appdata_tan | 可用於頂點着色器的輸入 | 頂點位置,頂點切線,頂點法線,第一組紋理座標 |
appdata_full | 可用於頂點着色器的輸入 | 頂點位置,頂點切線,頂點法線,四組(或更多)紋理座標 |
appdata_img | 可用於頂點着色器的輸入 | 頂點位置,第一組紋理座標 |
v2f_img | 可用於頂點着色器的輸出 | 裁剪空間中的位置,紋理座標 |
UnityCG.cginc中常用的幫助函數
函數名 | 描述 |
float3 WorldSpaceViewDir(float4 v) | 輸入模型空間中的頂點位置,返回世界空間中從該點到攝像機的觀察方向 |
float3 ObjectSpaceViewDir(float4 v) | 輸入模型空間中的頂點位置,返回模型空間中從該點到攝像機的觀察方向 |
float3 WorldSpaceLightDir(float4 v) | 僅可用於前向渲染中,輸入一個模型空間中的頂點位置,返回世界空間中從該點到光源的光照方向,沒有被歸一化 |
float3 ObjSpaceLightDir(float4 v) | 僅可用於前向渲染中,輸入一個模型空間中的頂點位置,返回模型空間中從該點到光源的光照方向,沒有被歸一化 |
float3 UnityObjectToWorldNormal(float3 norm) | 把法線方向從模型空間轉換到世界空間中 |
float3 UnityObjectToWorldDir(in float3 dir) | 把方向矢量從模型空間變換到世界空間中 |
float3 UnityWorldToObjectDir(float3 dir) | 把方向矢量從世界空間變換到模型空間中 |
CG/HLSL提供的語義:
這些語義告訴Shader該怎麼讀取數據,並把數據輸出到哪。同一個語義在不同的着色器中,含義不盡相同。
例如:在傳遞給頂點着色器的結構體中TEXCOORD0來描述texcoord,Unity會識別TEXCOORD0語義,以把模型的第一組紋理座標填充到texcoord中。如果在頂點着色器傳遞給片元着色器的數據結構體中TEXCOORD0修飾的變量由我們隨便賦值。
DirectX10以後,有了SV開頭的系統數值語義(system value)。SV開頭的語義修飾的變量不能隨便賦值,因爲渲染流水線需要用它們完成特定的目的。
應用階段傳遞模型數據給頂點着色器時,Unity內部賦予某些語義特殊含義:
語義 | 描述 |
POSITION | 模型空間中的頂點位置,通常是float4類型 |
NORMAL | 頂點法線,通常是float3類型 |
TANGENT | 頂點切線,通常是float4類型 |
TEXCOORDn,如TEXCOORD0,TEXCOORD1 | 該頂點的紋理座標,TEXCOORD0表示第一組紋理座標,以此類推,通常是float2或float4類型 |
COLOR | 頂點顏色,通常是fixed4 或 float4類型 |
從頂點着色器傳遞模型數據給片元着色器時,Unity支持的語義
語義 | 描述 |
SV_POSITION | 齊次裁剪空間中的頂點座標,結構體中必須要包含一個用於該語義修飾的變量,等同於DirectX9中的POSITION,但最好使用SV_POSITION(爲了通用性) |
COLOR0 | 通常用於輸出第一組頂點顏色,但不是必需的 |
COLOR1 | 通常用於輸出第二組頂點顏色,但不是必需的 |
TEXCOORD0~TEXCOORD7 | 通常用於輸出紋理座標,但不是必需的 |
除了SV_POSITION,其他都可以任意賦值,比如需要把自定義數據從頂點着色器傳遞給片元着色器,一般選用TEXCOORD0.
片元着色器輸出時,Unity支持的常用語義
語義 | 描述 |
SV_Target | 輸出值將會存儲到渲染目標中(render target),等同於DirectX 9中的COLOR語義,但最好使用SV_Target |