【Unity Shader】(2)半兰伯特模型 构建光照

在unity的Shader中使用半兰伯特模型来构建光照

在认识半兰伯特模型之前,建议查看一下我之前的兰伯特模型构建光照

  • 兰伯特光照模型

0

  • 半兰伯特光照模型

由于兰伯特模型的计算公式仅截取了[0,1]的光照区间,因此可能会丢失掉阴影部分的暗部细节。而Valve公司在开发《半条命》的时候,提出了一个新的光照技术,该技术是有原兰伯特光照模型的基础上进行了一个简单的修改——因此被称为半兰伯特光照模型。广义的半兰伯特光照模型如下:

1

和兰伯特光照模型类似,只是将Max函数替换成了(a·(n·I)+b)这样一来就可以保留充足的暗部细节。通常情况下,a和b的值为0.5。即该公式为如下:

3

之所以能够保留住暗部细节,是因为就算 n·I 的值最大为1,也会被乘0.5,然后再加上0.5。仍然可以确保右边括号仍然大于0且小于1。意思是将所有点积结果缩小后,再整体放大0.5,最终的效果其实是偏亮的。因为就算是阴影部分,最后还是会被提高了0.5。



  • 兰伯特模型 和 半兰伯特模型 的对照:

3

  • 半兰伯特光照模型Shader代码


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"
}

猜你喜欢

转载自blog.csdn.net/weixin_46840974/article/details/123977538