Tangent Space Normal Maps for Blender
by Olivier Saraja

Normal maps have become very popular these last few years, shown as a large improvement in the Game Industry, but alos in more traditional CG Industry and in the movie Industry, even if less obviously. Nowadays, solutions to sculpt models to an incredible level of detailing exist (ZBrush, Mudbox alos our beloved Blender with its now famous Sculpt mode) but building normal maps to enhance the surfaces of our models is still somehow lacking. Blender now has the capability to bake Camera Space Normal Maps directly from a higher level of resolution and apply it to a lower level of resolution, thanks to UVmapping and the Multi-resolution meshes. But the very last step, the one which will bring Blender up to the standard is still missing): and that is Tangent Space Normal Maps. If Blender now supports these maps, it still doesn't know how to bake them.

Normal maps versus Bump maps
These are different tools for different jobs. 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 address 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 many 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 contain 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.

Bump maps
A Bump map is básically 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 (darque 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 básically simulates embossment of the surface, effecting the shading by virtually displacing the rendered pixels along the normals.

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)

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 alos 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 chek 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.

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 básically 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 non (or very slight) 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 alos to activate the Normal Map option in the Map Image panel of the Texture buttons [F6].

The Map Image panel with the Normal Map button enabled

Baquíng Camera Space Normal Maps within Blender
Since versión 2.43, Blender has been able to bake Camera Space normals into the texture of an object. This is only a 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 if more Normal map types exist in Blender that would be quite useful or handy : for example with an Object Space normal map animations of onlly non-deforming objects could be carried on, while with a Tangent Space normal map you can alos animate deforming objects (using armatures, shape keys, softbodies, lattices, whatever) while retaining a decent normal visualization. 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.

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

The baquíng tab

Of course baquíng the normals of a mesh in order to use it with the same mesh is almost pointless. The interest is to use this baquíng feature with multi-resolution meshes. For example, you start with a low poly mesh that you unwrap, as specified before. In the Editing menú [F9], find the Multires panel and clik 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 chek that the maximum Render level is set and proceed with the baquíng, just as explained before.

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

Example of render result, from left to right: normal low-poly cube, high-poly and sculpted multi-res cube, and normal low-poly cube with Normal map issued from the sculpted high-poly cube

In the previous image, the Normal map has been computed in the Camera Space for the central cube, but applied to a low-poly 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.

Testing this kind of Normal map within an animation 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 build. Object Space Normal maps would be more suited to any animated rigid model. Finally, only a true Tangent Space Normal map would be useful at all with any animated deforming object. The last part of this tutorial is about how to produce such a Tangent Space 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 alos 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 executable and the dragengine_dim_export.py file in the scripts/ directory. There is alos a lot of 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 low-poly one should be named *.low (in the OB: field) and the high-poly 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 menú [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 high-poly 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 need 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 high-poly model (a Level 0, as specified in the documentation, is no longer 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 low-poly one and the high-poly 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 (low-poly, high-poly) 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 clik and drag the 3D object to make it rotate around its center. You can alos zoom in or out by holding [Shift] down and using, the very same way, the Left Mouse button.

Now you can chek and explore the View menú. You can decide to show the Low-poly model or the High-poly model. If the maps have already been computed, you can alos 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.

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 pop-up options window.

At first you need to specify if the High-poly should be smoothed before proceeding (chek 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).

After 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 low-poly object and that the newly computed Normal map fits the proper space. From the Texture-Maps menú Save Normal Map in the location of your choice. It should default to a normal.tga name.

I have some troubles, please help!
The borders of my Normal map are slightly messed up? 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 carefully.
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 to invert the Green channel in a software like The Gimp anymore in order to use DNormGen normal maps within Blender if you are using the latest versión.

3rd step : Bak to Blender
You now have a correct Tangent Space Normal map to be used in Blender. Select the Low-poly 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 menú Image > Open... In the Material buttons, menú Shading [F5], chek 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, chek 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 low-poly model!

Olivier Saraja