Premium apps Part of Renderloom
Normal Map & AO Baker (high → low poly)
Bake tangent-space normal and ambient-occlusion maps from a detailed mesh onto a low-poly OBJ.
Try an example: Bumpy sphere onto an icosphere with UVs: normal and AO maps · Smooth sphere: the tangent-space map is flat blue (DirectX green) · Ridged plane onto a flat plane without UVs: unwrap and bake AO
How it works
Upload a detailed high-poly mesh and a low-poly mesh with UVs (or let the tool unwrap it). Every texel casts a ray from a cage around the low-poly surface to the high-poly mesh: the hit normal becomes a tangent-space normal map with MikkTSpace-style tangents (OpenGL or DirectX green), and seeded hemisphere rays measure ambient occlusion. Download both maps as PNG together with a report of coverage, misses and mean normal. Runs on the same engine as Renderloom Sculpt Lab.
- High-poly mesh: welded, oriented, angle-weighted vertex normals, binned-SAH BVH. Low-poly mesh: OBJ texture coordinates per corner; meshes without UVs are unwrapped with the renderloom-uv-unwrap engine when allowed. Low-poly normals are angle weighted over vertices that share a position, so UV seams keep one normal.
- Tangents: per-face tangent and bitangent from the UV derivatives, projected into the plane of the vertex normal, angle weighted and averaged over corners with the same vertex, UV and handedness; the bitangent sign is kept per corner. Decoding (as in Blender, glTF viewers, Unity and Unreal): normalise interpolated normal and tangent per pixel, bitangent = sign × cross(normal, tangent).
- Each texel centre inside a UV triangle casts one ray from the cage (surface point + cage distance × normal) along −normal over twice the cage distance; the first high-poly hit gives the interpolated high-poly normal, expressed in the texel’s tangent frame and encoded as RGB = 0.5 + 0.5 × (x, y, z). DirectX maps store −y.
- Ambient occlusion: cosine-weighted hemisphere rays around the high-poly normal from the hit point, seeded per texel (same seed, same map); a ray that hits anything within the AO distance counts as blocked; AO = open fraction.
- Texels outside the layout are filled by padding rounds of neighbour averaging, then with a flat normal and white AO. Maps are 8-bit RGBA PNG. Budget: map size² × (1 + AO rays) ≤ 16.7 million rays, at most 300000 high-poly and 60000 low-poly triangles.
Tangents follow the published MikkTSpace rules but are an independent implementation; check the maps in your target engine. Both meshes must share the same position and scale. Rays that miss the high-poly mesh keep the low-poly normal and full AO — the report counts them.
Sources
- M. Mikkelsen: Simulation of wrinkled surfaces revisited (MikkTSpace), MSc thesis, University of Copenhagen 2008 (University of Copenhagen)
- glTF 2.0 specification: normal textures and MikkTSpace tangents (Khronos Group)
- T. Möller, B. Trumbore: Fast, minimum storage ray–triangle intersection, Journal of Graphics Tools 2 (1997) (Taylor & Francis)
- I. Wald: On fast construction of SAH-based bounding volume hierarchies, IEEE Symposium on Interactive Ray Tracing 2007 (IEEE)
- G. Thürmer, C. A. Wüthrich: Computing vertex normals from polygonal facets, Journal of Graphics Tools 3 (1998) (Taylor & Francis)
Part of Renderloom
-
Renderloom 3D scene & material studio
Shape a scene. Find its light. Keep every idea editable.
How to use the Normal Map & AO Baker
Bake a tangent-space normal map and an ambient occlusion map from a detailed mesh onto a low-poly OBJ with UVs, and check the bake report.
What it is for
A sculpted model with hundreds of thousands of triangles is too heavy for a game or a web viewer. The usual answer is a simple low-poly version plus a normal map that stores the detail of the sculpt, and an ambient occlusion (AO) map that darkens creases. This tool bakes both: you upload the detailed mesh and the low-poly mesh, it returns two PNG files.
The low-poly mesh needs texture coordinates. An OBJ with vt lines is used as it is; an STL, PLY or OBJ without UVs is unwrapped automatically and the tool hands you that OBJ too. Both meshes must sit in the same place at the same scale — the baker does not align them.
Worked example
The first example bakes a bumpy sphere (1,280 triangles, radius 1 with a small ripple) onto an icosphere of 80 triangles with UVs, at 128 × 128 pixels and 8 occlusion rays per texel.
The report shows 100 % of the rays hitting the high-poly mesh, 39.06 % of the texels inside the UV layout, a cage distance of 0.1039 (3 % of the model size) and 57,545 rays. The mean normal is (−0.000166, −0.00000253, 0.996): almost straight up in tangent space, which is why a normal map looks light blue. The ripple appears as pink and green shading on that blue. The sphere is convex, so AO stays near 1; the darkest texel is 0.875.
For contrast, the third example bakes only AO from a plane with ridges onto a flat plane without UVs. The plane is unwrapped automatically, covers 97.67 % of the map, and the grooves between the ridges reach 0.6875 (mean 0.9792).
Setting the cage to 0.5 % in the first example drops the hit rate to 9.906 % and the report warns that more than 5 % of the texels missed: the ripple is deeper than the cage.
How to read the result
- Rays that hit the high-poly mesh is the first thing to check. Anything below 100 % means some texels kept the low-poly normal; raise Cage distance (% of the model size).
- Texels inside the UV layout is the share of the map that belongs to charts; the rest is filled by the edge padding.
- Mean normal (x, y, z) should have a large z in tangent space. A strongly tilted mean points to a wrong cage or swapped meshes.
- Mean ambient occlusion and Darkest ambient occlusion run from 0 (fully enclosed) to 1 (open sky).
Tips and common mistakes
- Choose DirectX (−Y) under Green channel for Unreal Engine and 3ds Max, OpenGL (+Y) for Blender, glTF and Unity. A wrong choice makes bumps look like dents in light from above.
- The cage should be a little deeper than the largest difference between the two surfaces, not much more: a huge cage can hit the wrong side of thin parts.
- Occlusion distance (% of the model size) decides how far AO looks. Small values only darken tight creases.
- Keep the same Random seed to get identical AO maps; 16 rays per texel are noisy, 32–64 smoother.
- Use Edge padding (px) of at least 4 so mipmaps do not bleed background into the charts.
FAQ
Is the normal map MikkTSpace compatible?
The tangents follow the published MikkTSpace rules and the usual per-pixel bitangent. It is an independent implementation, so check the result in your engine; differences only matter on broken UVs.
Can I bake object-space normals?
Yes, choose Object space under Normal space. Those maps only work while the model is not deformed.
Why is part of my map flat blue?
Those texels lie outside the UV charts or their rays missed the high-poly mesh. The report counts the misses.
How big can the bake be?
Up to 1024 × 1024 pixels, 300,000 high-poly triangles and 16.7 million rays in total.
Guide last updated:
For scripts and AI agents
- JSON API:
POST https://renderloomnormalmapbaker.usefulweb.site/api/v1/calculate(same calculation as this page) - Interface description: OpenAPI 3.1 · AI guide: llms.txt
- MCP server (Streamable HTTP):
https://renderloomnormalmapbaker.usefulweb.site/mcp· tool namerenderloom_normal_map_baker
Example request
curl -s -X POST https://renderloomnormalmapbaker.usefulweb.site/api/v1/calculate \
-H 'content-type: application/json' \
-d '{…see OpenAPI examples…}'