glTF Normal Map Flipping: DirectX vs OpenGL
This article explains how the glTF 2.0 3D asset format handles normal map conventions between DirectX and OpenGL workflows. glTF strictly mandates the OpenGL tangent-space standard (+Y up), meaning it does not use runtime flags or dynamic toggles to flip normal maps. Instead, it relies on asset creators to invert the green channel during export from DirectX-based tools, or requires DirectX-based rendering engines to flip the green channel at shader level during ingestion.
The Difference Between DirectX and OpenGL Normal Maps
The fundamental conflict between DirectX and OpenGL normal maps lies in their tangent space definition, specifically the orientation of the green (Y) color channel:
- OpenGL (+Y Up): The green channel represents the vertical surface displacement pointing upward. Surfaces tilted toward the top of the texture reflect light as if facing the top edge.
- DirectX (-Y / +Y Down): The green channel is inverted compared to OpenGL. The vertical displacement points downward, causing inverted lighting calculations if read by an OpenGL-oriented renderer.
Both standards share the same convention for the red channel (+X pointing right) and the blue channel (+Z pointing outwards from the surface).
glTF's Strict OpenGL Standard
glTF 2.0 standardizes all tangent-space normal maps strictly to the OpenGL convention. The glTF specification explicitly dictates that:
- The red channel (\(R\)) maps to \(+X\) (Tangent direction).
- The green channel (\(G\)) maps to \(+Y\) (Bitangent direction, pointing up relative to the UV coordinates).
- The blue channel (\(B\)) maps to \(+Z\) (Normal direction, facing away from the surface).
By strictly requiring OpenGL orientation, glTF eliminates ambiguity. The file format intentionally avoids metadata flags that indicate whether an embedded or referenced texture is in DirectX or OpenGL format. This design ensures that every compliant glTF reader can process normal maps identically without conditional branching in texture decoding.
How Flipping Is Handled in the Pipeline
Because glTF does not perform automated format switching internally, managing the convention shift depends on where the asset originates and where it is rendered.
1. Ingestion and Export from Content Creation Tools
When exporting assets from authoring tools that use DirectX conventions (such as Substance 3D Painter configured for Unreal Engine, or 3ds Max):
- The export pipeline must flip the green channel before writing the glTF texture data.
- Mathematically, this operation inverts the channel: \[\text{Green}_{\text{glTF}} = 1.0 - \text{Green}_{\text{DirectX}}\]
- Most standard glTF exporters (such as the Khronos Blender glTF exporter or Substance Painter glTF presets) automatically handle this inversion during the export process.
2. Rendering glTF in DirectX-Based Engines
When a runtime engine natively built on DirectX (such as Unreal Engine or custom Direct3D renderers) loads a glTF file, the engine must accommodate glTF's OpenGL normal map:
- Texture Import Inversion: The engine can invert the green channel of the normal map during the texture import/decompression stage.
- Shader Inversion: The pixel shader can negate the \(Y\) component of the sampled normal vector before performing lighting calculations: \[\vec{N}_{\text{DirectX}} = \text{vec3}(N.x, -N.y, N.z)\]
Through strict standardization rather than dynamic negotiation, glTF shifts the responsibility of normal map orientation to the export and import boundaries of the 3D pipeline.