Skip to content
DepthCarve

3D and VFX

Normal map from an image without Photoshop

There are two different jobs hiding behind this query: converting a height map you already own, and estimating surface direction from a photograph that has no height field yet.

DepthCarve engineering5 minute read
normal map from image illustrated with smooth grayscale distance layers
A smooth thumbnail can still hide reversed direction, clipped range, or an incorrect object boundary. Inspect the field against its source.

First decide which input you have

If the image is a grayscale height map, the job is a direct conversion: sample the height around each pixel, compute the slope, and store the surface direction as RGB. This is deterministic, fast, and can run entirely in a browser. No model call and no upload are needed.

If the image is a photograph, there is no height field yet. The brightness in the photo records reflected light, not distance. You can still treat brightness as height for a quick material test, but that is not the same as recovering the surface. For a photo-derived normal map, estimate depth first, then derive normals from that field.

Try the workflow

Put this guide against your own image

The tool below is the same workbench described in this article. Generate a free preview, inspect the source checks, and decide whether the image is worth a production file.

Free browser converter

Already have a height or depth map? Convert it to a normal map

Brightness is treated as height. The file stays in your browser; nothing is uploaded. Use the workbench above when you want the height field estimated from a photograph instead.

Need height from a photo?
Source height
Your source preview appears here.
Tangent-space normal
The normal map preview appears here.

A luminance-derived normal map invents surface direction from brightness. It is useful for height maps and quick material tests, not for recovering geometry that the image never recorded. Read the normal map workflow guide before shipping a map to a shader.

The free local conversion

The normal map generator on this site includes a free converter. Choose a height or depth PNG, set the strength, choose OpenGL or DirectX green, and download the tangent-space PNG. The file stays in the browser; nothing is uploaded. That makes it suitable for client work and for iterating on a map without a round trip.

Strength controls how exaggerated the slope is. Too low and the map looks flat; too high and every compression block becomes a ridge. Start near 1.0 to 1.5 for a normalized height field, inspect the result on a lit sphere or a simple material, and adjust from there.

OpenGL and DirectX green channels

A tangent-space normal map stores the surface direction in three channels. The red and blue channels usually behave the same across engines, but the green channel differs. OpenGL-style maps point green up; DirectX-style maps point green down. If the convention is wrong, the lighting looks inverted: bumps read as dents and dents as bumps.

The converter exposes a DirectX toggle so you can produce both versions from the same source. Test on a known surface rather than guessing from the image. A lit sphere or a cube reveals the convention in seconds.

Normal maps are usually stored as 8-bit RGB, which is enough because the three channels are normalized and the eye is more sensitive to lighting changes than to the exact byte. Do not upconvert an 8-bit normal map to 16-bit and expect smoother shading; the direction information is already quantized. If banding appears on a very smooth curved surface, add geometry or use a higher-precision workflow in the DCC tool rather than padding the PNG.

Seams, borders, and tiling

A normal map derived from a height field is only as good as the height field's edges. If the height map is supposed to tile, the left and right edges must match, and the top and bottom must match. The converter clamps at the border instead of wrapping, so a non-tiling source will show a seam when repeated.

For a single relief or a non-tiling asset, a flat border is usually better than a sharp edge. For a tiling material, build the height field so the edges are continuous before conversion. No amount of normal-map strength fixes a discontinuity in the source.

When the texture will be sampled with mipmaps, keep a small padding band around the tile and author the edges as if they continue beyond the crop. The converter clamps at the border, so the padding is what prevents a bright rim from appearing when the material repeats at a distance.

Validate in the shader, not in the image viewer

A normal map can look plausible as an image and fail in the material. Import it into the target engine, apply it to a simple surface, and rotate the light. Check the direction, the strength, the green channel, and whether the map is tangent-space or object-space. If the engine expects a different space, the result will be wrong even if the file is valid.

Record the source, the strength, the channel convention, and the engine. A normal map without that context is hard to reproduce. The production bundle's manifest does this for the depth-derived path; the free converter gives you the PNG and the settings you chose. Keep a short note beside the file so the next artist does not have to guess which convention produced it.

When to use the photo-derived path

Use the photo-derived path when the goal is look development, a relief, or a quick surface-orientation pass from an image that has no height data. Use the height-map path when the data already exists and you need a deterministic conversion. Mixing the two without saying which one you used is how a team ends up comparing a measurement with an interpretation.

The photo path still cannot recover hidden sides, glass, mirrors, smoke, or fine hair. Treat the output as front-facing surface information and check it against the depth field before it reaches a shader.

Before the file moves forward

Final checklist

  • The input is identified as a height map or a photograph.
  • A height map is converted locally without uploading it.
  • The strength is tested on a lit sphere or simple material.
  • The green channel matches the target engine (OpenGL or DirectX).
  • Tiling sources have continuous edges before conversion.
  • The map is validated in the shader, not only in an image viewer.
  • The source, strength, and convention are recorded with the asset.

Straight answers

Questions this workflow raises

Can I create a normal map from a JPG?

Yes, but a JPG is a poor height source because compression blocks and sharpening halos become slopes. Use a lossless height map when you have one. If the JPG is a photograph, estimate depth first and treat the result as an interpretation.

Is the normal map converter really free?

Yes. The browser converter runs locally and downloads a PNG at no cost. The photo-derived production bundle is a separate paid workflow with one credit per approved job.

Why does my normal map look inverted?

The green channel convention is probably wrong for the target engine. Switch between OpenGL and DirectX and test on a lit sphere. Also confirm that the height direction is not reversed.

What strength should I use?

Start around 1.0 to 1.5 for a normalized height field, then adjust while watching a known surface. Higher strength exaggerates noise as well as detail.