
MikkTSpace normal maps work when the baker and renderer agree on the coordinate frame attached to every vertex. The texture stores directions relative to that frame, not free-floating bumps. Change the mesh normals, UVs, triangle split, or tangent handedness after baking and the same RGB values decode into different lighting.
This is why a normal map can look perfect in the baking tool and develop seams, waviness, or diagonal dents in-engine. The file is often innocent. The low-poly mesh used to encode it is no longer the mesh used to decode it.
This guide treats MikkTSpace tangent space as a pipeline contract. You will see what the algorithm standardizes, what it cannot standardize, how mirrored UVs and triangulation enter the result, and how to ship a synced workflow through Blender, Unity, Unreal Engine, and glTF.
MikkTSpace normal maps are an encoding contract
A tangent-space normal map does not store the final world-space direction. Each texel stores components along three local axes: tangent T, bitangent B, and surface normal N. The renderer reconstructs a shading direction from that basis:
N_shaded = normalize(n.x * T + n.y * B + n.z * N)
The baker performs the inverse operation. It measures a high-poly direction, projects that direction into the low-poly basis, then writes the resulting components to RGB. Correct reconstruction therefore needs the decode transform to match the encode transform closely enough at every pixel.
MikkTSpace, created by Morten Mikkelsen, gives tools a repeatable way to derive tangents and orientation from positions, vertex normals, and texture coordinates. Its reference implementation is designed to produce consistent results regardless of face order. It also explains that normal-map sampling must use the exact inverse of the transform used during baking. The standard removes a major source of disagreement; it does not make the input mesh irrelevant.
Think of the normal map and low-poly mesh as one encoded asset. Sending only the texture to another mesh is like shipping a key and replacing the lock because both pieces were made of brass.

What the MikkTSpace tangent basis actually contains
The input is not just vertex positions. MikkTSpace evaluates face corners using position, normal, and UV coordinates. The output used by many real-time pipelines is a unit tangent plus a sign. The bitangent can then be reconstructed as:
B = sign * cross(N, T)
That sign records whether the local UV orientation is preserved or mirrored. Storing T.xyz and the sign in T.w avoids a separate bitangent attribute while keeping reflected UV islands readable.
The tangent basis mismatch people see as a texture bug can come from any input or reconstruction change:
- different vertex normals or smoothing splits;
- a changed UV map, UV set, or mirrored-shell orientation;
- different quad triangulation;
- tangents calculated before deformation but reconstructed differently after it;
- a missing or inverted handedness sign;
- normalization at a different stage of interpolation;
- an OpenGL-versus-DirectX green-channel convention mismatch.
The last item is adjacent to MikkTSpace, not part of the tangent-generation algorithm. A synced basis can still read a Y-down texture as Y-up. Diagnose the frame and the swizzle separately.
Triangulation is part of the baked result
MikkTSpace triangulation matters because vertex attributes are interpolated across triangles. A quad has two legal diagonals. Switch the diagonal and the tangent frame inside the face changes, especially on twisted geometry, skewed UVs, or a bake carrying a strong gradient.
The reference implementation notes that reordered faces produce the same vertex tangent results, but the interpolated tangent space still depends on the diagonal chosen to split each quad. This explains the classic diagonal dent: the bake tool used one split, the exporter or engine silently chose the other, and a four-sided face acquired a lighting crease with no matching edge in the texture.
Triangulate the final low-poly mesh before baking. Apply that topology, bake against it, and export that exact mesh. Do not triangulate one copy for the engine while baking an editable quad copy and assuming identical topology will emerge by goodwill.
LOD meshes need their own consideration. Each LOD has different triangles and usually different tangents. Either bake an appropriate map per LOD or prove that the shared map remains acceptable under the destination's tangent calculation and screen distance.

