Bump Mapping
(c) 1995 Brian Lingard
Introduction
This article will briefly summarize Blinn's method for performing bump mapping and will skip over some of the mathematical detail. Interested readers should consult the references given at the end. An example of applying bump mapping to the task of embossing is given in the second section, along with some sample images and source code.
Blinn's Method
In 1978, James Blinn presented a method of performing what is called bump mapping. Bump mapping simulates the bumps or wrinkles in a surface without the need for geometric modifications to the model. The surface normal of a given surface is perturbed according to a bump map. The perturbed normal is then used instead of the original normal when shading the surface using the Lambertian technique. This method gives the appearance of bumps and depressions in the surface.
A similar method for adding wrinkles to surfaces is displacement mapping. Displacement mapping is applied to a surface by first dividing the surface up into a mesh of coplanar polygons. The vertices of these polygons are then perturbed according to the displacement map. The resulting model is then rendered with any standard polygon renderer. But to achieve a fine resolution in the texture of the wrinkles, the additional polygons would get ever smaller and more numerous, placing a tremendous burden on the renderer.
Blinn saw that instead of using the perturbed vertices to calculate normals used in shading, why not perturb the original surface normal. The perturbed normal would then be used in the Lambertian shading equation. One problem with this method is that the simulated wrinkles would not extend all the way to silhouette of the object. To implement bump mapping, a way must be found to perturb the surface normal that is independent of the surface's orientation and position. This requirement arises from the observation that if a bump mapped object was being animated, we would not want the surface wrinkles to change shape or appearance. Thus we should base the perturbation function on the local surface derivatives.
We can parameterize a surface of an object using the function O(u,v), letting this function be the position vectors of this surface. Thus the surface normal N is given by:
where O_u and O_v are partial derivatives of the surface at point O.
We can define two other vectors, A and B, that lie in the same plane, which when combined with N form a coordinate system that is independent of the surface's orientation and position. Using components of these two vectors, we can derive a perturbation vector D. Mathematically, we can see:
and
where B_u and B_v are partial derivatives of the bump map B(u,v).
The perturbation vector D is added to the original surface normal N to obtain a perturbed normal vector N prime or N' = N + D. The formal proof of the method is left as an exercise for the reader. The process of calculating perturbed normals is performed for every point on the surface O. This method can be combined with the scan line algorithm for shading polygons.
One difficulty that arises with this method is that when the surface is scaled by a factor of two, the surface normal is scaled by a factor of four, but the perturbation vector is only scaled by a factor of two. This has the effect of smoothing out the simulated wrinkles. We can derive a D which is scale invariant by:
It is possible to address the problem of the silhouette lacking the bump mapped wrinkles by combining this technique with displacement mapping only those regions close to the silhouette.
An Example: Embossing
A popular feature of image processing programs on computers is that of embossing images. Embossing an image or painting is exactly analogous to the process of bump mapping. The source image can come from many sources including text, scanned in logos, etc.
John Schlag's Graphics Gems IV note applies a method similar to Blinn's bump mapping to embossing an image. Given in this section is a brief summary of his gems note and an explanation of some sample code using his embossing function.
We can consider a bump map image as a 3D surface P(u,v), and we can interpret the intensity values of the bump map image as height displacements. Thus black pixels having an intensity of 0 would be low heights, and white pixels having an intensity of 255 would be high. The surface normal can be derived using partial derivatives as in Blinn's method. We can express P(u,v) as a vector:
where i(u,v) is intensity at (u,v), and have the surface normal N at point P as:
where i_u and i_v are partial derivatives of i(u,v).
The partial derivatives of i(u,v) can be estimated by convolving the bump map image with the following masks:
These masks will blur the resulting image somewhat since they are 3x3 masks, and will actually help to antialias sharp edges. The response of the masks must be compensated for by scaling either i(u,v) or by scaling the z component of the normal vector N. The scaling factor regulates the width of the translation region or "bevel". This can help control the apparent depth of the embossing effect. The sample embossing code "emboss.c" found in Graphics Gems IV, uses the width formula:
which is based on assuming i(u,v) = au, and after convolution yielding i(u,v) = 6a. The parameter 'w' is used to control the width of the bevel.
Decent shading results can be obtained by using the Lambertian shading formula N dot L / (mag N * mag L). Several optimizations can help speed up the processing like pre-multiplying some terms and noticing that many of the pixels in the map image may be black and thus yield the same shading values. These can be pre-computed by [0 0 1] dot L. The shading result can be used for a grey scale image or applied against another texture image to get color.
An example program using Schlag's embossing code is given in the file "embdemo.c". This program produces simple grey scaled images in a ".img" format described in the source code. Some code to bump map any grey scale image either by itself or onto a texture image is given in "bumpdemo.c". This code uses some functions found in "imagfile.c" and "imagfile.h" to read and write standard 24-bit Windows Bitmap (BMP) files. The Bumpdemo program reads in the bump map image and converts it from an RGB 3 byte per pixel image to a grey scale 1 byte per pixel image. If a textured image is desired, a texture image is read in next. Schlag's embossing function is called to perform the actual bump mapping. The resulting embossed image is output to a BMP image file. There is also a "makefile" for compiling the executables. Shown below are some examples produced by the bump map demo program, top left is source bump map image, top right is just the embossed bump map, and both bottom images are embossed texture images:
[input image] [ouput image1]
[ouput image2] [ouput image3]
References
Blinn, "Simulation of Wrinkled Surfaces", Computer Graphics, (Proc. Siggraph), Vol. 12, No. 3, August 1978, pp. 286-292.
Max and Becker, "Bump Shading for Volume Textures", IEEE Computer Graphics and Animation, July 1994, pp. 18-20.
Schlag, "Fast Embossing Effects on Raster Image Data", Graphics Gems IV, AP Professional, 1994, gem VIII.1, pp. 433-437.
Watt and Watt, Advanced Animation and Rendering Techniques, Addison-Wesley, 1992, pp. 199-201.
------------------
lingard@wpi.wpi.edu