How to create normal maps (bumpmaps) with Blender
Published January 06 2023 by @manavortex Last documented update: January 20 2024 by @manavortex
This guide will teach you how to create a custom normal map.
For a different guide about this, check this Google Doc by Тима (Teem)#3118
For a guide on Cyberpunk materials in Blender, see Cyberpunk Shaders in Blender
If you want to create a .mlmask
instead, see Textures: Custom MultilayerMask
Otherwise, you can use the wiki's search function — it uses an LLM and is actually quite useful.
If you don't have Photoshop, Photopea offers almost the same thing online for free.
For a free tool for faster normal baking, check out xnormal.
Export your mesh from WolvenKit
Import it into Blender (do not import materials)
Select the object
Make sure your material has exactly one material (see the end result in the screenshot at step 5):
if there are no materials: Awesome, you passed the reading comprehension test! Create one by clicking the +
button.
If there are materials: You failed the reading comprehension test and I am very disappointed. Delete all but one by selecting them and clicking the -
button.
The viewport should already be set to "Solid". Click on the dropdown arrow next to the options and select "Texture" from the list.
As the first step, we create a Displacement Map for our 3d object. This black and white image will turn your mesh into an object with actual (simulated) depth, which we will then "bake" into a normal map.
This tutorial won't cover the process of how to draw such a map in-depth, but there will be a few tips how to do that in Blender.
The displacement image should be saved in 32 bit image depth rather than the usual 8. This will yield better results with the normal maps.
The Texture Paint perspective lets you draw directly on your mesh's surface:
To see how the mesh is projected on your image, you can check out the UV edit mode.
Switch to "Edit" (shortcut: Tab) and select all vertices (shortcut: ctrl+A). You will now see them projected on the texture:
Feel free to change the UV mapping. You can export this back into Cyberpunk!
Once you are done with your displacement map and the UV mapping looks like you want it to, it's time for the next step: projecting!
Take your displacement map and create a slightly blurry version of it. This will prevent artifacts on the normal map, as the algorithm doesn't like perfectly straight edges.
I create a duplicate of my entire armature, just to make certain that I don't accidentally overwrite anything I want to keep. Only work on the new object, since we're getting destructive here.
Make sure that your viewport is in Object Mode
Select all objects that you want to go on the same normal map, then join them together (shortcut: Ctrl+J).
Create a duplicate of this mesh (Ctrl+D, ESC to stop moving), then rename that to "Low Poly".
Select the mesh you duplicated and rename it to "High Poly".
Open the "Modifiers" tab and assign the following modifiers after the armature modifier (check screenshot in Step 6)
Generate -> Subdivision Surface Levels Viewport: 2 or so Render: As many as Blender lets you get away with without crashing, I used 7 Advanced: UV Smooth: Keep Corners, Junctions Boundary Smoothing: Keep Corners
Deform -> Displace Coordinates: UV UV Map: UVMap Direction: Normal Strength: -0.002 (you can play around with this) Midlevel: 0.000
If you hide your "Low Poly" mesh, the modifiers should now let you see creases on your high poly object! Exciting!!
The normal map will only care for relative depth, so keep the creases on your mesh shallow. If you make them too sharp, this can lead to artifacts on the baked normal map.
Switch to the "Shading" perspective again. Add another image texture and create an image with your target resolution. Call it "Bake" or whatever.
Remove the link to your material's normal input - otherwise, it'll bake your normal map into your normal map, and the results won't be pretty.
The high poly mesh needs to be completely covered by the low poly one, like plastic wrap. That will normally not be the case yet, so we need to inflate the poly mesh:
Set the viewport to Object Mode
Select the Low Poly mesh
Switch into Edit Mode (Hotkey: Tab
)
Select all vertices (Hotkey: ctrl+A
)
Optional: Merge by distance (Hotkey: M
)
Fatten (Hotkey: Alt+S
, adjust amount of fattening via mouse or by typing it in directly)
Fix up whatever parts didn't fatten correctly by hand.
Undo your action and select all vertices again.
Put the 3d cursor in the center of the selected vertices:
Right-Click -> Snap Vertices -> Cursor To Selected
Set the Pivot Point to 3D cursor (Shortcut: .
(dot), Numpad 6
)
Fatten again!
If you're unable to shake a normal map from this process, you might have to resort to Photoshop. (If you don't have it, photopea.com offers almost the same features for free).
Switch back to Object Mode.
In Blender, the "active" object is the "previously selected" one. Select your meshes in the following order:
Low Poly
High Poly
Find the "Render Properties" tab.
At the very top, set "Device" to "GPU Compute" (unless you'd rather bake on your CPU)
Scroll down all the way to "Bake". Configure it like this:
Bake Type: Normal
Influence / Space: Tangent
Selected to Active: Checked
Extrusion: 0.04 m If your generated normal map shows artifacts, try tweaking this.
Max Ray Distance: 0.04 m If your generated normal map shows artifacts, try tweaking this.
Output / Target: Image Textures
Clear Image: Checked
Margin / Size: 16px (or whatever suits you)
Save. Your. File.
Baking takes time (several minutes) and most of your PC's free resources. This is normal.
If everything went well, the image editor on the bottom left will change and display your normal map.
You can export the image via the hamburger menu in the image editor (bottom left panel of the screenshot).
If you don't have Photoshop, photopea.com offers almost the same features for free.
So your baking process failed horribly and you're frustrated. Fair, I've been there — 3d edits are finicky. Let's do it in photoshop instead.
Load your black and white image into the photo editor of your choice (Photoshop or Photopea).
From the menu, select Filter -> 3d -> Normal Map (Generate Normal Map) in Photoshop)
Photoshop: Click "OK" on the popup (about the 3d features being outdated)
Tweak the parameters until you have a normal map — you want it to be as sharp as possible without artifacts/tearing! Some blur might be necessary.
Click "OK" to apply the changes.
Congratulations, you now have a normal map.
This troubleshooting section is for the baking process — the one for normal map textures is here.
Make sure to remove the normal mapping from your material.
First of all, make sure that all your normals are pointing the right way. In the viewport editor, click the "Show Overlays" button and select "Geometry -> Face Orientation" near the bottomn. Blue means outside, red means inside.
The baking process works by capturing the rays of light that bounce between the high poly mesh and the low poly mesh. If you have artifacts, then some of those rays bounced off something else first, which makes them register as inverted. That's the reason why steep creases are a problem — a ray of light might get caught in there and be flipped around.
Check the troubleshooting step for artifacts.
Make sure your displacement map (the one used by the modifier) is blurred.
Try lowering the strength of the Displace modifier on the High Poly mesh, making the creases more shallow.
Try changing Extrusion and Max Ray Distance in the Bake settings.
If that doesn't help, you could try a cage, or otherwise hit Google.
Restart Step 4 and make sure that you haven't deleted or altered any vertices, other than scaling/inflating the low poly mesh.
This is a workaround and won't solve the problem. If you know how to fix this for good, please update this page!
Open the UV of your 3D model and select the vertices that are outside on the left of your UV
Now you have two separate submeshes. Export them both into the same .glb file for Wolvenkit.
Open Photoshop, Paint.net or Photopea to invert the green channel. Save your new .png under a name like <name_inverted_n>
Import your inverted normal map in Wolvenkit. Now, you can create a new material for the normal-inverted parts of your mesh!
Assign a material to the only remaining slots:
Switch to the "Shading" perspective and add an "Image Texture". Select your image by clicking the corresponding button:
For the "Displace" Modifier, create a new picture, then click on the two sliders to show this texture in the textures tab
Load your blurred texture:
Here is an example of the issue :
Version
Blender>= 3.6 (working on 4.0)
Assumed skill level
You know what a normal map is
You're able to draw stick figures
You are not afraid of Blender
You know how to read.
In-game, your normal map isn't looking as expected
The texture has to be imported without the isGamma
flag. Import over an already-existing normal map to rule out this as a source of error. See this conversation on Discord for more detail.
Cyberpunk actually considers the UV map's scaling when calculating the weight of the normal maps:
Since the neck part is scaled much larger than the chest, this will make the parts of the mesh visibly distinct.