The first derivative of the height values of the bump map in a given direction s',t' can be approximated by the following process:
Consider a one dimensional bump map for simplicity. The map only varies as a function of s. Assuming that the height values of the bump map can be represented as a height function F(s), then the three step process above would be the following: . If the delta is one texel in s, then the resulting texture coordinate is , where w is the width of the texture in texels. This operation implements a forward difference of F, which would approximate the first derivative of F if F was continuous.
In the two dimensional case, the height function is F(s,t), and performing the forward difference in the direction of s',t' evaluates the derivative of F(s,t) in the direction s',t'. This technique is also used to create embossed images.
This operation provides the values used for the first two addends shown in Equation 1. In order to provide the third addend of the dot product, the process needs to compute and add the transformed z component of the light vector. The tangent space transform in Equation 2 implies that the transformed z component of L is simply the inner product of the vertex normal and the light vector, . Therefore, the z component can be computed using OpenGL to evaluate the diffuse lighting term at each vertex. This computation is performed as a second pass, adding to the previous results.
The steps for diffuse bump mapping are the following:
Using the accumulation buffer can improve the accuracy of this technique. The bump mapped objects in the scene are rendered with the bump map, re-rendered with the shifted bump map and accumulated with a negative weight, then re-rendered again using Gouraud shading and no bump map texture, accumulated normally.
The process can also be extended to find bump mapped specular highlights. The process is repeated using the halfway vector () instead of the light vector. The halfway vector is computed by averaging the light and viewer vectors . The combination of the forward difference of the bump map in the direction of the tangent space and the z component of approximate . Here are the steps for computing :
The result must be raised to the shininess exponent before blending.
One technique for performing this exponential is to use the texture color table extension to perform a table lookup on the results of . Invoke glColorTableSGI() with GL_TEXTURE_COLOR_TABLE_SGI as its target, then enable GL_TEXTURE_COLOR_TABLE_SGI. Copy the image calculated above from framebuffer memory into texture, using glCopyTexImage2D(). Finally, apply a projective texture transformation or calculate texture coordinates so that the specular component is mapped onto the object with the same screen coordinates in which it was drawn. Pixels copied from other objects drawn will not fall on the bump mapped object and will be discarded. It is a good idea to copy only the rectangular screen region that bounds the bump-mapped object if the application supports this. If the texture color table extension is not available, it may be possible to use glReadPixels(), glTexSubImage2D(), apply the exponent on the host, and still retain interactivity for small regions.
Another possibility is to use glCopyPixels() with a color table configured with glPixelMap(). The bump mapped object can be applied to the stencil buffer to create a mask so that only the pixels covered by the bump mapped object are applied to the framebuffer.
Finally, use blending during the application of the specular component to add to the diffuse component and complete the lighting equation.