The idea: three kinds of light at every point
Rasterization decides which pixels a triangle covers. It does not say what colour they are. That is the job of a lighting model. The classic one, from Bui Tuong Phong in 1975, adds three simple terms at each surface point: a constant ambient glow, a diffuse part that depends on how squarely the surface faces the light, and a specular highlight that depends on where the eye is.
The page shows a side view of a sphere: a light up to the right at (120, 100), an eye straight above at (75, 105), and 25 surface points along the top of the sphere, numbered 0 (left, 150°) to 24 (right, 30°).
The formula
With all four vectors of length 1, the Phong reflection model is
I = ka + kd · max(0, N·L) + ks · max(0, R·V)ⁿ
R = 2(N·L)N − L
| Term | What it models | Depends on | Page value |
|---|---|---|---|
| ambient ka | light bounced around the room, from everywhere | nothing | 0.1 |
| diffuse kd·N·L | a matte surface scattering light in all directions (Lambert's cosine law) | normal and light | kd = 0.6 |
| specular ks·(R·V)ⁿ | a shiny surface reflecting the light mostly one way: the highlight | normal, light and eye | ks = 0.5, n = 20 |
Ambient and diffuse are multiplied by the surface's own colour (blue here). Specular is multiplied by the light's colour (white), which is why highlights on a blue ball look white, not blue.
Diffuse: N·L
N·L is the cosine of the angle between the normal and the light direction (see Vectors and Dot Product). Facing the light head on gives 1; side-on gives 0. A negative value means the surface faces away from the light, so it is clamped to 0 and only the ambient term is left. Point 3 (135°) has N·L = −0.18 and comes out almost black, I = 0.10 (Demo: point facing away from the light). The diffuse term does not involve V at all: a matte wall looks equally bright from anywhere in the room.
Specular: R·V to the power n
R is L mirrored about the normal: the direction a perfect mirror would send the light (the same reflection as in Reflection Matrix). R·V is close to 1 only when the eye looks back along R. Raising it to the shininess n makes the falloff steep: 0.9²⁰ is only 0.12.
Point 15 (75°) sits right in the highlight: N·L = 0.87, R·V = 0.996, (R·V)²⁰ = 0.92, so I = 0.10 + 0.52 + 0.46 = 1.08 and the pixel is rgb(138, 192, 254), almost white (Demo: one point in the highlight). Point 21 (45°) faces the light even better (N·L = 0.96) but R·V = 0.133, so it has no highlight: I = 0.68 (Demo: diffuse only, no highlight).
| Shininess n | Points with specular ≥ 0.05 | Looks like |
|---|---|---|
| 1 | 12 of 25 | a broad sheen, dull plastic |
| 5 | 7 | soft highlight |
| 20 | 4 | glossy |
| 100 | 2 | a small sharp spot, polished metal |
(Demo: shade the whole surface, Demo: sharp highlight, n = 100, Demo: broad highlight, n = 5.) Many engines use the Blinn–Phong variant, which replaces R·V with N·H, where H is the unit vector halfway between L and V. It is cheaper and looks a little softer for the same n.
Flat, Gouraud and Phong shading
A renderer does not have a perfect sphere, only a mesh of flat triangles with a normal stored at each vertex. There are three classic ways to shade the pixels in between (Demo: Gouraud misses the highlight, with 4 facets and 5 vertices at points 0, 6, 12, 18, 24):
| Method | Lighting runs | Between vertices | Brightest pixel |
|---|---|---|---|
| Flat | once per facet | one colour for the whole facet | facet 3 glows as a band, I = 1.08 |
| Gouraud | once per vertex (5) | blend the vertex colours | point 18, I = 0.70 ✗ highlight lost |
| Phong shading | once per pixel (25) | blend the vertex normals, renormalise, then light | point 15, I = 1.08 ✓ |
The vertex intensities are 0.10, 0.15, 0.48, 0.70 and 0.57. A blend of two numbers is never larger than the bigger one, so Gouraud cannot be brighter than 0.70 anywhere. The highlight, which sits between vertices 12 and 18, is gone. Phong shading gives each pixel its own normal and finds it again. "Phong shading" (interpolate normals) and "Phong reflection" (the formula) are two different ideas from the same paper; modern GPUs run the formula, or a physically based one, in a fragment shader for every pixel, which is Phong shading.
See also Ray Tracing vs Rasterization, which uses only the ambient and diffuse terms plus shadow rays, and Perspective Projection for how the points reach the screen.
What the page leaves out
The scene is a 2D slice with one white point light and one material. Real renderers work in 3D, add the terms per colour channel and per light, dim the light with distance (attenuation), add shadows, and today mostly use physically based models (Cook–Torrance, GGX) that conserve energy, so a highlight cannot add more light than arrives. The page also clamps the final colour instead of tone mapping, and skips textures, normal maps and the Fresnel effect.