Flat. That's the word every reporting thread uses for a normal map that looked perfect in Substance Painter and then goes dead the moment a GLB lands in Godot's viewport — ridges vanish, panel lines smear into the base color, and the bump you baked for twenty minutes reads as a decal instead of geometry. The cause almost never lives in the texture. It lives in tangents, and Godot's glTF importer recalculates them on every import whether your mesh needs it or not.
Godot's importer uses Mikktspace to generate tangent vectors from your mesh's UVs at import time, and by default it does this even when your GLB already ships tangents baked by Blender or Substance Painter. If the tangent basis your bake used doesn't match what Mikktspace derives from the same UV layout, the normal map's lighting direction shifts just enough to flatten fine detail and throw visible seam lines at every UV border. This has been reported consistently against Godot 4.3 through 4.5 — it's documented behavior, not a regression, and the open issue thread on Godot's GitHub tracker confirms the importer treats `.blend` and `.glb` sources differently for exactly this reason.
Why GLTF normal maps flatten out after Godot import
![]()
Three symptoms point at tangent mismatch specifically, as opposed to a bad bake or wrong color space:
- The map looks correct in Blender's viewport and in a browser-based GLTF viewer, but flat only in Godot
- Detail disappears more on curved or rotated UV islands than on flat ones
- You see faint dark or light lines that trace the exact shape of your UV seams
If you're seeing all three, the fix is a settings mismatch, not a re-bake. Re-baking without touching import settings just gives you a second flat result.
Fixing it: match tangent generation between Blender and Godot
![]()
Two places control this, and you only need to touch one of them consistently:
In Blender's glTF export panel, under the Geometry section, check Tangents. This writes the mesh's actual tangent vectors into the GLB's accessor data instead of leaving Godot to invent its own. It requires a UV map to be present and only has an effect on meshes that carry a normal map.
In Godot, select the imported `.glb` in the FileSystem dock, open the Import tab, and go to Advanced Import Settings. Under the Meshes section, disable Ensure Tangents — this is the flag that forces Mikktspace regeneration regardless of what's in the file. With it off, Godot trusts the tangents Blender exported and the lighting on the normal map matches what you saw in Blender.
Reimport after changing either setting; Godot won't pick it up on a plain scene reload.
```gdscript
# quick runtime check — flags meshes still using generated tangents
for child in mesh_instance.mesh.get_surface_count():
var arrays = mesh_instance.mesh.surface_get_arrays(child)
if arrays[Mesh.ARRAY_TANGENT] == null:
push_warning("Surface %d has no baked tangents — Ensure Tangents is active" % child)
```
If you'd rather see the problem before it ever reaches Godot, drop the GLB into BitSoul's 3D Studio first — it runs the UV and material inspection in your browser on your own GPU, so you can confirm the UV layout and tangent-relevant seams before you touch an import setting.
Gotchas: green-channel flips, mirrored UVs, and multi-mesh files
Fixing tangent generation clears most flat-normal-map reports, but three related issues get mistaken for the same bug:
| Symptom | Real cause | Fix |
|---|---|---|
| Normal map looks inverted, not flat | Green channel authored for DirectX (Y-) instead of OpenGL (Y+), which glTF requires | Invert the green channel in your image editor or re-export from Substance with the OpenGL normal preset |
| Detail flips on one side of a symmetric mesh | Mirrored UV islands share tangent direction incorrectly | Mikktspace handles most mirrored islands correctly once tangents are baked — verify by disabling Ensure Tangents rather than manually flipping UVs |
| Fix works on one mesh but not the rest of the file | Multi-mesh GLBs apply Advanced Import Settings per surface, not globally | Reopen Advanced Import Settings and confirm each mesh in the list has Ensure Tangents unchecked, not just the first one |
A GLB with several meshes — a character plus its attached gear, for instance — is where this trips people up most, since the settings dialog defaults to showing only the first surface. The Wasteland Mercenary model is a good one to test this against precisely because it ships as multiple attached meshes rather than one — a free account's two monthly downloads cover evaluation like this, with commercial use included in paid memberships.
None of this is unique to assets pulled from a marketplace — it's the same failure mode covered in Blender 5's glTF export changes and in the bone-weight import issue from glTF's 4-bone limit — Godot's importer making its own decisions about data your source file already computed correctly. If you've hit the collision-shape version of this same "importer overrides the file" pattern, it's the same root cause described in why GLB imports skip collision generation.
Once tangents match, re-verify at the texel level, not just visually: open the Advanced Import Settings preview, rotate the mesh under the default light, and check that ridge highlights stay sharp as the surface turns. A correct fix holds up under rotation; a texture-level workaround — brightening contrast, boosting normal strength — looks fine static and falls apart the moment the camera moves.
---
*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*