In contrast to the diffuse lighting discussed earlier, many objects in the real world display specular highlights. A specular material on a perfectly smooth object would display a highlight only at points whose surface normals bisect the angle between the incoming light source and the incoming camera viewing ray -- at the so-called half-angle. However, as with all things in graphics, this is not how real life works.
We cannot normally assume that the concept of "perfect smoothness" exists in reality. Instead, we allow for the notion that surfaces exist as the union of perfect specular reflectors called microfacets. Each of these microfacets has a normal that differs from the normal of the actual surface by a certain factor, usually deemed the roughness of the surface.
If a surface has no roughness, it is a perfect reflector. However, with even a small amount of roughness, microfacets near points with surface normals near the half-angle direction will have normals pointing toward the half-angle direction, courtesy the deviation introduced by a nonzero roughness. As we move farther away from points with real normals pointing in the half-angle direction, fewer and fewer microfacets will satisfy this constraint, leading to less of a specular reflection.
Bui Phong and, eventually, Jim Blinn devised two methods to simulate this concept of roughness, both of which lead to a more blurry and realistic specular highlight. Blinn's model takes the dot product of the view ray with the incoming light ray (remember, this is proportional to the angle between the two vectors!) and raises the cosine of this resultant angle to a kind of inverse "roughness" factor. The higher this exponent is, the less blurry the reflection will be.
// Compute V dot R for Phong highlight
double dot = V.dot(R);
if(dot > 0.0)
{
double phong_mult = material->getSpecularCoef()
* powf(dot, material->getPhongCoef());
total_color += light->getSpecular() * phong_mult * dropoff;
}
Jim Blinn simplified the computations necessary for this kind of shading with his Blinn-Phong shading model. Instead of forcing a recomputation of R•V, where R is the reflection of a light off a surface, we can store a halfway vector based on only the viewer and the light, then dot this vector with the surface normal at each point. This provides Blinn-Phong with a significant speedup over plain Phong shading. OpenGL and, until recently, Direct3D's default shading model is Blinn-Phong.