Geometry Independent Interactive Lighting with
Orthogonal Illumination Maps
Cass Everitt
Abstract
One shortcoming of the OpenGL lighting model is that lighting calculations are only performed per vertex. This typically requires that applications oversample the geometry to produce many more vertices than would otherwise be required. In the same way that traditional texture mapping is used to enhance the complexity of a scene without additional geometry, orthogonal illumination maps can be used to enhance the complexity of the lighting in a geometry independent fashion. The technique of orthogonal illumination mapping is a multipass technique designed to shift the computational burden of lighting calculations from the geometry processing portion of the OpenGL pipeline to the fragment processing portion. This is appropriate since much of the recent work in OpenGL hardware has been to extend and enhance fragment processing capabilities.
Note
I will use the term multipass when referring to rendering techniques that take advantage of any of accumulation buffering, blending, or multitexturing to achieve their effects.
History
This section will need to discuss a lot, probably. There is a lot to be said for where texture mapping came from, what bump mapping is and where it came from. Robert, I will need some help from you on outlining what’s important to cover here.
Here is a first shot at what might be useful:
Orthogonal Illumination Maps
The texture-based bump mapping technique [Peercy, Cabral] describe requires computing texture coordinate biases per vertex that are somewhat expensive, but then amortizes that cost over the polygon interior. Orthogonal illumination maps require only a per frame calculation. The trade off is that this technique only applies to diffuse illumination by directional (or infinite) light sources.
The basics of the process are simply a reorganization of the diffuse illumination equation such that the operations can occur in the fragment processing stage of the OpenGL pipeline. Diffuse illumination is given by
C = (L . N) Cl * Cd (Equation 1)
Where Cl is the color of the light source and Cd is the diffuse color of the material. Typically what happens in an OpenGL application is that Cl, Cd, N and the light position (or direction) are specified and OpenGL evaluates the equation at each vertex.
First, we need to decompose the dot product in order to move the evaluation of this equation out of the geometry processing.
L . N = Lx * Nx + Ly * Ny + Lz * Nz (Equation 2)
Equation 2 begins to look like something that could be implemented with a multipass technique, except that the components are signed and our fragment processing is generally clamped to the range [0,1]. To deal with this, we will split each normal component as follows:
Nxp = clamp(Nx, 0, 1)
Nxn = clamp(-Nx, 0, 1)
Nyp = clamp(Ny, 0, 1)
Nyn = clamp(-Ny, 0, 1)
Nzp = clamp(Nz, 0, 1)
Nzn = clamp(-Nz, 0, 1) (Equation 3)
Now we can rewrite Equation 2 as:
L . N = Lx * Nxp + Ly * Nyp + Lz * Nzp – Lx * Nxn – Ly * Nyn – Lz * Nzn (Equation 4)
If we make each of Nxp, Nyp, Nzp, Nxn, Nyn, Nzn become a luminance texture and we use the GL_TEX_ENV of GL_MODULATE, we can factor the Lx, Ly, and Lz terms into the object’s color in separate rendering passes. Since half of the terms are negative, three of the passes will require subtractive blending. To avoid clamping problems, all the additive passes should occur first.
The following algorithm demonstrates the sequence of operations assuming Lx, Ly, and Lz are non-negative.
Simple conditionals on the sign of Lx, Ly, or Lz can be used at each of the 6 passes to determine which texture to load and to possibly flip the sign of Ctemp (in the case of negative components).
Ok – I’m done for now. I will pick it back up when I regain my cognitive skills.