基于Lambert光照模型的Shader

Lambert模型

Lambert光照模型计算公式为:

alt 使用入射光颜色和漫反射颜色相乘再乘以saturate裁剪后的光线方向(从入射点到光源方向)和法线方向夹角大小(点乘cos值)。

Shader "Custom/Lambert"
{
    Properties
    {
        _MainColor("MainColor",Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc"

            struct v2f
            {
                float4 pos : SV_POSITION;
                fixed4 dif : COLOR0;
            };

            fixed4 _MainColor;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                //法线向量 由模型空间变换到世界空间并标准化
                float3 n = UnityObjectToWorldNormal(v.normal);
                n = normalize(n);

                //灯光法向向量
                fixed3 l = normalize(_WorldSpaceLightPos0.xyz);
                
                //按照公式计算漫反射
                fixed ndotl = dot(n,l);
                o.dif = _LightColor0 * _MainColor * saturate(ndotl);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return i.dif;
            }
            ENDCG
        }
    }
}

alt

HalfLambert模型

alt

修改公式将夹角值映射到[0.5,1]避免背面全黑。

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                //法线向量 由模型空间变换到世界空间并标准化
                float3 n = UnityObjectToWorldNormal(v.normal);
                n = normalize(n);

                //灯光法向向量
                fixed3 l = normalize(_WorldSpaceLightPos0.xyz);
                
                //按照公式计算漫反射
                fixed ndotl = dot(n,l);
                o.dif = _LightColor0 * _MainColor * (0.5 * ndotl+0.5);

                return o;
            }