Normal mapping in Blender

This image provides a quick idea of the pros and cons of normal maps:



Now, let's talk technicality! To use something as complicated as normal maps, you need to know what they do and how they do it. We'll start at the beginning. Don't worry if you don't get it all; it'll be much easier to comprehend when you've given it a try or two.

Normals
In order to display objects, your computer shows you the result of light bouncing off of your objects and then looks at what angle it is from your point of view; this is how it works too in real life. To calculate this, the renderer needs to know what angle your faces are at. This direction is a normal; a vector that points from the center of a face or a vertex. In Blender, they're represented as cyan lines. Activate them by going to Editing (F9) -> Mesh Tools More and turning on Draw Normals and Draw Vnormals when in Edit Mode.



The Nsize parameter here is just a lie for easier visualisation; they always have a length of 1.

Calculating the angle of these face normals is rather easy; they're just perpendicular to your face. There is just one problem here; you may want something to look round. With this kind of shading, you'll have to insert a lot of polygons to make something look round.

So instead, smooth normals were invented. You're already familiar with what they do. They create vertex normals, which are the average of the face normal they're connected to. Then, something called Gouraud shading – named after Henri Gouraud – comes in and makes up averages for every pixel on your screen that displays a face. The normals are still the same, but you get an infinite amount of in-between normals. It's a good way to trick your eyes into thinking something is round, even when it's just as flat as it was with solid shading.

In reality, solid shading uses this algorithm too, but with one vital difference. Smooth shading creates vertex normals which are an average of the surrounding face's normals. Solid shading makes multiple vertices out of them and assigns one to each face with a normal that is exactly the same as that for the face. When creating averages between face normals and vertex normals that are exactly the same, the result is the same too and the whole face has one normal – one angle. For ease of editing, the multiple vertices are treated as one, but here is how your renderer sees things:



Gouraud isn't perfect either, though, because its data is still limited to the amount of inputs. Simply said, the more geometry you have, the better it looks. The problem is that adding geometry is exactly what we don't want to do, because we're working with a budget. Normal maps are a good solution here.

Every texture consists of texels. They are the pixels in your image, but mapped onto a 3D object and they're called texture pixels – texels, for short – to distinguish them from pixels on your screen (because as you can see, every texel takes up multiple pixels on this image).

Normal mapping does this: it assigns a normal to every single texel you have. What this means is that, regardless of it actual shape or direction, your image tells the renderer which way every single texel is facing for lighting purposes. And with these angles, you can easily create fake roundness, fake hardness or even fake depth. It creates the illusion of a shape that isn't there.

There are multiple ways of doing this, but we'll be going over tangent space normal maps. Object space normal maps are useful at times, but they have their own flaws and they're a whole different can of worms.



Now, how does one store directions in an image? By coincidence, vectors – such as normals – consist of three values (x, y and z) and colours consists of three values too (Red, Green and Blue). All it does is use the RGB values and puts them in the x, y, z channels. Not all combinations are possible since the coordinates have to form a vector that has a distance of exactly 1. What this means is that there's a sphere of possibilities:



The sphere has all the values that make up a normal with a length of 1, originating from the center of the texel.



This is a normal map of a sphere onto a place. The edges all face outwards in x, y directions, while the middle points directly at us. It shouldn't be too hard to see this as a top-down sphere. Added are the RGB values for the outer edges for every 45 degrees and the dead center. While the exact reason for these specific numbers isn't terribly important, you should note something about the colours here:
The Red value is highest on negative x
The Green value is highest on negative y
The Blue value is highest in the center – that is, positive z.

Now, you may be wondering – why are Red and Green linked to negative x and y values? Wouldn't positive be just as useful? Yes, that would be just as good and it would make more sense – which is why every software other than Blender doesn't use this setup.

So let's reiterate: a normal map has RGB values ranging from 0 to 255. These are converted to x, y, z coordinates between 0 and 1. A normal is drawn between the face's center and these coordinates. This determines the angle of your texel.

Let's kick the practicality up a notch here, because nobody likes maths.
So, you know what a normal map can do and how it does it – more or less, anyway, experience is key here. Let's look at how you go about creating one. If your first thought is nVidia filter or GIMP, slap yourself. We'll be looking into baking.

You bake your information from a high-poly object to a low-poly target object. The high-poly has an unreasonable amount of polygons and any realtime renderer would clog up immediately. What we do is use its information to create a normal map for the object that we actually want to use.

