For Blender: 2.44 - Version française pas encore disponible(fr)

Normal maps versus Bump maps

These are different tools, to be used at the right moment, with the right conditions. None should be considered better than the other, and sometimes, they should be combined/mixed in order to get the best results possible. They all rely on the normals of a given object, so this is the first thing we will try to adress in this article) : what's a normal?

A normal is a vector perpendicular to the surface, at the given point. In polymodeling, as complex surfaces are made of small planar faces, you can assume that there is only one true normal by face but as much normals as there are faces. This is easily viewed in Blender. For example, select your model, and then go into Edit mode [Tab]. In the Editing buttons [F9], look for the Mesh Tools 1 panel. It contains several buttons of interest, especially Draw Normals (displays normals as blue lines) and NSize (changes the displayed length of the blue line for better visualization). A normal vector has a length equal to one unit.

normals displayed

Bump maps

A Bump map is basically a greyscale image that will tell, for each pixel of the rendered surface, if the local normal length should be scaled. If not, the pixel will be interpreted as laying on the 'ground' level of the face (middle grey pixels of the Bump map) ; if yes, it will be interpreted as laying above the ground (dark pixels of the Bump map) or under the ground (light pixels of the Bump map) ; a 50% grey will mean no scaling of the normal. A Bump map basically simulates embossment of the surface, effecting the shading by virtually displacing the rendered pixels along the normals.

bump render example
On the right, you can see the greyscale image used for the Bump, and on the left, the rendered result

To get a Bump effect, you need to associate a greyscale texture (it could be an image or a procedural texture) to a texture channel, and activate the Nor option in the Map To panel of the Material buttons. Use the Nor slider, in the same panel, in order to modulate the intensity of the Bump effect.

The Nor button has three states:

  • off : the texture channel doesn't affect the rendered output
  • on (white) : the texture channel does affect the rendered output
  • on (yellow) : the texture channel does affect the rendered output but the normals are inverted (bumps become crevices)

Map to tab
The Map To tab, showing the Nor option and its slider

And what about Displacement maps?

Very much like the Bump map, the Displacement map will use a greyscale image in order to actually displace the polygon along its normal according to the value stored in the texture. It is really efficient with a finely subdivided or subsurfed mesh. You can check the Displace modifier in order to learn more about this, as it is beyond the scope of the article : Bump maps and Normal maps actually fake complex surfaces on simple geometries, where Displacement maps need a very dense geometry to be effective at all.

displace modifier

Normal maps

In the case of the Normal maps, the normals vectors are all normalized (e.g., they have the same length equal to one unit) and a color image is used to tell, for each pixel of the rendered image, what is the simulated orientation of the local normal at the pixel. The Normal map basically simulates the local orientation of the surface by virtually rotating the pixel according to the normal. The normal effect will be quite visible even with not (or a little) specular materials. To get a normal effect, you need to associate a color texture (an Image type one, because normal maps need special tools to be produced) to a texture channel, activate the Nor option in the Map To panel, as previously, but also to activate the Normal Map option in the Map Image panel of the Texture buttons [F6].

map image panel
The Map Image panel with the Normal Map button enabled

Baking Camera Space Normal Maps within Blender

Since version 2.43, Blender is able to bake Camera Space normals into the texture of an object. This is only a first step toward a proper production of Normal Maps with Blender, because Camera Space suffers from some limitations : the normals baked are only used with the object with the same location/rotation/size versus the same location/rotation/aperture of the camera. If either the camera or the normal mapped object are moved, deformed or animated in any way, then the normals will look wrong.

I read about other normal map types, what about them?

Of course, more Normal map types exist, that could be more useful or handy : with an Object Space normal map, animations of non-deforming objects could be carried on ; with a Tangent Space normal map, you could also animate deforming objects (using armatures, shape keys, softbodies, lattices, whatever) while retaining a decent normal visualization. But unfortunately, Blender is not able to bake these kind of normals at the moment, so you will have to rely on external tools to build efficient Tangent Space normal maps.

