Sep 6 2006 · Graphics and Rendering
Work on zerospace has finally picked up in the past few weeks and a few days ago I posted the first screenshot in the zerospace blog. Not much to see as yet, just an background, starfield, and untextured model. However, I did put in some major work on the lighting system, which is visible in the screenshot (to a certain extent; the specular highlights are dull and, although they’re there, they’re only apparent when the model rotates).
Anyway, what I wanted to discuss in this post is the lighting model, since I think it’s fairly unique and it gives some amazing results.
The ambient component is done per-vertex (i.e. all computations are done in vertex shader and color is interpolated over the face of the triangle) and consists of 7 directional lights hitting the model from various directions. It’s sort of an ultra-simplified version of ambient occlusion mapping.
The diffuse component is sampled from a 2d texture. This texture is a scaled down and heavily blurred version of the background texture (done offline; a heavy blur, such as the one required would be too expensive in the pixel shader). Scaling it down is simply a matter of performance, as the background texture is large (2048×2048). Blurring (I do a guassian blur) is a trick to get the diffuse lighting from a scene (this is a bit difficult to explain, I’ll try to do later in another post).
So how how is the texture mapped onto the 3d model? Spherical texture mapping! (see this article for an explanation). Note that the normal vector used to computer the texture coordinates is the the normal vector transformed by the world matrix (since I don’t want to texture map the diffuse lighting onto the 3d model in model space; this will cause the lighting to be “static” – i.e. when the model rotates the lighting values won’t change to reflect the change in orientation).
The specular component is is done per-pixel because per-vertex specular highlights usually look terrible (there are some other issues in general, but this was the main one for zerospace). For the specular lighting there is really only 1 light, a single directional light pointing down the z-axis. However, there are 8 view vectors and the specular computation is done between the single light and each of the 8 view vectors. I came up with this hack as I found that experimenting with multiple lights was more difficult than experimenting with multiple view vectors (different light vectors would cause either a too extreme or too weak specular highlight). Anyway, I do the specular computation with an exponent of 7, and I them multiple the results by 0.075 to dull the highlights.
One final note, the screenshot is no longer 100% accurate of the lighting system . I just found a major (and stupid!) mistake where I was multiply the ambient and diffuse components together instead of adding them. However, what I described above should stay the same, I just have to tweak some values to prevent the lighting from being too bright or too dark.
Also, on a more final note, this is not the complete lighting model for zerospace. Lighting from weapons, particles, etc. will also be taken into account.