[Unity Shader] (2) Half-Lambert model to build lighting

Use the half-Lambert model in unity's Shader to build lighting

Before getting to know the half-Lambert model, it is recommended to check out my previous Lambert model to build lighting

  • Lambert lighting model

0

  • Half Lambert lighting model

Since the calculation formula of the Lambert model only intercepts the illumination interval of [0,1], the details of the dark part of the shadow part may be lost. When Valve was developing "Half-Life", it proposed a new lighting technology, which is a simple modification based on the original Lambert lighting model-so it is called Half- Lambert Lighting model . The generalized semi-Lambert lighting model is as follows:

1

Similar to the Lambert lighting model, except that the Max function is replaced by (a · ( n · I )+b) so that sufficient dark details can be preserved. Typically, the values ​​of a and b are 0.5. That is, the formula is as follows:

3

The reason why the details of the dark part can be preserved is that even if the maximum value of n·I is 1, it will be multiplied by 0.5 and then added by 0.5. Still ensures that the right parenthesis is still greater than 0 and less than 1. It means that after all the dot product results are reduced, and then enlarged by 0.5 as a whole, the final effect is actually brighter. Because even if it is the shadow part, it will still be increased by 0.5 in the end.



  • Comparison of Lambert and semi-Lambert models:

3

  • Half Lambert lighting model Shader code


Shader "LeonShader/shader_6_4_Diffuse_HalfLambert"
{
    Properties{
        _Diffuse("Diffuse",Color) = (1,1,1,1)
    }
        SubShader{
            Pass{
                Tags { "LightMode" = "ForwardBase"}

                CGPROGRAM

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

                fixed4 _Diffuse;

                struct a2v {
                    float4 vertex : POSITION;
                    float4 normal : NORMAL;
                };
                struct v2f {
                    float4 pos : SV_POSITION;
                    float3 worldNormal : TEXCOORD0;
                };

                v2f vert(a2v v) {
                    v2f o;
                    //将定点左边从本地空间转变投影空间
                    o.pos = UnityObjectToClipPos(v.vertex);
                    //得到环境信息
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                    //法线信息由物体空间转变为世界空间
                    o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);

                    return o;
                }

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

                    fixed3 color = ambient + diffuse;

                    return fixed4(color , 1.0);
                }

                ENDCG
            }
    }
        FallBack "Diffuse"
}

Guess you like

Origin blog.csdn.net/weixin_46840974/article/details/123977538