Baking the Camera Space normal map into the texture of an object is pretty easy. Select the object you want to bake, and UV unwrap it ; in its UV/Image editor, add a new image (menu Image > Add...) and then go in the Scene menu [F10]. In the Bake tab, choose the Normals option and hit the BAKE button. Then don't forget to save the Normal map, in the file format of your choice (Targa is the default, PNG tends to be very convenient).

baking tab
The baking tab

Of course, baking the normals of a mesh in order to use it with the same mesh is almost pointless. The interest is to use this baking facility with multi-resolution meshes. For example, you start with a low poly mesh that you unwrap, as specified before. In the Editing menu [F9], find the Multires panel and click the Add Multires button. Add Level and start sculpting your mesh, adding details along with levels. When you are satisfied with you sculpting, you then can check that the maximum Rendel level is set and proceed with the baking, just as exposed before.

normal map
Example of Normal map baked within Blender from a high level multi-res of a sculpted cube

normal mapped cube
Example of render result, from left to right: normal lowpoly cube, highpoly and sculpted multi-res cube, and normal lowpoly cube with Normal map issued from the sculpted highpoly cube

In the previous image, the Normal map has been computed in the Camera Space for the central cube, but applied to a lowpoly instance of the same cube, slightly on its right. Of course, at first glance, the fact that the normals are wrong (they are not exactly in the same Camera Space) is not easy to spot in this still shot, but within an animation, wrong shadows will quickly betray the wrong Normal map. For example, in the first video, you can see the highpoly cube bouncing and spining. In the second video, you see the lowpoly cube, on which has been applied the Camera Space Normal map : it should be obvious to you that something in the shading is wrong, if you carefully look at the central bump of each face.

Video of a highpoly cube that has been sculpted


Video of a highpoly cube that has been sculpted

Video of a lowpoly cube that has been normal mapped in Camera Space : the shading is slightly wrong


Video of a lowpoly cube that has been normal mapped in Camera Space : the shading is slightly wrong

These video should be a good illustration of how much Camera Space could be useless when used on objects that actually move or are relocated in a different location than the one the Normal map has been built from. Unfortunately, as stressed before, the Camera Space Normal map is the only one that Blender actually knows how to built. Object Space Normal map would have been slightly better for this bouncing cube, as it is a rigid model. Finally, only a true Tangent Space Normal map would have been useful at all with a deforming object. The last part of this tutorial is about how to produce such a Normal map, with external tools, and how to use it within Blender.

Using DNormGen for building Tangent Space Normal Maps with Blender

There are many free tools available on the web for building Tangent Space Normal maps, but only a few are available for many OS at the same time. One of these, actually stands out as having a quite good support for Blender, is the Drag[en]gine Normal Map Generator and is available for Windows, Linux and Os X. Source codes are also available under GPL v2.0.

Go to the Downloads section and select the package you want to use. There are dependencies to solve for Unices and Os X, but nothing too fancy (libfox1.4, libfox1.4-dev, libpng3, libtiff4, libxmu-dev are a few examples) and perhaps link the libtiff.so.3 to libtiff.so.4 (sudo ln -s libtiff.so.4 libtiff.so.3).

Once DNormGen has been extracted, pay attention to the dnormgen exectuable and the dragengine_dim_export.py file in the scripts/ directory. There are also numerous good information on the usage of the tools in the README file.

The Blender script that is shipped with the tool will take two models : the lowpoly one should be named *.low (in the OB: field) and the highpoly one should be named *.hi (* being the original name of the object). This is absolutely mandatory for the script to work, and could be done in the Link and Materials panel of the Editing menu [F9] buttons. It will then export the two models in the .dim format, which is specific to the normal generator tool. Then this tool will be able to build a Normal map from this .dim file.

1st step : From Blender

