Shader 基礎使用(三) ----- vertex & fragment

基本數據類型與surface一致,就不在此文章贅述了
頂點語義綁定

float4 POSITION 頂點座標位置
float3 NORMAL 頂點法線向量座標
float4 TEXCOORD0 第一個UV座標
float4 TEXCOORD1..N 第二個到第N個UV座標
float4 TENGENT 頂點切線向量座標
float4 COLOR 頂點顏色值

常用函數庫

HLSLSupport.cginc 輔助爲跨平臺的着色器編譯宏和定義
UnityShaderVariables.cginc 常⽤用全局變量量
UnityCG.cginc 常⽤用輔助函數
AutoLight.cginc 光、影函數
Lighting.cginc 光照模型相關
TerrainEngine.cginc 地形植被輔助

首先我們應該知道頂點片段着色器的基本框架

Shader "MyVFShader/VFShader_001" 
{
    Properties
    {
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
                //預編譯指令關鍵詞  |  函數類型  |  函數名
                #pragma vertex vert  //vertex 是頂點着色器
                #pragma fragment frag // fragment 是片段着色器
                void vert(){}
                void frag(){}
            ENDCG
        }
    }
}

接下來先來用頂點片段着色器寫一個純色的Shader

Shader "MyVFShader/VFShader_002" 
{
    Properties
    {
        _MainColor("顏色",Color) = (1,1,1,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
                //預編譯指令關鍵詞  |  函數類型  |  函數名
                #pragma vertex vert  //vertex 是頂點着色器
                #pragma fragment frag // fragment 是片段着色器
                //輸入一個頂點座標 名稱vertexPos 語義綁定POSITION
                //輸出一個像素座標 語義綁定SV_POSITION
                float4 vert(float4 vertexPos:POSITION):SV_POSITION
                {
                    //老版本寫法(Model View Project矩陣變幻,得到每個像素的座標位置)
                    return UnityObjectToClipPos(vertexPos);
                    //新版本寫法UnityObjectToClipPos(頂點座標)
                    return UnityObjectToClipPos(vertexPos);
                }
                float4 _MainColor;
                //無輸入 輸出內插值顏色
                float4 frag():COLOR
                {
                    return _MainColor;
                }
            ENDCG
        }
    }
}

/*
我們來說一下步驟和思路 做一個總結

首先看頂點函數
1.參數 --> 每個頂點的座標位置 語義綁定是POSITION 類型是float4
2.返回值 --> 每個頂點的像素位置 語義綁定是SV_POSITION 類型是float4
3.頂點函數的作用:就是將三維空間座標投影到二維窗口
然後看片段函數
1.參數 --> 片段函數沒有參數
2.返回值 --> 片段的顏色值 語義綁定COLOR 類型是float4
3.片段函數的作用:就是給片段顏色賦值,也就是設置片段顏色
*/

如果感覺純色的太侷限了 我們來寫一下彩色的看看效果

Shader "MyVFShader/VFShader_003" 
{
    Properties
    {
        //_ColorOffset("顏色偏移量",Range(0,1)) = 0.5
        _ROffset("紅色偏移量",Range(0,1)) = 0
        _GOffset("綠色偏移量",Range(0,1)) = 0
        _BOffset("藍色偏移量",Range(0,1)) = 0
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
                //預編譯指令關鍵詞  |  函數類型  |  函數名
                #pragma vertex vert  //vertex 是頂點着色器
                #pragma fragment frag // fragment 是片段着色器
                //頂點輸出的結構體
                struct V2F 
                {
                    //像素座標
                    float4 position:POSITION;
                    //0級紋理座標(可以理解爲像素的顏色)
                    float4 color:TEXCOORD0;
                };

                float _ROffset;
                float _GOffset;
                float _BOffset;
                //頂點函數
                //輸入一個頂點座標 名稱vertexPos 語義綁定POSITION
                V2F vert(float4 vertexPos:POSITION)
                {
                    //聲明結構體
                    V2F v2f;
                    //通過頂點座標求像素座標
                    v2f.position = UnityObjectToClipPos(vertexPos);
                    //頂點座標當做顏色值設置成像素顏色
                    //通過紅,綠,藍三個顏色的偏移量來修改顏色的變化
                    v2f.color = vertexPos + float4(_ROffset,_GOffset,_BOffset,0);
                    //返回
                    return v2f;
                }   
                //片段函數
                float4 frag(V2F v2f):COLOR
                {
                    return v2f.color;
                }
            ENDCG
        }
    }
}


