Height map
Normal map
Bake height maps into normal maps, locally
A normal map fakes surface detail on low-poly 3D geometry by encoding per-pixel surface directions in color. This generator takes any grayscale-friendly image as a height map, computes the brightness gradients, and outputs a tangent-space normal map you can drop into game engines like Unity, Godot or Unreal.
How to use
- Drop a height map (bright = high) or load the sample.
- Tune strength until the slopes look right; the preview updates live.
- Flip channels if your engine expects DirectX-style Y (green) or reversed X (red).
-
Download the RGB PNG — flat areas are exactly
#8080FF.
Convention and edge rules (the fine print)
| Setting | Default |
|---|---|
| Space | Tangent space |
| Red — X axis | +X points right (invert with “Invert X”) |
| Green — Y axis | +Y points up, OpenGL texture space (invert for DirectX) |
| Blue — Z axis | +Z out of the surface; flat = #8080FF |
| Height source | Luminance 0.2126 R + 0.7152 G + 0.0722 B |
| Edge sampling | Clamped — border pixels replicate outward (no wrap) |
| Determinism | Same image + same settings always produce identical bytes |
Limits
- Input: one PNG / JPG / WebP up to 20 MB and 4096 × 4096 px; output PNG keeps the input resolution with RGB + opaque alpha.
- This is not 3D reconstruction: photos of objects are not height maps, and results will show lighting baked into the photo. Use real height or bump maps.
FAQ
What does this normal map generator do?
It reads the brightness of each pixel in your image as height, computes surface slopes with a Sobel-style gradient filter, and encodes the resulting surface normals into an RGB PNG: red = left/right tilt, green = up/down tilt, blue = facing the viewer.
What is the default channel convention?
Tangent space, OpenGL style: red = +X pointing right, green = +Y pointing up in texture space, blue = +Z out of the surface. A flat area is exactly #8080FF. Use the invert Y toggle for DirectX-style (Y-down) normal maps, and invert X if your engine expects flipped red.
How is height computed from a color image?
Luminance with the Rec. 709 weights: 0.2126 × red + 0.7152 × green + 0.0722 × blue. Bright pixels count as high. The invert height option flips this so bright means low.
What happens at the image edges?
Sampling is clamped: pixels outside the image copy the nearest edge pixel, so borders behave like a flat continuation instead of wrapping around.
Can I recover the 3D shape of a photo with this?
No. A normal map only describes local slopes of the brightness field. A photo of a face is not a height map — lighting, shadows and texture all leak into the result. Use actual height/grayscale bump maps for meaningful output.
Is my height map uploaded anywhere?
No. The math runs entirely in your browser with canvas and JavaScript; no image data, filename or setting leaves this page, and nothing is stored after you close the tab.