What happens is that every texel you have sends out a ray along it's Gouraud (that's the standard) normal. Whenever it comes along another piece of geometry, it 'steals' the normal and stores it as an RGB value (as has been discussed).

So what you need to do is make a high polygon object that more or less fits the low polygon object that you're baking from. You'll need to take into account that the shape of the lowpoly determines the way the rays are sent out.



Remember that you're only taking the angle information from the highpoly, not the actual depth! This means that simple extrusions will not show up on your normal map.


So let's talk a little about those green rays in the image. They're baking rays sent out by the low polygon mesh. Blender uses two values for these rays: Dist (or Distance) and Bias. When the ray comes across more than one surface, it has to choose which one it uses the normal from. To choose, it looks at the Bias value; the surface of which the distance to the lowpoly object is closest to the Bias will be picked. A high bias value makes sure you'll always get the outer surfaces, but if it's too high, it might go so far as to take information from surfaces that weren't intended for that part of the lowpoly (this happens easily with fingers, where the rays from the sides go too far and find the high poly of the other fingers).
The Distance value is the maximum range that a ray will go to in either direction. Take not that this distance is measured from the Bias value, not from the target mesh!
Here is a confusing image: Everything outside of the Dist range is completely ignored; your rays never go there. Between that, only one value can be used for every texel, so the rays have to choose. There is a green overlay on the parts that are closest to the Bias (wether they have competition or not) and are thus used. Every piece of non-green line has a competitor with the same x-value, but closer to the red Bias line. Below is the resulting normal map – take note of the orange part; that's where the surface was pointing downwards and the Blue value is negative as a result. This obviously isn't a very good normal map of the subject. The solution would be to increase both the Bias and Dist values. Just increasing Dist still leaves you with the negative part and just increasing Bias leaves even more of the bottom uncaught.



A word of note here. The low polygon mesh should (almost) always have smooth shading. As we've learned before, hard edges duplicate their normals and have them face perpendicular to the polygon they belong to. This means that in corners and edges, some detail will be missed and some will be doubly baked.



Floating geometry. We know that depth isn't taken account, only the angle of the highpoly source. That means that your high poly geometry doesn't have to have the same depth as you want the normal map to appear to have. You can have details outside of the mesh. We call this floating geometry.

Note how, in the following image, none of the high poly elements connect; The highpoly of the indent in the middle sticks out and the indents on the screws aren't even part of the screws. Floating geometry is immensely useful for creating this kind of detail on (relatively) flat surfaces.



Chamfering
While, theoretically, a bake should perfectly represent the normals of the highpoly, this isn't entirely true in reality. Raytracing does display everything correctly, but real time renderers tend to have a lot of problems with 90 (or more) degree edges. As such, it's worth beveling those edges to have correct smoothing. Basically, your lowpoly should be shaded at least somewhat like your highpoly.

Doing something!
Yes, it's time to actually make a normal map now! Action time!

I'll be using a model that you can download here, if you want to work along or use it for reference.
Firstly, build the high and lowpoly, as you usually would. It's generally better to do the highpoly first, because it'll give you more of an impression what the final result would look like and is thus best to determine the proportions. It's how pretty much everyone works, but only the results matter here.



Once you've got the models, it's time to start UV-mapping.
A word of note here: I'll be mirroring parts. Blender does not support mirrored normal maps! It's currently listed as a low priority bug as opposed to a missing vital function of normal mapping. I'll be mirroring anyway, because every game engine save for the BGE can mirror and it's incredibly useful. Copying parts and using them in the same alignment (as with the teeth in my model) is possible.

Normally, you delete the parts that you want to be mirrored or duplicated and you duplicate and mirror the parts after UV'ing. We'll do that now too, but with one difference. Instead of having the duplicates' Uvs on the same space as the originals, we'll move them to outside the standard UV window. Textures tile here, and the end result will look the same, but only the UVs in the 0-1 range will be used for baking. Having overlapping Uvs will cause baking problems, since Blender isn't sure which results to use. So once you duplicated your parts, have their Uvs moved by 1. Oddly enough, the default size for the 0-1 UV space in Blender is 256 (as opposed to, you know, 1), so typing G 256 should do the trick. If you've already created a map in the UV window, change 256 to the width of your map.



