Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
82 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:


This article should have shown you several things. First of all the usage of multiple passes is a well working and efficient solution, that decreases rendering speed nearly linear compared to the number of passes. With this multiple pass approach you can also safely apply multiple overlapping lights without worrying about errors.

If you read the article from back to front, you can see, how to divide a ps.1.4 shader into several ps.1.1 pixel shaders to make it work on a ps.1.1 graphic card. I guess that the knowledge on how to downsize shaders will be even more useful in the future :-).

Further Improvements

There are several ways to improve these examples. I would like to suggest to read the article of Ronald Frazier [Frazier]. He shows a lot of ideas used throughout the examples above and two interesting improvements: First, he adds a self-shadowing term to the light, that sets the light brightness to zero if the light lies behind the polygon. This term additionally helps reducing pixel popping on bump mapped surfaces, when the light is in front of the polygon at a distance between 0 and 0.125 by allowing a linear scaling of the light brightness.

Another interesting idea that I found in this article was an alternative specular formula, which should lead to a smoother specular reflection: 4*((N dot L)^2 - 0.75.

Jakub Klarowicz [Klarowicz] pointed me to an interesting specular lighting formula in the Game Developer Algorithm forum. It is based on R dot V (R- reflected light vector, V - vector to the camera) instead of N dot H and leads to a smoother specular reflection, because it is per-pixel correct. This is because of the way H is calculated and interpolated. It is usually calculated and normalized per vertex, by being derived from V and L, and then renormalized per pixel (as shown for the H vector in the examples above).

A more proper way to get a per-pixel correct vector would be to interpolate it unnormalized and normalize it per pixel later (as shown for the the L vector in the examples above). This might be possible for H with ps.1.4, but requires three normalizations per-pixel. Therefore it is easier to use the unnormalized L and V vectors, normalize them with cube normalization maps and calculate R in the pixel shader and finally R dot V. Jakub Klarowicz has used that in practice and he says that R dot V looks always stable and the highlight is always where it's supposed to be.

A better way to handle specular with per-pixel exponent on fixed-point pixel pipeline, while accounting for the denormalization (due to interpolation) of the half-angle vector, is the "N.H H.H" method discussed in an article in Game Programming Gems III. This technique is used in the OpenGL PointlightShader example available on ATI's web-site and in one of the RenderMonkey examples.

Another good read is the article of David Gosselin [Gosselin], where he shows a way to use three lights in one ps.1.4 pixel shader. I would also like to recommend the article of Steffen Bendel [Bendel] which has an even more innovative approach compared to the examples shown here.


[Bendel] Steffen Bendel, "Smooth Lighting with ps.1.4", ShaderX, Wordware Inc., pp ?? - ??, 2002, ISBN 1-55622-041-3

[Beaudoin/Guardado] Philippe Beaudoin , Juan Guardado, "Non-integer Power Function on the Pixel Shader", ShaderX, Wordware Inc., pp. ?? - ??, 2002, ISBN 1-55622-041-3. Available online at Gamasutra.

[Dempski] Kelly Dempski, Real-Time Rendering Tricks and Techniques in DirectX, Premier Press, Inc., pp 578 - 585, 2002, ISBN 1-931841-27-6

[Dietrich] Sim Dietrich, "Attenuation Maps", Game Programming Gems, Charles River Media Inc., pp 543 - 548 2000, ISBN 1-58450-049-2

[Frazier] Ronald Frazier, "Advanced Real-Time Per-Pixel Lighting in OpenGL", http://www.ronfrazier.net/apparition/index.asp?appmain=research/advanced_per_pixel_lighting.html

[Ginsburg/Gosselin] Dan Ginsburg/Dave Gosselin, "Dynamic Per-Pixel Lighting Techniques", Game Programming Gems 2, Charles River Media Inc., pp 452 - 462, 2001, ISBN 1-58450-054-9

[Gosselin] David Gosselin, "Character Animation with Direct3D Vertex Shaders", ShaderX, Wordware Inc., pp ?? - ??, 2002, ISBN 1-55622-041-3.

[Hurley] Kenneth Hurley, "Photo Realistic Faces with Vertex and Pixel Shaders", ShaderX, Wordware Inc., pp ?? - ??, 2002, ISBN 1-55622-041-3

[Johnson] Tim Johnson, Message in Microsoft DirectX forum.

[Klarowicz] Jakub Klarowicz, Message in Game Developer Algorithm forum.


I would like to thank the following individuals for proof-reading and helping me to improve this article:

  • Arnaud Floesser
  • Damian Trebilco (Auran)

© 2002 Wolfgang Engel, Frankenthal, Germany


  Printable version
  Discuss this article

The Series
  Fundamentals of Vertex Shaders
  Programming Vertex Shaders
  Fundamentals of Pixel Shaders
  Programming Pixel Shaders
  Diffuse & Specular Lighting with Pixel Shaders