Creating a Bump Map Shader - Part 1/2

Parts > 1 | 2

Note: A complete example of this code is available: BumpMapShader.zip

Introduction

In the previous HLSL tutorials, we have done lighting and texturing. All of this can be done with the BasicEffect class with ease. But now we are going to move on to a more sophisticated shader that will do bump mapping. Bump mapping is a method where you use a texture to make it appear like a model has a lot more detail than it really does. Usually, this detail is in the form of bumps, but it isn't really limited to this. You can also do quite a bit of detailing with bump maps. In fact, there are programs out there that will take a low detail 3D model and a high detail 3D model and create a bump map for the low detail model that will make it look almost the same as the high detail model.

I have split this tutorial into two parts. In this first part, we will look at how bump mapping works, as well as the general process of creating them. I will also show you a couple of different ways that you can create bump maps. This way, we will be able to create all of the content that we need for our XNA game and our bump mapping shader. In part two, we will go over the actual shader and the changes we will need to make in our XNA game.

Below is an image of the final outcome of our shader. I'll be the first to admit that the bump map I used is not the best for this object, nor is this object the coolest object to demonstrate bump mapping on, but it will do.

screenshot1.png

All Kinds of Maps

The first thing we need to talk about is how we are going to actually do bump mapping. Probably the most common method of bump mapping is called normal mapping. In normal mapping, we will create a texture (or map) that stores the normal for the point. In the normal map, the normal is represented as a color.

Usually, the process starts with the texture map. For the helicopter that I've been using, the texture is below:

HelicopterTextureMap.png

This is just a simple texture, and many models will have much more sophisticated textures. I just have a few blocks of color for various parts of the helicopter. The main light blue color is the body of the helicopter, the darker blue is the glass window, the yellow is on the rotors' edges, the black is the rest of the rotors, and the white is a sort of stripe on the tail of the helicopter.

We will need to create a normal map that lines up with this texture map. However, determining the normals at every point in the texture and coloring the normal map is not a simple process. It is a little easier to create yet another kind of map called a heightmap. Below is a height map that I created for the helicopter. You can see that it lines up with the various parts of the helicopter texture.

HelicopterHeightMap.png

Height maps are usually grayscale images where lighter colors represent high "elevations" and dark colors represent low elevations. These are usually pretty easy to make in an image editing program, and we will talk a little bit more about how to make them in the next section. You can see that some of the regions I have made perfectly flat because they are all the same color. The window (lower right corner) has some roughness to it because the glass is never perfectly smooth. The body of the helicopter is fairly bumpy.

Once the heightmap has been created, we can generate a normal map from it. There is a simple algorithm that is used to create a normal map from a height map, but we don't need to worry about it, because we will just use some free software to calculate it. Below is the normal map for the helicopter.

HelicopterNormalMap.png

Normal maps always end up looking kind of bluish and reddish. Each pixel indicates what the normal is like at that point in the texture. In this method of normal mapping, these values indicate how the normal at this point is different from what the normal should be like without the bumps. In other words, we will need to still factor in the regular normal in with the value of the normal maps. It is less frequent, but occasionally, people will make a normal map that stores the exact normal of the texture, so you don't need to factor in the regular normal. These normal maps end up looking more like a rainbow because you'll see lots of greens and yellows as well. If you do a Google image search for "normal map" you will most likely find examples of both, but you'll see that the reddish-bluish ones are more common.

Generating Height and Normal Maps

There are many tools out there that will create normal maps for you. I will walk you through the process that I usually use because it involves only free tools. Usually, I will create my heightmap with the same program that I use to create my regular texture map. You can use any program you want, but it needs to be able to export images in the .tga file format. Both Photoshop and Paint.NET (which is free) can do this. If not, you will need another way to convert your image file to a .tga file, because the program that we will use to create the normal map requires .tga files for input. If you are using Paint.NET, when you save a .tga file, be sure to turn off the compression, because the tool we will use does not know how to deal with a compressed .tga file.

Once you have the heightmap, you are ready to create the normal map. I usually use a free tool called xNormal, which can be downloaded from the xNormal downloads page. Once you've got xNormal installed (it may take a few minutes, and it will probably install a variety of other libraries that come up as separate installations) it should be pretty easy to make your normal map. xNormal actually has a ton of features, and we're only going to use one of them for what we're doing. Open up xNormal and look on the right side. There you'll find a button that says Tools. Click on that to open up the Tools window. Click on the one that says Height map to normal map and a new window will pop up to allow you to create your normal map. On the Height map side, right-click and choose Browse height map. Find the height map file you want from the file system. Then go over to the Normal map side, right-click, and choose Generate, and the normal map will be generated for you. Right-click in the Normal map side again, and choose Save normal map and save your generated normal map out to file.

Remember that you'll need to add your normal map file to your XNA project like usual.

Once you have created a good normal map, you are ready to continue on to part 2, where we will create the actual bump map shader and use it in an XNA game.

Parts > 1 | 2


Troubleshooting.png Having problems with this tutorial? Try the troubleshooting page!