Shaderlab Notizen 14 Specular(鏡面反射)Shader

一.Specular Shader
源碼如下:

//鏡面反射Shader(specular shader )  

Shader "Shader/Specular"  
{  
    //------------------------------------【屬性值】------------------------------------  
    Properties  
    {  
        //主顏色  
        _Color("Main Color", Color) = (1, 1, 1, 1)  
        //鏡面反射顏色  
        _SpecColor("Specular Color", Color) = (1, 1, 1, 1)  
        //鏡面反射光澤度  
        _SpecShininess("Specular Shininess", Range(1.0, 100.0)) = 10.0  
    }  

    //------------------------------------【唯一的子著色器】------------------------------------  
    SubShader  
    {  
        //渲染類型設置:不透明  
        Tags{ "RenderType" = "Opaque" }  

        //--------------------------------唯一的通道-------------------------------  
        Pass  
        {  
            //光照模型ForwardBase  
            Tags{ "LightMode" = "ForwardBase" }  
            //===========開啟CG著色器語言編寫模塊===========  
            CGPROGRAM  

            //編譯指令:告知編譯器頂點和片段著色函數的名稱  
            #pragma vertex vert  
            #pragma fragment frag  

            //頂點著色器輸入結構  
            struct appdata  
            {  
                float4 vertex : POSITION;//頂點位置  
                float3 normal : NORMAL;//法線向量坐標  
            };  

            //頂點著色器輸出結構  
            struct v2f  
            {  
                float4 pos : SV_POSITION;//像素位置  
                float3 normal : NORMAL;//法線向量坐標  
                float4 posWorld : TEXCOORD0;//在世界空間中的坐標位置  
            };  

            //變量的聲明  
            float4 _LightColor0;  
            float4 _Color;  
            float4 _SpecColor;  
            float _SpecShininess;  

            //--------------------------------【頂點著色函數】-----------------------------  
            // 輸入:頂點輸入結構體  
            // 輸出:頂點輸出結構體  
            //---------------------------------------------------------------------------------  
            //頂點著色函數  
            v2f vert(appdata IN)  
            {  
                //【1】聲明一個輸出結構對象  
                v2f OUT;  

                //【2】填充此輸出結構  
                //輸出的頂點位置為模型視圖投影矩陣乘以頂點位置,也就是將三維空間中的坐標投影到了二維窗口  
                OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex);  
                //獲得頂點在世界空間中的位置坐標  
                OUT.posWorld = mul(_Object2World, IN.vertex);  
                //獲取頂點在世界空間中的法線向量坐標  
                OUT.normal = mul(float4(IN.normal, 0.0), _World2Object).xyz;  

                //【3】返回此輸出結構對象  
                return OUT;  
            }  

            //--------------------------------【片段著色函數】-----------------------------  
            // 輸入:頂點輸出結構體  
            // 輸出:float4型的像素顏色值  
            //---------------------------------------------------------------------------------  
            fixed4 frag(v2f IN) : COLOR  
            {  
                //【1】先準備好需要的參數  
                //獲取法線的方向  
                float3 normalDirection = normalize(IN.normal);  
                //獲取入射光線的方向  
                float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);  
                //獲取視角方向  
                float3 viewDirection = normalize(_WorldSpaceCameraPos - IN.posWorld.xyz);  

                //【2】計算出漫反射顏色值  Diffuse=LightColor * MainColor * max(0,dot(N,L))  
                float3 diffuse = _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection));  

                //【3】計算鏡面反射顏色值   
                float3 specular;  
                //若是法線方向和入射光方向大于180度,鏡面反射值為0  
                if (dot(normalDirection, lightDirection) < 0.0)  
                {  
                    specular = float3(0.0, 0.0, 0.0);  
                }  
                //否則,根據公式進行計算 Specular =LightColor * SpecColor *pow(max(0,dot(R,V)),Shiness),R=reflect(-L,N)  
                else  
                {  
                    float3 reflectDirection = reflect(-lightDirection, normalDirection);  
                        specular = _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(reflectDirection, viewDirection)), _SpecShininess);  
                }  

                //【4】合并漫反射、鏡面反射、環境光的顏色值  
                float4 diffuseSpecularAmbient = float4(diffuse, 1.0) + float4(specular, 1.0) + UNITY_LIGHTMODEL_AMBIENT;  

                //【5】將漫反射-鏡面反射-環境光的顏色值返回  
                return diffuseSpecularAmbient;  
            }  

            //===========結束CG著色器語言編寫模塊===========  
            ENDCG  
        }  
    }  
}

二、帶紋理載入的Specular Shader
源碼如下:

//支持紋理載入的specular shader  

