Shader5-簡單的Shader & Unity內置文件和變量 & CG語義

最簡單的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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章