unity shader學習筆記(十四)——Unity中的複雜光照之光源類型

光源類型

  Unity中共有四種光源,平行光點光源聚光燈面光源。面光源僅在烘焙是纔可發揮作用。最常使用的光源屬性有光源的位置方向顏色強度以及衰減這5個屬性。
  

平行光

  平行光的幾何定義是最簡單的,它可以照亮的範圍是沒有限制的,通常作爲太陽的角色在場景中出現。它的特點就是沒有一個唯一的位置,只有方向。同時也沒有衰減,就是光照強度不會隨着距離的變化而變化。
  

點光源

  點光源的照亮空間是有限的,它由空間中的一個球體定義,表示由一個點發出的、向所有方向延伸的光。點光源是有位置屬性。它的方向屬性用點光源的位置減去某點位置來計算。點光源也是會衰減的,球心出最強,球體邊界處最弱,值爲0。
  

聚光燈

  聚光燈是這三種光源中最複雜的,它的照亮空間也是有限的,是由空間中的一塊錐形區域定義的。它可以表示由一個特定位置出發、向特定方向延伸的光。它有位置屬性和方向屬性,方向屬性計算方式和點光源一樣,衰減也是隨着物體與光源的距離變化而變化,只不過計算方式更加複雜,需要計算是否在錐體內。
  

前向渲染中的光源類型

  下面是在Unity中訪問光源屬性的shader示例:

Properties
{
    _Diffuse("Diffuse", Color) = (1.0, 1.0, 1.0, 1.0)
    _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
    _Gloss("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
    Pass
    {
        Tags{ "LightMode" = "ForwardBase" }

        CGPROGRAM
        #pragma multi_compile_fwdbase
        #pragma vertex vert
        #pragma fragment frag
        #include "Lighting.cginc"

        fixed4 _Diffuse;
        fixed4 _Specular;
        float _Gloss;

        struct a2v
        {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
        };

        struct v2f
        {
            float4 position : SV_POSITION;
            float3 worldNormal : TEXCOORD0;
            float3 worldPos : TEXCOORD1;
        };


        v2f vert(a2v a)
        {
            v2f v;
            v.position = UnityObjectToClipPos(a.vertex);

            //把法線轉化爲世界座標下的法線
            v.worldNormal = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
            v.worldNormal = normalize(UnityObjectToWorldNormal(a.normal));  //unity 內置函數實現

            //把頂點座標轉化爲世界座標
            v.worldPos = normalize(mul(unity_ObjectToWorld, a.vertex));

            return v;
        }

        fixed4 frag(v2f a) : SV_Target
        {
            //環境光
            fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

            //光照
            fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
            worldLight = normalize(UnityWorldSpaceLightDir(a.worldPos));  //unity 內置函數實現

            //漫反射光
            fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(a.worldNormal, worldLight));

            //攝像機方向
            fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - a.worldPos.xyz);
            viewDir = normalize(UnityWorldSpaceViewDir(a.worldPos));  //unity 內置函數實現

            //反射光
            //fixed3 reflectDir = normalize(reflect(-worldLight, a.worldNormal));
            //入射光和攝像機方向的中間向量
            fixed3 halfDir = normalize(worldLight + viewDir);

            //高光反射
            fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(a.worldNormal, halfDir)), _Gloss);

            //光照衰減值
            fixed atten = 1.0;

            //顏色
            fixed3 color = ambient + (diffuse + specular) * atten;

            return fixed4(color, 1.0);
        }
        ENDCG
    }

    Pass
    {
        Tags { "LightMode" = "ForwardAdd" }

        Blend One One

        CGPROGRAM

        #pragma multi_compile_fwdadd
        #pragma vertex vert
        #pragma fragment frag
        #include "Lighting.cginc"
        #include "Autolight.cginc" 

        fixed4 _Diffuse;
        fixed4 _Specular;
        float _Gloss;

        struct a2v
        {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
        };

        struct v2f
        {
            float4 position : SV_POSITION;
            float3 worldNormal : TEXCOORD0;
            float3 worldPos : TEXCOORD1;
        };


        v2f vert(a2v a)
        {
            v2f v;
            v.position = UnityObjectToClipPos(a.vertex);

            //把法線轉化爲世界座標下的法線
            v.worldNormal = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
            v.worldNormal = normalize(UnityObjectToWorldNormal(a.normal));  //unity 內置函數實現

                                                                            //把頂點座標轉化爲世界座標
            v.worldPos = normalize(mul(unity_ObjectToWorld, a.vertex));

            return v;
        }

        fixed4 frag(v2f a) : SV_Target
        {
            //環境光
            fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

            //光照
            #ifdef USING_DIRECTIONAL_LIGHT
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
            #else
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz - a.worldPos.xyz);
            #endif

                                                                          //漫反射光
            fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(a.worldNormal, worldLight));

            //攝像機方向
            fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - a.worldPos.xyz);
            viewDir = normalize(UnityWorldSpaceViewDir(a.worldPos));  //unity 內置函數實現

            //入射光和攝像機方向的中間向量
            fixed3 halfDir = normalize(worldLight + viewDir);

            //高光反射
            fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(a.worldNormal, halfDir)), _Gloss);

            //光照衰減值
            #ifdef USING_DIRECTIONAL_LIGHT
                fixed atten = 1.0;
            #else
                float3 lightCoord = mul(unity_WorldToLight, float4(a.worldPos, 1)).xyz;
                fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
            #endif

            //顏色
            fixed3 color = ambient + (diffuse + specular) * atten;

            return fixed4(color, 1.0);
        }
        ENDCG
    }
}
FallBack "Specular"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章