TA Toolbox Home / TA Glossary

Normal Map Format: DirectX vs OpenGL

Published 2026-08-27 · Revised 2026-10-08

Use explicit tangent-space conventions

In the common normal-map naming convention, OpenGL Y+ and DirectX Y- differ in the sign of the tangent-space Y component, encoded in the green channel. These labels do not by themselves select a rendering graphics API.

Do not infer the format from a purple tint, a single colored edge, or the word “up” without a coordinate definition. Check the source application's export setting and the target material/import pipeline.

Flat normals do not distinguish the format

You cannot identify the format from a flat normal. A tangent-space normal (0,0,1) is encoded approximately as (128,128,255) in an 8-bit RGB image. Quantization means 127 and 128 straddle the neutral value; that tiny difference is not a reliable format detector.

Convert only a known Y-convention mismatch

For an otherwise matching tangent-space basis, invert the green component: G_new = 1 - G in normalized values, or G_new = 255 - G in 8-bit channels. Green-channel inversion is not the same operation as vertically flipping the image or flipping UVs.

Do not invert twice in both the source image and importer. Different tangent bases, mesh normals, UV orientation, compression and material decoding can require other fixes.

Validate on the same mesh and lighting

  1. Record the exporter/importer convention.
  2. Use one mesh with a known raised or recessed feature and fixed lighting.
  3. Compare the original against a green-inverted copy, changing only one setting.
  4. Check the actual target material. Do not assume an engine automatically detects the convention.

Reference: Adobe: OpenGL and DirectX normal formats. Engine-specific behavior must be verified in your project; this article is not a claim of a completed engine rendering test.

FAQ

What do the two names mean?

The common convention is OpenGL Y+ and DirectX Y-. Confirm the actual tangent-space convention in the source and target pipelines.

Can neutral purple identify the format?

No. A flat normal encodes approximately as (128,128,255) in both conventions; inspect export settings and a controlled render instead.

How should I convert a known Y mismatch?

Invert the green channel once, and compare the two variants on the same mesh and lighting. Do not treat image or UV flipping as an equivalent operation.