Blinn-Phong
Phong specular requires computing a reflection vector. Blinn-Phong takes a faster route — it uses the half-vector instead:
Here's what the half-vector is, and how it differs from Phong.
What is the half-vector?
l points toward the light, v points toward the camera. Add them together and normalize — the result is the half-vector, pointing exactly halfway between l and v.
Phong asks "does the reflected ray reach the eye?" (dot(r, v)). Blinn-Phong instead asks "does the surface normal point toward the half-vector?" (dot(n, hV)). Both produce similar-looking highlights, but the half-vector is cheaper to compute and is the standard in real-time rendering.
pow controls highlight size
dot(n, hV) ranges from 0 to 1 (0% when the normal and half-vector are perpendicular, 100% when aligned). The pow exponent determines tightness: a high exponent produces a small, sharp highlight like a mirror; a low exponent spreads it wide like a matte surface.
48.0 gives a moderately tight highlight — visible but not pinpoint.
Diffuse + specular combined
baseCol * (0.12 + 0.88 * diff) is the diffuse layer (base color scaled by how much it faces the light). vec3(1.0) * spec adds a white specular highlight on top. Together they form the full Blinn-Phong result.
Try changing it
| Change | Effect |
|---|---|
48.0 → 8.0 | Highlight spreads wide, matte-like surface |
48.0 → 128.0 | Highlight shrinks to a tight bright dot, glass-like |
vec3(1.0) * spec → vec3(1.0, 0.8, 0.4) * spec | Warm yellow highlight |
Light direction vec3(-0.4, 0.6, 0.7) → vec3(0.8, 0.2, 0.7) | Highlight shifts to the right side |
Exercise
Replace hV = v with the correct half-vector hV = normalize(l + v) so the sphere shows a white specular highlight.
Answer Breakdown
Starting state: hV = v substitutes the view direction for the half-vector. This makes dot(n, hV) peak at the center of the sphere rather than at the lit area, producing a misplaced highlight.
The fix: normalize(l + v) averages the light and view directions. Now dot(n, hV) peaks where the surface faces both the light and the camera — exactly where a real highlight should appear.
Try changing 48.0 to 200.0 to see the highlight compress into a near-invisible pinpoint at very high glossiness.