Mirrored UVs need handedness, splits, and padding
MikkTSpace mirrored UVs are supported through tangent-frame orientation. When a UV shell is reflected, its bitangent direction reverses. The tangent sign tells the shader which orientation to reconstruct. If an interchange format, mesh optimizer, custom vertex packer, or shader drops that sign, one mirrored side may show dents where the other shows bumps.
A correct sign does not make the UV border disappear. Orientation changes may require tangent splits, and the normal map still needs padding beyond the island boundary. Bilinear filtering and mipmaps sample outside the visible shell. Without dilation, border texels borrow unrelated directions and draw a seam that resembles a basis error.
Test mirrored shells with an asymmetric bevel or stamped detail. Symmetric noise can conceal inversion. Rotate one strong light around both sides and compare highlight motion. If the geometry is symmetric but the highlight bends oppositely, inspect T.w, channel swizzle, and shader reconstruction before rebaking.
Build one synced normal map workflow
A dependable synced normal map workflow makes every choice explicit:
- Finalize the low-poly. Lock positions, smoothing, UVs, mirrored shells, and material borders.
- Triangulate once. Apply a deterministic split and keep the resulting mesh as the bake and export source.
- Choose the normal policy. Decide whether the engine imports authored normals or recalculates them. Do not mix policies by asset.
- Bake with MikkTSpace. Select tangent space and use the final low-poly data when running how to bake MikkTSpace normal maps tests.
- Export matching attributes. Preserve the intended normals, tangents, UV set, triangle topology, and handedness.
- Configure import. Import or recalculate tangents according to the documented engine path, then set the expected normal-map swizzle.
- Validate without material noise. Use neutral base color, medium roughness, one moving light, and no post effect that hides gradients.
- Archive the contract. Record tool versions, exporter preset, importer settings, tangent policy, texture convention, and a hash of the bake mesh.
Rebake after changes to normals, UVs, or topology. A later “cleanup” that welds vertices, regenerates smoothing, rotates UV shells, or optimizes indices may be visually invisible without the map and still alter its decoder.
MikkTSpace in Blender, Unity, Unreal Engine, and glTF
For MikkTSpace Blender work, use Tangent space in Cycles baking and keep the relevant UV map active. Blender's current baking documentation identifies tangent space as the normal choice for transformable and deforming objects, while its UV Tangent node uses MikkTSpace to match Blender shading and exported geometry. Apply triangulation before bake when the destination may split quads differently.
For MikkTSpace Unity work, the model importer can import tangents or calculate them using MikkTSpace. Pick the path that matches the bake. If you calculate tangents in Unity, preserve the baked positions, normals, UVs, and triangles. Mark the texture as a Normal map and confirm its flip-green setting instead of changing both mesh and texture conventions in the same test.
For MikkTSpace Unreal Engine work, Interchange import exposes Recompute Normals, Recompute Tangents, and Use MikkTSpace controls. Recomputing tangents can be correct when the imported low-poly inputs match the bake target. Recomputing normals changes a basis input and usually invalidates a bake made against authored normals.
For MikkTSpace glTF, the glTF 2.0 specification recommends default MikkTSpace generation when tangent attributes are absent. It stores tangent XYZ plus a W handedness sign and defines bitangent reconstruction from their cross product. Exporting tangents can remove runtime ambiguity; omitting them can also work when the viewer follows the spec and receives matching geometry.
“Supports MikkTSpace” is the start of verification, not the end. Export settings can remove tangents, importers can recalculate normals, mesh compression can change attributes, and custom shaders can ignore the expected sign.
Fix normal map seams with evidence, not channel roulette

To fix normal map seams MikkTSpace style, classify the shape of the error first:
- Diagonal inside a quad: compare triangulation between bake and render meshes.
- One mirrored island inverted: inspect tangent handedness and green-channel convention.
- Hard edge glowing or dented: compare normal splits, UV splits, and padding.
- Broad waviness on a flat face: inspect vertex normals, cage projection, tangent precision, and compression.
- Error only after animation: check normal and tangent skinning, normalization, and morph handling.
- Error only at distance: inspect mip filtering, LOD topology, and mesh-specific maps.
Export a diagnostic mesh with visible triangle boundaries and compare vertex counts, triangle indices, normals, tangents, UVs, and T.w before and after import. A render screenshot shows the symptom. Attribute comparison identifies the contract breach.
The best MikkTSpace workflow 2026 is not a magic checkbox shared by every application. It is a reproducible chain in which the checkbox points to the same final mesh data on both sides.
Try CraftPBR
CraftPBR helps you create and test the texture side of MikkTSpace normal maps while keeping the mesh contract visible:
- Text-to-PBR creates aligned base color, normal, roughness, height, AO, and metalness from a material brief.
- Photo-to-PBR turns controlled surface photos into coherent maps for a chosen asset.
- Node workspace lets you isolate normal strength, repair edge behavior, and compare height-derived detail.
- Engine export prepares normal orientation, channel packing, color-space intent, and target-friendly names.
- Free tier lets you validate a full PBR set before committing production time.
- CC0 output lets you edit, rebake, test, and ship generated textures without attribution.
Generate the maps, freeze the mesh contract, and make the renderer read what the baker wrote.
Create a synced PBR material →