You spent hours baking a perfect normal map in Blender or Substance Painter. You drop it into Unity, and suddenly the lighting looks inside-out — shadows where highlights should be, and the surface detail reads completely wrong. Nine times out of ten, the culprit is a single checkbox: the green channel convention. DirectX and OpenGL normal maps are not interchangeable, and every engine handles them differently.
This guide explains the difference clearly, covers tangent space vs. object space normal maps, and gives you exact per-engine settings so you get correct results the first time.
DirectX vs OpenGL Normal Maps — The Green Channel Problem
Normal maps encode surface direction as RGB color data. Red (X) and Green (Y) store the lateral direction of each surface normal; Blue (Z) stores the depth. The X axis is the same in both conventions. The difference is the Y axis: DirectX uses Y-down, OpenGL uses Y-up.
In practice, this means the green channel is literally inverted between the two formats. A DirectX normal map has a greenish-dark tint in areas that would appear greenish-bright in an OpenGL map, and vice versa. When you import the wrong format for your engine, you'll see:
- Lighting that appears to come from the wrong direction
- Specular highlights that look "dented" instead of raised
- Surface detail that reads as depth when it should read as height
![]()
The fix is simple once you know which convention each tool produces and which each engine expects:
| Tool / Engine | Default Convention |
|---|---|
| Blender (baked) | OpenGL |
| Substance Painter | DirectX (default) |
| Unity | OpenGL |
| Unreal Engine 5 | DirectX |
| Godot 4 | OpenGL |
| Marmoset Toolbag | DirectX |
You have two options when there's a mismatch: flip the green channel in your texture editor before exporting, or use in-engine settings to compensate at import time. For production pipelines, flipping at export is cleaner — you're not relying on the person doing the import to know the convention.
In Photoshop or GIMP, inverting the green channel is a 10-second operation. In Substance Painter, you can switch the bake output convention under Project Settings → Normal Map Format. In Blender, go to the Image Editor, select your baked normal map, and flip via Image → Invert → Invert Green Channel.
Tangent Space vs Object Space vs World Space Normal Maps
The DirectX/OpenGL distinction applies mainly to tangent space normal maps, which is what you'll use 99% of the time. But it's worth understanding all three types so you know when each is appropriate.
Tangent space normal maps store normals relative to the surface itself. They look mostly blue/purple because most normals point straight up (toward the camera). Tangent space maps work with UV-mapped meshes, support skeletal animation and mesh deformation, and are portable across different object orientations. This is the standard format for all game engine imports.
Object space normal maps store normals relative to the object's local coordinate system rather than the surface. They look like full-spectrum rainbow textures — each axis maps to a primary color. Object space maps produce sharper detail and are easier to bake correctly (no tangent basis mismatch issues), but they break completely when an object rotates or deforms. Use them only for rigid, static props. Some studios use object space maps for baking and convert to tangent space before export.
World space normal maps store normals in global scene coordinates. Rarely used in games; mostly relevant in offline rendering.
![]()
For game assets, the rule is: always use tangent space unless you have a specific reason not to. Object space maps are a useful intermediate step in some baking workflows but shouldn't be your final export format.
One common gotcha: if you're baking tangent space normals in Blender and importing into Unreal Engine 5, you need both tools to agree on the tangent basis. Blender uses MikkTSpace by default; Unreal Engine 5 also uses MikkTSpace. This means Blender → UE5 tangent space bakes work without seam issues as long as both settings are left at their defaults.
Per-Engine Settings — Unity, Unreal Engine 5, and Godot 4
Here's exactly where to find the normal map convention controls in each engine:
Unity (URP and HDRP)
Unity expects OpenGL (Y-up) normal maps. When you import a texture and mark it as a Normal Map in the Inspector, Unity applies its own processing. If you're importing a DirectX normal map, check "Create from Grayscale" or manually flip the G channel before import. In Shader Graph, the Sample Texture 2D node set to type Normal automatically handles the flip based on the platform build target (DirectX on Windows, OpenGL on other platforms). For explicit control, use the `UnpackNormalWithTransform` function.
Unreal Engine 5
UE5 expects DirectX normal maps. When importing, you'll see a "Flip Green Channel" checkbox in the texture import dialog — use this when importing an OpenGL normal map from Blender. Alternatively, in the Texture Editor, enabling "Flip Green Channel" on any texture asset converts it. For consistent pipelines, it's better to export DirectX-format normal maps from your DCC tool than to rely on the engine flip.
```
// UE5 Material Editor: manually flip the green channel
float3 normal = tex.Sample(s, uv).rgb;
normal.g = 1.0 - normal.g; // Flip Y for OpenGL → DirectX conversion
return normal * 2.0 - 1.0; // Unpack to [-1, 1] range
```
Godot 4
Godot 4 uses OpenGL convention. When importing normal maps via the Import dock, ensure "Normal Map" is enabled for the texture type — Godot applies sRGB conversion correctly for normal maps (they should be stored in linear color space, not sRGB). If lighting looks wrong, check Project Settings → Rendering → Textures → Default Texture Filter and confirm your normal map asset has sRGB disabled in its import settings.
Exporting from Blender and Substance Painter with the Right Convention
For a clean pipeline, standardize on one convention and export correctly rather than compensating in-engine.
Blender bakes → Unreal Engine 5:
Blender bakes OpenGL by default. In UE5, enable Flip Green Channel on the imported texture, or in Blender's Image Editor select your baked normal map and use Image → Invert Green.
Substance Painter → Unity / Godot 4:
Substance Painter defaults to DirectX. Change this in Project Settings → Normal Map Format → OpenGL before export. Alternatively, in the export dialog, use the OpenGL preset for your export configuration.
Substance Painter → Unreal Engine 5:
Leave Substance Painter at its default DirectX setting and export. UE5 will import it correctly without any flipping.
Blender → Unity / Godot 4:
Blender's OpenGL output matches both engines directly. No conversion needed.
| Source → Target | Action Required |
|---|---|
| Blender → Unity | None |
| Blender → Godot 4 | None |
| Blender → Unreal Engine 5 | Flip G channel (Blender or UE5) |
| Substance Painter (DX) → Unity | Flip G channel or change SP to OpenGL |
| Substance Painter (DX) → Godot 4 | Flip G channel or change SP to OpenGL |
| Substance Painter (DX) → Unreal Engine 5 | None |
Quick Checklist and Troubleshooting
If your normal map still looks wrong after checking the convention, run through this list:
- Surface looks dented instead of raised? Green channel is inverted. Flip it.
- Seams visible on the normal map? Tangent basis mismatch. Confirm both Blender and your engine use MikkTSpace.
- Lighting breaks when the object rotates or animates? You accidentally used an object space normal map. Re-bake in tangent space.
- Normal map looks correct in Blender viewport but wrong in engine? The texture is being treated as sRGB in-engine. Set it to Linear/Non-Color in both Blender (Image Texture node: Color Space = Non-Color) and your engine's import settings.
- Blue channel is very dark or missing depth? The map was exported as a 2-channel (RG only) format. Re-export as full RGB.
- Weird specular artifacts along UV seams? Check that UV islands have adequate padding (2–4 px at 1024, 4–8 px at 2048). Normal map bleeding across UV seams causes shading errors.
For teams sourcing pre-made normal-mapped assets, BitSoul's marketplace offers game-ready GLB files where normal map conventions are pre-verified for Unity, UE5, and Godot 4 — saving you the import debugging cycle entirely.
Get Normal Map–Verified Assets from BitSoul
Normal map convention mismatches are a solved problem — but they cost time every time someone new to a project imports an asset. Standardize your team on verified, convention-correct assets from BitSoul's marketplace, where every asset ships with PBR textures tested across all three major engines.