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;