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"

你可能感兴趣的:(UnityShader学习笔记)