It is vital that you reattach the mirrored or duplicated parts again before the baking process. The edge normals are different from normals on a vertex with faces on all sides, so the results of a bake would be different. You'd end up with a nasty and obvious seam along your mirroring line.

You could, at this point, bake your normal map, but there's a high likelihood of parts affecting each other. The best option if you have multiple parts is to explode them. Move them away from each other at set intervals, both for the high and lowpoly (so that they still overlap). You can even rotate them if that helps aligning the high and lowpoly. If you have parts that affect each other on one continuous mesh, you can duplicate them and change the parts that you don't want baked outside the 0-1 UV space, just as before. Beware! Make a copy of the lowpoly mesh before you go to making an exploded version! The exploded one is the one you'll be baking from, but you need a whole one as your final result.



Now, let's bake!
In Scene (F10) -> Render buttons there's an Anim panel. Switch it to Bake.
Change Full Render to Normals.
Flip on Selected to Active.
We've talked about Distance and Bias before. Their optimal values depend on the size of your model, so it's best to experiment a little. I tend to start with a Dist of 1 and a Bias of .1, but my models are always rather small.
Clicking on Normals for the type should have opened up a list that by default says Camera. Change this to Tangent.
The Margin value is important too. Unless you've turned off MIP-mapping (and why would you?), Blender (and every other piece of software) will not display single texels anymore at a distance, but it will blend them. Pixels close to the edge of your UV islands will get blended with the black parts where there are no UV islands, which, obviously, isn't very desirable. Margin adds a couple of pixels to outline the UV islands, which will keep them accurate even at distance. If you're seeing seams when zoomed out but not when zoomed in, this is where your problem is. The margin you need depends on the size of your map. If you're unsure, just set it to 32 – it's never on top of any baking, so it doesn't ruin anything to have more than you need.



Those are the settings. Select your exploded lowpoly and go to Edit Mode. Select all your faces with A. Now, in UV mode, go to Image -> New (shortcut Alt + N). Blender's baking does not interpolate, so to get smooth edges (which you want), you'll have to bake at twice the resolution than you'll be using eventually and resize in Photoshop or GIMP. So if you want a 512x512 texture, create a 1024x1024 here.

Go back to Object Mode and deselect your exploded lowpoly. Select all the parts of the exploded highpoly and then the exploded lowpoly. The last object that you select will be the target mesh for the baking, so make sure it's the lowpoly. The last selection will have slightly brighter edges. I always place the exploded high and lowpoly each in a seperate layer. That way, you can select all (A) in the highpoly layer and add the lowpoly layer and selected the lowpoly.
Save! Blender just loves to crash during the baking process.

Press the big shiny Bake button in Scene (F10) -> Render buttons.



You should now have a normal map in your UV window. Congratulations! Go to Image -> Save as and store it somewhere as a TGA. If you change anything to your model, be sure to re-bake, since the map is based on the layout of your faces.

If any parts of your map are a sickly green-yellow-ish colour, you have inverted normals. This occurs when either the low or highpoly has normals pointing inwards there. Fix it, and re-bake.



Now to apply your normal map and see how it turned out.
Select the whole (i.e. Not exploded) lowpoly you have.
Go to Shading (F5) -> Material buttons. In Links and Pipeline, add a new material.
Go to Shading (F5) -> Texture buttons.
In Texture, click Add New. You might want to give it a name to remember it.
Change the Texture Type to Image.
This should get you two new panels.
In Map Image, flip on Normal Map. It's already Tangent by default, which is what we need.
In Image, load up your file.



Go back to Shading (F5) -> Material buttons. On the far right, the texture panel should indicate that it has loaded your texture.
Go to Map Input and flip on UV, which disables Orco.
In Map To, deselect Col and flip on Nor.
Change the Nor value in this panel to 1. Why anyone would want a default strength of .5 is beyond me. Note that there is no such thing as a normal map 'strength' – it takes only directions, so you should always use a value of 1.



In Blender's top bar, go to Game and turn on Blender GLSL Materials.
Now, if you're in Texture mode and there is a light somewhere, you should see your normal map. Congratulations!



With and without a normal map.

Rendered in 8MonkeyLabs' Marmoset, which does render mirrored normal maps.




Links:
Blender Wiki on bump and normal maps
Polycount Wiki on normal maps






2009 Copyright Joey Spijkers