Shader "Shader/Specular with Shader"  
{  
    //------------------------------------【屬性值】------------------------------------  
    Properties  
    {  
        //主紋理  
        _MainTex("Texture", 2D) = "white" {}  
        //主顏色  
        _Color("Main Color", Color) = (1, 1, 1, 1)  
        //鏡面反射顏色  
        _SpecColor("Specular Color", Color) = (1, 1, 1, 1)  
        //鏡面反射光澤度  
        _SpecShininess("Specular Shininess", Range(1.0, 100.0)) = 10.0  
    }  

    //------------------------------------【唯一的子著色器】------------------------------------  
    SubShader  
    {  
        //渲染類型設置:不透明  
        Tags{ "RenderType" = "Opaque" }  

        //--------------------------------唯一的通道-------------------------------  
        Pass  
        {  
            //光照模型ForwardBase  
            Tags{ "LightMode" = "ForwardBase" }  
            //===========開啟CG著色器語言編寫模塊===========  
            CGPROGRAM  

            //編譯指令:告知編譯器頂點和片段著色函數的名稱  
            #pragma vertex vert  
            #pragma fragment frag  

            //頂點著色器輸入結構  
            struct appdata  
            {  
                float4 vertex : POSITION;//頂點位置  
                float3 normal : NORMAL;//法線向量坐標  
                float2 texcoord : TEXCOORD0;//一級紋理坐標  
            };  

            //頂點著色器輸出結構  
            struct v2f  
            {  
                float4 pos : SV_POSITION;//像素位置  
                float3 normal : NORMAL;//法線向量坐標  
                float2 texcoord : TEXCOORD0;//一級紋理坐標  
                float4 posWorld : TEXCOORD1;//在世界空間中的坐標位置  
            };  

            //變量的聲明  
            float4 _LightColor0;  
            float4 _Color;  
            sampler2D _MainTex;  
            float4 _SpecColor;  
            float _SpecShininess;  

            //--------------------------------【頂點著色函數】-----------------------------  
            // 輸入:頂點輸入結構體  
            // 輸出:頂點輸出結構體  
            //---------------------------------------------------------------------------------  
            //頂點著色函數  
            v2f vert(appdata IN)  
            {  
                //【1】聲明一個輸出結構對象  
                v2f OUT;  

                //【2】填充此輸出結構  
                //輸出的頂點位置為模型視圖投影矩陣乘以頂點位置,也就是將三維空間中的坐標投影到了二維窗口  
                OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex);  
                //獲得頂點在世界空間中的位置坐標  
                OUT.posWorld = mul(_Object2World, IN.vertex);  
                //獲取頂點在世界空間中的法線向量坐標  
                OUT.normal = mul(float4(IN.normal, 0.0), _World2Object).xyz;  
                //輸出的紋理坐標也就是輸入的紋理坐標  
                OUT.texcoord = IN.texcoord;  

                //【3】返回此輸出結構對象  
                return OUT;  
            }  

            //--------------------------------【片段著色函數】-----------------------------  
            // 輸入:頂點輸出結構體  
            // 輸出:float4型的像素顏色值  
            //---------------------------------------------------------------------------------  
            fixed4 frag(v2f IN) : COLOR  
            {  
                //【1】先準備好需要的參數  
                //獲取紋理顏色  
                float4 texColor = tex2D(_MainTex, IN.texcoord);  
                //獲取法線的方向  
                float3 normalDirection = normalize(IN.normal);  
                //獲取入射光線的方向  
                float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);  
                //獲取視角方向  
                float3 viewDirection = normalize(_WorldSpaceCameraPos - IN.posWorld.xyz);  

                //【2】計算出漫反射顏色值  Diffuse=LightColor * MainColor * max(0,dot(N,L))  
                float3 diffuse = _LightColor0.rgb * _Color.rgb * max(0.0, dot(normalDirection, lightDirection));  

                //【3】計算鏡面反射顏色值  
                float3 specular;  
                //若是法線方向和入射光方向大于180度,鏡面反射值為0  
                if (dot(normalDirection, lightDirection) < 0.0)  
                {  
                    specular = float3(0.0, 0.0, 0.0);  
                }  
                //否則,根據公式進行計算 Specular =LightColor * SpecColor *pow(max(0,dot(R,V)),Shiness),R=reflect(-L,N)  
                else  
                {  
                    float3 reflectDirection = reflect(-lightDirection, normalDirection);  
                    specular = _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(reflectDirection, viewDirection)), _SpecShininess);  
                }  

                //【4】合并漫反射、鏡面反射、環境光的顏色值  
                float4 diffuseSpecularAmbient = float4(diffuse, 1.0) + float4(specular, 1.0) + UNITY_LIGHTMODEL_AMBIENT;  

                //【5】將漫反射-鏡面反射-環境光的顏色值乘以紋理顏色值之后返回  
                return diffuseSpecularAmbient * texColor;  
            }  

            //===========結束CG著色器語言編寫模塊===========  
            ENDCG  
        }  
    }  
}  
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容