The Phong Approximation

The Phong Approximation


Phong shading was invented by a Mr. Wu Tong Phong. It improves somewhat on the Gourad approximation for shading polygons. The basic principle is to calculate the surface normal at each vertex of a polygon, and interpolate the vector over the surface polygon. Then, for each pixel, calculate the brightness of the pixel based on this normal vector.

This is a very slow process indeed, and one which cannot yet be considered a realtime option for home computers. Many programs which claim to be able to perform realtime Phong shading are infact using fake phong shading. This is very nearly as good, and is very much faster.

This is a very popular method for shading polygons, especially in non-realtime rendering packages like 3D Studio. However, although it looks much nicer than Gouraud shading, it is still not physically accurate.

To gain a good understanding, you should also read the article entitled 'A Physical Model of Light'.


Phong shading is just an extension of the Physical Model of Light in the previous article. Every single pixel has it's brightness carefully calculated using the interpolated normal vector.

This involves:

2 square roots
2 divides
4 multiplies
not to mention numerous adds, per pixel! And these are all non-integer calculations too. Compare this with one add per pixel for Gouraud shading, and you can see why this is so slow.


Right, enough of this. How to do Phong Shading.

Phong shading is based on the fact that the amount of light refected from a surface is proportional to the cosine of the angle between the surface normal and the direction of the light. The angle you are viewing the surface from makes no difference.

In reality, very few materials exhibit this ideal property. Microscopically rough surfaces, such as corsely sanded wood may come close. Most surfaces also exhibit specular reflection to some extent. Phong shading does not deal with this. It also does not handle the fact that brightness is inversely proportional to the inverse square of the distance from the light.

So, we have a polygon. Each of it's vertices has been given a normal vector (v1, v2, v3). These vectors are interpolated across the polygon in much the same way the shade was in Gouraud shading. In Gouraud shading, there was only one value to interpolate, shade, in Phong shading, there are three, Vx, Vy and Vz (the three components of a vector).

So, let's take a pixel on this polygon, the red one. It's normal vector, n has been calculated. Light is striking the polygon along a vector l. The fraction of light from the light source reflecting off this pixel is the dot product of n and l. Simple.

Now, the dot product function returns values in the range 1 to -1. 1 is full brightness. There is no such thing as negative light, so values less then 0 should be taken as 0. If you multiply this value by the brightness of the light, then you have the brightness of that pixel.


I am not going to bother to demonstrate this algorithm or give any pseudo code. Those who are smart enough to implement this really don't need my help. People who really want Phong shading in their programs should read the next article on Fake Phong shading.