简单光照模型(Phong模型(镜面反射)与 Blinn-Phong光照模型(修正镜面光) )

时间:2021-07-14 04:12:56

Phong模型认为镜面反射的光强与反射光线和视线的夹角相关:
计算公式为:R + L = 2 * dot(N, L) * N 即 R = 2 * dot(N,L) * N - L
简单光照模型(Phong模型(镜面反射)与 Blinn-Phong光照模型(修正镜面光) )

光源发出灯光,在材质表面反射,材质决定吸收灯光的什么分量和反射什么分量,而材质本身是不具有颜色的!在现实世界中,我们看到的物体颜色不是属于物体的,而是光与其作用后反射的。代码和效果图如下:
简单光照模型(Phong模型(镜面反射)与 Blinn-Phong光照模型(修正镜面光) )

Shader "Sbin/MySpecularFrag"
{
 properties
   {
      _SpecularColor("Specular",color)=(1,1,1,1)
      _Shininess("Shininess",range(1,32))=8
   }

    SubShader
    {

        Pass
        {
            tags{"LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma multi_compile_fwdbase
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            #include "lighting.cginc"
              float4 _SpecularColor;
              float  _Shininess;


            struct v2f
            {
            float4 pos:POSITION;
            float3 normal:TEXCOORD0;
            float4 vertex:COLOR;  
            };

            v2f  vert(appdata_base v)
            {
             v2f o;
             o.pos= mul(UNITY_MATRIX_MVP,v.vertex);
            o.normal=v.normal;
            o.vertex=v.vertex;

            return o;
              }

            fixed4 frag(v2f IN):COLOR
            {//ambient color
            fixed4 col= UNITY_LIGHTMODEL_AMBIENT;
            //diffuse color
            // dot(n,l)
             float3 N=UnityObjectToWorldNormal(IN.normal);
             float3 L=normalize(WorldSpaceLightDir(IN.vertex));
             float diffuseScale=saturate(dot(N,L));
             col+=_LightColor0*diffuseScale;
             //specular color
             float3 V=normalize(WorldSpaceViewDir(IN.vertex));
             float3 R=2*dot(N,L)*N-L;
             float specularScale=saturate(dot(R,V));
             col+=_SpecularColor*pow(specularScale,_Shininess);
             return col; 

             }
            ENDCG
        }
    }
}

Blinn-phong光照模型。
它是以Phong模型为基础的,效果是能让高光更加柔和,更平滑。其实这个模型的效果并不比Phong模型 高级,使用blinn-phong 进行光照渲染,在同样的高光系数下,高光领域覆盖范围较大,明暗界限不明显。所以它真实感还没Phong模型强。但是这个模型运算速度要快些。因此在DX中默认的高光模型就是它。Blinn-phong光照模型公式为:H = (L + V) / |L + V| ),其中N是入射点的单位法向量,H是光入射方向L和视点方向V的中间向量,通常也称之为半角向量(半角向量被广泛用于各类光照模型,原因不但在于半角向量蕴含的信息价值,也在于半角向量是很简单的计算。镜面高光由n和h的夹角决定如图所示:
简单光照模型(Phong模型(镜面反射)与 Blinn-Phong光照模型(修正镜面光) )

代码及效果图如下:

Shader "Sbin/MySpecular"
{
   properties
   {
      _SpecularColor("Specular",color)=(1,1,1,1)
      _Shininess("Shininess",range(1,64))=8
   }

    SubShader
    {

        Pass
        {
            tags{"LightMode"="ForwardBase"}

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


           float4 _SpecularColor;
           float  _Shininess;
            struct v2f
            {
            float4 pos:POSITION;
            float4 color:COLOR;

            };

            v2f  vert(appdata_base v)
            {
             v2f o;   
             o.pos= mul(UNITY_MATRIX_MVP,v.vertex);



            float3 L=normalize(WorldSpaceLightDir(v.vertex));
            float3 N=UnityObjectToWorldNormal(v.normal);
            float3 V=normalize(WorldSpaceViewDir(v.vertex));

            //Ambient Color
            o.color=UNITY_LIGHTMODEL_AMBIENT ;
            // Diffuse Color
            float ndotl=saturate(dot(N,L));
            o.color+=_LightColor0* ndotl;
            //Specular Color
            //float3 wpos=mul(_Object2World,v.vertex).xyz;

            float3 H=L+V;

            H=normalize(H);

            float specularScale=pow(saturate(dot(H,N)),_Shininess);
             o.color.rgb+=_SpecularColor * specularScale;


            return o;
              }

            fixed4 frag(v2f IN):COLOR
            {
            return IN.color+UNITY_LIGHTMODEL_AMBIENT;
             }
            ENDCG
        }
    }
}

简单光照模型(Phong模型(镜面反射)与 Blinn-Phong光照模型(修正镜面光) )