Lambertian and Blinn-Phong

Lambertian Model

Lambertian model is based on lambertian reflectance, is the property that defines an ideal “matte” or diffusely reflecting surface. The reflected quantity is equal to the vertical component of the incident light ray.

Shader "Custom/LambertianShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf SimpleLambert

        struct Input
        {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;
        
        void surf (Input IN, inout SurfaceOutput o)
        {
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
        }

        half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten)
        {
            half NdotL = dot(s.Normal, lightDir);
            half4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * NdotL * atten;
            c.a = s.Alpha;
            return c;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

LightingSimpleLambert is the re-implementation. atten is used to modulate the intensity of the light. _LightColor0 is a built-in variable. The light color. half4 Lighting<Name> is the naming convention for custom lighting models of surface shaders. Unity documentation lists all other declarations.

Cel Shading (Toon Shading)

Shader "Custom/Cel"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _RampTex("Ramp", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Toon

        struct Input
        {
            float2 uv_MainTex;
        };
        sampler2D _MainTex;
        void surf(Input IN, inout SurfaceOutput o)
        {
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
        }

        sampler2D _RampTex;
        fixed4 LightingToon(SurfaceOutput s, fixed lightDir, fixed atten)
        {
            half NdotL = dot(s.Normal, lightDir);
            NdotL = tex2D(_RampTex, fixed2(NdotL, 0.5));

            fixed4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * NdotL * atten;
            c.a = s.Alpha;

            return c;
        }

        ENDCG
    }
    FallBack "Diffuse"
}

The coefficient is calculated using ramp texture to re-map it onto different set of values.

Blinn-Phong Model

Lambertian: $I = N \cdot L$

Blinn-Phong uses a half vector:

$$ I = (N \cdot H)^{sepcular} \cdot gloss \
H = \frac{L + H}{ |L + H| } $$

Physically Based Rendering (PBR)

PBR is northing more than surface shader with advanced lighting model.

  • Metallic workflow The material reflects light depends on how metallic it is.
  • Specular workflow A specular map is required.

PBR surface outputs

3 new properties except Albedo, Normal, and Alpha:

  • half Metallic: 0 - 1, how light reflects on the material
  • half Smoothness: the surface’s smoothness 0 - 1
  • half Occlusion: ambient occlusion.

Specular workflow has half3 Specular instead of Metallic, it’s a half3.