Lighting Models

The Lambert reflectance and the Phong / Blinn-Phong reflection models

The complete code can be found here

Overview

This shader demonstrates the basic Lambertian diffuse lighting model along with Phong and Blinn-Phong specular highlights. It was implemented in Unity using HLSL.

Live Demo

This demo shows the lighting with Lambertian diffuse highlight and the Blinn-Phong specular highlight with no ambient light. There is only a single Directional Light in the scene.

Some Explanation

Lambertian

The Lambertian Lighting model calculates the intensity of the light according to the angle between the light direction and the normal of the surface. The intensity is highest when the light is in the same direction as the normal and decreases as it starts rotating. For this the cosine function can help us, so the Lambertian diffuse light is calculated as:


float3 N = normalize( i.normal );             // surface normal
float3 L = _WorldSpaceLightPos0.xyz;          // light direction
float lambertian = saturate( dot( N, L ) );   // normal * light direction * cos( theta )
float3 diffuseLight = lambertian * _LightColor0.xyz;
				

Phong

The Phong specular highlight considers the view direction. It first reflects the light around the surface normal, then calculates the specular according to the angle between the reflected light and the view direction. In this way the highlights appear most strong where the reflection vector aligns with the view angle.


float3 V = normalize( _WorldSpaceCameraPos - i.worldPos );    // view angle from the camera
float3 R = reflect( -L, N );    // reflects the light around the normal

float3 specularLight = saturate( dot( V, R ) );
specularLight *= _LightColor0.xyz;
				

Blinn-Phong

In Blinn-Phong, a half-vector is used instead of the view angle. The highlight is calculated according to the angle between the half-vector and the surface normal. The half-vector is the vector half way between the light direction and view angle. This provides similar results to Phong but often with better performance.


float3 H = normalize( L + V );    // half vector, half way between light dir and view angle

float3 specularLight = saturate( dot( H, N ) );
specularLight *= _LightColor0.xyz;