**[**Back to GRAPHICS SWAG index**]** **[**Back to Main SWAG index**]** **[**Original**]**

```
Fast Phong Shading, Theory
```**and **Practive
Introduction
<I> Fast phong shading **is **always a goal **of **anyone writing a 3D engine.
Despite some **of **its failings, Phong shading **is **still common **in **3D systems,
**and **people are always looking **for **faster **and **easier ways **to **approximate it.
**In **this page, I'll discuss firstly <I> real </I> phong shading, then some of
the approximations **of **it. I'll also explain why the document OTMPHONG.DOC
**is **utter nonsense, **and **should be avoided at all costs.
Real </I> phong shading
<P> Real phong shading **is **done by interpolating the vertex normals across the
surface **of **a polygon, **or **triangle, **and **illuminating the pixel at each point,
usually using the phong lighting model. At each pixel, you need **to
**re-normalize the normal vector, **and **also calculate the reflection vector.
The reflection vector **is **calculated by:
R = 2.0*(N.L)*N - L
I found this vector also needs **to **be normalized. **Then**, we feed these vectors
into the illumination equation **for **the phong lighting model, which **is
**I = Ia*ka*Oda + fatt*Ip[kd*Od(N.L) + ks(R.V)^n]
Here, the variables are:
Ia **is **the ambient intensity
ka **is **the ambient co-efficient
Oda **is **the colour **for **the ambient
fatt **is **the atmospheric attenuation factor, ie depth shading
Ip **is **the intensity **of **the point light source
kd **is **the diffuse co-efficient
Od **is **the objects colour
ks **is **the specular co-efficient
n **is **the objects shinyness
N **is **the normal vector
L **is **the lighting vector
R **is **the reflection vector
V **is **the viewing vector
**To do **multiple light sources, you sum the term
fatt*Ip[kd*Od(N.L) + ks(R.V)^n] **for **each light source. Also,
you need **to repeat **this equation **for **each colour band you are interested **in**.
Such shading **is **incredibly expensive, **and **cannot be done **in **realtime **on
**common hardware. So, people have been looking into optimizations **and
**approximations **of **this **for **a long time.
Angular Interpolation
One idea **is to **avoid the expensive dot-product **and **normalization operations
by interpolating the angles. This sounds good **in **theory, but has a couple **of
**problems:
Choosing a **function to do **the interpolation
Perspective problems
**In **the **file **OTMPHONG.DOC, the idea was **to **interpolate the angle, **or **cosine **of
**the angle (I can't remember which) across the surface of the polygon. This
doesn't work, because:
Cosine **is NOT **linear
Using linear interpolation you cannot get a value outside **of **your start
value, **and end **value. So no highlight **is **possible.
OTMPHONG.DOC just re-invented Gouraud shading, **and **tried **to **turn it into
Phong shading. It doesn't really work very well. Yes, I have tried it, I've
tried a great deal **of **methods **of **implementing it, but it just doesn't work!
Another way I've heard of is using a Taylor series approximation.
Admittedly, I haven't tried this yet; from what I gather, the idea here is to
use a polynomial **to **approximate the cosine. People have used this **in **the past
**to **generate sin tables, **in **4k intros **and **what have you, so it should be
possible. Again, I haven't tried it yet, if I ever do, I'll tell you what I
find.
A halfway-house **is **the highlight test. Here, a polygon **is **tested, **to
**see **if **the highlight falls **on **the polygon. **If **it doesn't, then you just use
plain gouraud shading. **If **it does, you use your phong shader. The test follows:
**For **any vertex, **is **N*H >= t (threshold) ? **If **so, highlight = TRUE
**For **any edge, **is **N*H >= t at any point **on **that edge? **If **so, highlight = TRUE
**For **all edge, does N*H exhibit a maximum? **If **so, highlight = TRUE
**If **none **of **the above conditions, highlight = FALSE
H **is **the halfway vector, (L + V) / 2. I found this algorithmn **in **the book
"3D Computer Graphics" by Alan Watt. I have yet **to try **this one, but it
sounds workable. The only problem might be slight discontinuities **in **the
shading. Again, this **is **guesswork, you'd have to implement it to see.
The Fake Method
Now I'll describe a method that is a bit odd, yet works very well in
practice. Its the method most demos use **to do **their 'phong' shading, **and is
**very fast.
First, we need **to **generate a 'highlight map'. This **is **a texture, which
consists **of **concentric circles, the brightest **in **the middle, decreasing **in
**brightness **as **they go outwards. So it looks like a highlight. This **is **easy
enough **to **generate, a simple way being **to **take the distance from the centre,
**and **get it into the range 0..256. Also, this map should be 256x256, **for
**efficiency reasons.
Now we need **to **map the highlight onto the **object**. Again, this **is **easy **to do**.
Take your vertex normal X value, multiply it by 128, **and **add 127 **to **it. **Do
**the same **for **Y. Call these values P, Q (save confusion **with **U,V - texture
co-ords). These are our texture co-ordinates! Now simply map the texture **to
**the **object**, **and **hey presto, one nicely shaded **object**. **As **you rotate the
**object**, the highlights will also move. Its a very handy algorithmn I think,
**if **a little odd. Its based **on **a trick called environment mapping, which you
will find described elsewhere **in **these pages. You'll also notice that if you
go behind your **object**, the lighting **is **the same. Another problem **with **the
algorithm. Take **is **an extra light source **for **free. Also, **as **this method **is
**based **on **environment mapping, its only correct **for **parallel projection.
But don't let that spoil your fun!
Extending this **to **multiple light sources shouldn't be too hard. For 2 light
sources, you would have 2 maps, each having values **in **the range 0..128. You
would **then **add them together, **to **get a colour value. Moving the light source
around involves changing the P **and **Q values; using the normals sort **of **works,
but after about 90 degrees, weird things start **to **happen.
Also one other thought. The phong map **is **basically a bunch **of
**circles:
So, it **is **symmetrical about the centre. Why **not **just use one quadrant
**of **the map, **then **use sign **and **quadrant information **to **convert the u,v
co-ordinates? Would say some memory... Like so:
Well, I hope I helped **to **demistify Phong shading, **and **disprove some **of **the
myths surrounding the subject. So please, don't come onto #coders, asking
how **to **implement phong shading, **or **asking about that gibberish otmphong.doc
**file**, you have all the information you need right here.
Tom Hammersley, <A HREF="mailto:tomh@globalnet.co.uk"> tomh@globalnet.co.uk</A>
Please don't call the fake phong shading method phong shading. It gets
us all confused. Can someone please think up a good name **for **that method,
**and **use that instead? After all, fools gold **is not **gold, no matter how much
it glitters

**[**Back to GRAPHICS SWAG index**]** **[**Back to Main SWAG index**]** **[**Original**]**