半兰伯特光照模型

由于使用漫反射光照的时候 在光照面和半光照面结合处出现了锯齿形状,影响模型的效果,Value公司 提出一种技术,在原兰伯特光照模型基础上做出了修改解决了漫反射中的的问题,依次被称为半兰伯特光照模型

广义半兰伯特计算公式:

C^{_{diffuse}}=(C_{light}* M_{diffuse})max(0,\hat{n}\cdot \hat{l}))(C_{light} * M_{diffuse})(α(\hat{n}\cdot\hat{l})+β)

没有采用max 函数来防止点积为负值,采用的是α倍的缩放和β倍的偏移。一般情况下,α和β的值均为0.5

这样也可以将结果从[-1,1]映射到[0,1],这样在被光面 也可以有明暗变化(不同的点积结果会映射成不同的值),而不是像之前那样都为0在被光面。

半兰伯特模型 是一种是视觉加强技术,没有物理依据的。

与漫反射的逐像素光照相比,只是修改了片元函数中漫反射的计算

Shader "Custom/HalfLambert"
{
    Properties
   {
       _DiffuseColor("Color",Color)=(1.0,1.0,1.0,1.0)
   }
   
   SubShader
   {     
       pass
       {
           Tags{"LightMode"="ForwardBase"}

           CGPROGRAM

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

            fixed4 _DiffuseColor;

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

            struct v2f
            {
                float4 pos :SV_POSITION;
                float3 normalWorld:TEXCOORD0;
            };

            v2f vert(a2v v)
            {
                v2f o;
                o.pos=UnityObjectToClipPos(v.vertPos);
                o.normalWorld=mul(v.normal,(float3x3)unity_WorldToObject);
                return o;
            }

            fixed4 frag(v2f i):SV_Target
            {
                fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 worldNormal=normalize(i.normalWorld);
                fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
                fixed halfLambert=dot(worldNormal,worldLightDir)*0.5+0.5;
                fixed3 diffuse=_LightColor0.rgb*_DiffuseColor.rgb*halfLambert;
                return fixed4(ambient+diffuse,1);
            }

           ENDCG
       }

   }

    FallBack "Diffuse"
}

三种效果比较:向光面

背光面:

可以看出来半兰伯特光照在背面也是有明显的明暗变化

发布了76 篇原创文章 · 获赞 43 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/hnzmdlhc/article/details/104398850