/*
我們來說一下步驟和思路 做一個總結

頂點着⾊色器器輸出結構體
1.float4 postion:SV_POSITION 空間位置 
2.float4 color:TEXCOORD0 0級紋理理座標
首先看頂點函數
1.參數 --> 每個頂點的座標位置 語義綁定是POSITION 類型是float4
2.返回值 --> 輸出結構體
3.頂點函數的作用:將三維空間座標投影到⼆維口,顏⾊值設置爲頂點座標+偏移量(營造彩虹效果)
然後看片段函數
1.參數 --> 頂點着⾊器輸出結構體 
2.返回值 --> 片段的顏色值 語義綁定COLOR 類型是float4
3.片段函數的作用:直接將頂點輸出的顏色設置到片段顯示
*/

由淺至深的 接下來 我們看一下頂點片段着色器的漫反射應該怎樣實現

Shader "MyVFShader/VFShader_004" 
{
    Properties
    {
        _Color("顏色",Color) = (1,0,0,1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
                #pragma vertex ver
                #pragma fragment frag
                //引用庫
                #include "UnityCG.cginc"
                //聲明外部顏色變量
                float4 _Color;
                //聲明內部光照顏色變量
                float4 _LightColor0;
                //頂點函數輸入結構體
                struct appData
                {
                    //頂點座標
                    float4 vertexPos:POSITION;
                    //頂點法線
                    float3 normal:NORMAL;
                };

                struct V2F
                {
                    //像素座標
                    float4 position:SV_POSITION;
                    //像素法線
                    float3 normal:NORMAL;
                };
                //頂點函數
                V2F ver(appData data)
                {
                    //定義輸出結構體
                    V2F v2f;
                    //座標系轉換
                    v2f.position = UnityObjectToClipPos(data.vertexPos);
                    //從頂點法線 到 像素法線
                    v2f.normal = mul(float4(data.normal,0),unity_WorldToObject).xyz;
                    //返回
                    return v2f;
                }
                //片段函數
                float4 frag(V2F v2f):COLOR
                {
                    //求法線的單位向量
                    float3 v2fnormal = normalize(v2f.normal);
                    //求入射光的單位向量 _WorldSpaceLightPos0內部函數
                    float3 lnormal = normalize(_WorldSpaceLightPos0.xyz);
                    //逆向光公式:Diffuse=LightColor * MainColor * max(0,dot(N,L)) 
                    //正向光公式:Diffuse=LightColor * MainColor * -min(0,dot(N,L))
                    float3 diffuse = _LightColor0 * _Color * -min(0,dot(v2fnormal,lnormal));
                    //添加環境光
                    float4 newDiffuse = float4(diffuse,0) + UNITY_LIGHTMODEL_AMBIENT;
                    //返回顏色值
                    return newDiffuse;
                }
            ENDCG
        }
    }

    FallBack "Diffuse"
}


/*
我們來說一下步驟和思路 做一個總結

第一步
1.引入庫 #include “UnityCG.cginc”
頂點着色器輸入結構體
1.頂點位置 語義綁定POSITION  類型float4
2.法線 語義綁定NORMAL 類型float3
頂點着⾊器輸出結構體
1.像素位置 語義綁定SV_POSITION 類型float4 
2.法線 語義綁定NORMAL 類型float3
全局變量聲明
1.光照顏色 內部值 _LightColor0 類型float4
2.漫反射顏色 屬性值  自己定義
首先看頂點函數
1.參數 --> 輸入結構體
2.返回值 --> 輸出結構體
3.步驟:
    1.矩陣變幻
    2.計算法線
        1).輸入法線擴充 : float4(input.normal, 0.0) 
        2).內部值 : unity_WorldToObject 
        3).法線計算 : mul(float4(input.normal, 0.0), unity_WorldToObject).xyz
然後看片段函數
1.參數 --> 頂點着⾊器輸出結構體 
2.返回值 --> 片段的顏色值 語義綁定COLOR 類型是float4
3.步驟:
    1.獲取輸入法線方向(float3) normalize(input.normal)
    2.獲取入射光法線方向(float3)normalize(_WorldSpaceLightPos0.xyz)
    3.計算漫反射值
        1).逆向光公式:Diffuse=LightColor * MainColor * max(0,dot(N,L)) 
        2).正向光公式:Diffuse=LightColor * MainColor * -min(0,dot(N,L))
           i).LightColor 光照顏⾊色 
           ii).MainColor 漫反射顏⾊色 
           iii).N 輸⼊入法線
           iiii).L 光照法線
    4.合併環境光
        1).漫反射擴充 float4(diffuse, 1.0) 
        2).添加環境光 + UNITY_LIGHTMODEL_AMBIENT
    5.返回結果 片段顏色
*/

Shader就先介紹這麼多了,感謝大家的支持, 如果有人想要深入的研究,可以給我評論留言,我們一起討論研究!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章