Fast Phong Shading
# Fast Phong Shading

The basic Phong shading technique tends to be very slow. However, it can look really good,
and so it has been the subject of much optimisation. It's only possible to optimise the origional
algorithm so far. No matter how much Fixed Point maths and lookup tables you throw at it, it
still runs too slowly to make it a realistic option for realtime graphics.

A document has been circulating for some time under the name of OTMPHONG.DOC. It suggests
that instead of interpolating the normal vector across the polygon, you should interpolate the
angle between the light source and the normal. This is a nice idea except for the fact that it
doesn't really work. It is essentially a repeat of Gouraud shading, and of little use to anyone.

Except that this gave me an idea which I later discovered people had already suggested. I
have heard this explained in several ways, all of which are essentially equivalent. I considered
that rather than simply interpolate an angle across the polygon, it might be possible to interpolate
two. This would be very similar to interpolating a vector. Now, rather than do some horrid
calculations with these two angles, you might as well consider them to be texture coordinates
and lookup the result of the calculations in a texture map.
This is really a big step in the life of realtime graphics. No longer must we put up with dodgy
Gouraud shading. We can now enjoy the full benefits of Phong shading from the comfort of our
home computers. Phong shading is now just linear texture mapping, which, thanks to the likes of
Michael Abrash, can be done very quickly indeed.

## The Phong Map

It just so happens that the texture map you need is a very simple one. This is a convenient
256x256 texture which you can take and use if you want. I must confess I very rudely stole this
image from Tom Hammersley's Graphics Coding Page.
I hope he doesn't mind. You may want to generate your own however. It's quite simple to get your
program to create one, or you can make various deviations to give different effects. For example,
you might try an image with rings of bright colour to give the appearence of a chrome object.

OK, so how to actually do this. I haven't done a vast amount of investigation here, and the only
way I have come up with so far has been a teeny bit slow, although I am sure there is a faster
method. If anyone knows one, I would be happy to know what it is.

So, for each vertex of the polygon to be rendered, you will need to calculate the coordinates
to the Phong Map.

You have a polygon. For this polygon, define two vectors which are at right angles to
each other and to the surface normal. Call them
**V** and **H**.
These two vectors represent the (u,v) coordinates of the phong map.

Now we'll look at this polygon at an angle so the vector from the light source to the vertex
can be seen. This is vector **L**.
The aim is to calculate the coordinates (u,v) in terms of
**V**, **H** and **L**

The algorithm is a very simple one. If the phong map is 256x256 and centered then:

**
u = ( V . L ) * 128 + 127**

v = ( H . L ) * 128 + 127

do this for each vertex, and then map the Phong map onto it, and there you have one nicely phong
shaded polygon.

Since this can be slow, there are various ways you can speed it up if you don't mind a little
loss of freedom. If you assume that the light source is at the same place as the camera, then you
can ignore the **V** and **H**
vectors altogether. Instead take the **X** and **Y** components of the normal vector, multiply
by 128 and add 127 (assuming that is that the magnitude of the normal vector is 1).

Alternatively, you can take the light source as being like an inverse camera. Transform the
object as if the light source were the camera, and calculate the phong as in the previous
paragraph.

## Notes on Fake Phong Shading

As you would probably expect, this method is not perfect. The fact that the Phong Map has
a limited resolution means that sometimes the highlights on an object will look a little
pixelated. This will not really be noticable though if the object is spinning or moving quickly.
If you add bump mapping, the effect will be barely noticable.

One artifact of the technique is that you get the effect of 2 light sources. The first will
be where you expected it to be. The other will appear to be on the other side of the object. This
is possible to overcome, and I will explain how to do this later, and how to make that extra light
a different colour if you want.

If you're really clever with a bump map, you can turn it into a shinyness map too. It is
possible to have, say, an object with diffuse bits and chrome bits, all controled by the bump
map. I'll get onto this n the next article on Bump Mapping.