There are quite a few steps to do within Blender, before using the script, like renaming the objects, setting Subsurf on the highploy one, and selecting the two objects to export. The exact procedure is as follow :

  1. Select your low poly object and add to its name, in the OB: field, the extension .low. Unwrap it, give it a material (if it doesn't already have one) and a texture (Image > New... in the UV/Image editor) that you won't forget to save (Image > Save or Image > Save As...).
  2. Now select your high poly object and add to its name, in the OB: field, the extension .hi.
  3. Add a Subsurf modifier to the highpoly model (a Level 0, as specified in the documentation, is no more possible in Blender whose minimum is 1; if you don't want to alter the shape, use Simple Subdiv. option instead of Catmull-Clark).
  4. Select the two objects : the lowpoly one and the highpoly one.
  5. Change one of the views into a Text Editor. Use File > Open... in order to load the dragengine_dim_export.py script. Hit [Alt]+[P] with the mouse cursor pointer in the Text Editor to run the script, choose a name for the exported .dim file (or accept the default one).

That's it for the part to be done within Blender. You should now have one .dim file that you can feed the DNormGen tool.

2nd step : From DNormGen

When you run the DNormGen tool, you will get two distinct windows :

  • DE Normal Map Generator : this window will show the 3D models (lowpoly, highpoly) and will let you configure the kind of map you need (Displacement map, Normal map, Tangent Space or Object Space, etc.)
  • Texture Preview : this window will show the resulting maps.

At first, you will need to load the previously created .dim file in the DE Normal Map Generator (File > Open...). The original low poly should appear on the screen. Using the Left Mouse button, you can click and drag the 3D object to make it rotate around its center. You can also zoom in or out by holding [Shift] down and using, the very same way, the Left Mouse button.

Now you can check and explore the View menu. You can decide to show the Lowpoly model or the Highpoly model. If the maps have already been computed, you can also show them in this window.

The next step, for the generation of a Tangent Space Normal map lies in the Texture-Maps menu : you will have first to define the Texture Maps Size, by setting the Height and Width. These parameters defaults to 256.

set texture dimensions

Now, you can proceed with the generation of the Normal map. In the Texture-Maps menu, select Generate Normal/Displacement Maps and pay a few seconds attention to the poping options window.

generate texture maps

At first, you need to specify if the Highpoly should be smoothed before proceeding (check box Smooth Hi-Res Mesh Normals)  then, you can select the kind of Normal Space map you need (radio button Tangent-Space or Object-Space).

Accepting the options, the texture map is generated, and the Texture Preview window automatically updated. You will note that it shows the UV coordinates set on the lowpoly object, and that the newly computed Normal map fits the proper space. In the Texture-Maps menu, don't forget to Save Normal Map in the location of your choice. It should default to a normal.tga name.

denormgen in action

I have some troubles, please help!

  • The borders of my Normal map are slightly messed? In View > Set Hi-Res Mesh Options, increase very slightly the Vertex Offset option. Alternatively, using a greater map could help, too.
  • The bumpiness given by the Normal map is not strong enough? In Texture-Maps menu, select Apply Detail Normal Map and experiment with the Strength value. Applying it with the default Strength of 50 could lead to dramatic results, so use purposefully.
  • I read somewhere that the Green layer of my Normal map should be inverted. Is that true? It used to be true, yes, but Blender's normal mapping now is fully compatible since v2.43 (previously the scale of the Z vector differed). So you don't have anymore to invert the Green channel in a software like The Gimp in order to use DNormGen normal maps within Blender if you use the latest versions.

3rd step : Back to Blender

You now have a correct Tangent Space Normal map to be used in Blender. Select the Lowpoly model you unwrapped a few minutes ago. In UV Face Select mode, in the UV/Image editor, discard any temporary map you might have and load the normal.tga built by DNormGen using the menu Image > Open... In the Material buttons, menu Shading [F5], check the Shaders tab and activate the NMap TS button.

In the Map Input tab, the texture should use the UV coordinates, and in the Map To tab, it should be set to Nor channel (invert it if you feel the shading is wrong).

Finally, in the Texture buttons, in the Image Map panel, check that the Normal Map button is activated and that the map selected in the Image panel is the normal.tga built by DNormGen. Save [F2] your project, that's it, you are done with a Tangent Space Normal mapped lowpoly model!

Video of a lowpoly cube that has been normal mapped in Tangent Space : the shading is correct, the map being perfectly suitable for animations and deformations


Video of a lowpoly cube that has been normal mapped in Tangent Space : the shading is correct, the map being perfectly suitable for animations and deformations