Bump mapping

Bump mapping

In computer graphics, the bump mapping is a technique to simulate bumped surfaces (3D graphics) or bumped images (2D graphics).

In 3D graphics, bump mapping is a surface rendering technique used to simulate bumped surfaces without changing the model geometry (without increasing the size of the 3d model description).

As example, here a flat textured surface and the same one with a bump mapping effect applied on. The result is simply a more realistic rendering.

Elementary surface and light

The idea is to consider that each pixel is an elementary oriented surface, in a 3D space, on which a light is applied. Then, the light intensity is depending on the surface orientation (given by the normal vector) and the light orientation:
In order to compute the normal vector at every pixel on the surface, we need to know the altitude of each pixel, this information is given by a height map which is commonly a grayscale bitmap. Each gray value represents a height value:

Normal vector computation

If we consider that a pixel is an elementary surface centered in a 3D space (i.e. the height is equal to zero at center of this surface), the equation of the tangent plan including the point (0,0,0) is given by:

As the point (0,0,0) is at the middle of this plan and the origin of the axes, then h(0,0)=0, moreover by the use of the finite differences, we also may consider:

Finally, the equation of the plan can be computed like this:

In our 3D space, that means that for any point (x, y, z) of the elementary surface the equation is true. If we consider this point as the coordinates of a 3D vector, this equation is done by a dot product:

That means the vector (dh/dx, dh/dy, -1) is perpendicular to the surface. This is our normal vector, but not normalized.

Another approach can be geometrical:

If we consider the both vectors (dx, 0, dzx) and (0, dy, dzy) as the directing vectors of the plan, the normal vector is the cross product of the both vectors, so (dzx/dx, dzy/dy, -1), or with our notation: (dh/dx, dh/dy, -1).

As we consider each pixel as an elementary surface, we can compute for a given y (using finite differences) x and h according to this approximation:

The same approach can be done for computing y and h, for a given x. That gives us these formulae:

So, the formlae used to compute the x and y normal vector coordinates are:

z/x = heightmap(x+1,y)-heightmap(x-1,y)

z/y = heightmap(x,y+1)-heightmap(x,y-1)

Finally, if this normal vector is normalized, we have to compute its z coordinate:

With this formula, we can fill the lookup table commonly called environment map. Note that z² and z are both in same range 0 to 1.0 and we sometimes found the first formula (z²) used to fill the lookup table.

Now, by using the heightmap and this lookup table (called environment map), it is quite easy to retrieve the z coordinate of the normal vector and then to compute the brightness of the pixel according to the light direction (basically, a dot product).

Note that for the formulae described above we assume that the height map contains values that ensure z/x and z/y to be normalized.

The environment map

In my code I use three different environment maps, filled with three formulae from the original linear formula:

To create such a lookup table, I have created a small tool (that you can download in the download section). This utility let you create these three lookup tables.

All you have to do is to select the formula and generate the binary file. In the HB++ example projects, the binary files are included as binary resources and used by a dedicated class.

The generated environment maps use 5 bit signed integer numbers (from -16 to +15).

Some words about the HB++ projects

You can select a spot light or a directional light.

Spot light: the light is always perpendicular to the image and in order to avoid the dot product computation we use the environment map to simulate the decreasing light, as shown below:

Directional light: the difference between the image center and the position of the stylus is considered as the light angle (for both axes).

So, by moving the stylus, with spot light mode we change the light position and with directional light mode we change the light orientation.

I let you experiment and change parameters to create nice effects.