EXT_materials_bump vs glTF Normal Mapping
In the glTF 2.0 ecosystem, simulating surface relief without
increasing geometric complexity is essential for real-time rendering
performance. While core glTF relies on standard tangent-space normal
mapping via the normalTexture property, the
EXT_materials_bump extension introduces support for
traditional height-based bump mapping. This article examines how these
two approaches fundamentally differ in data representation, runtime
computation, memory consumption, mesh requirements, and visual
fidelity.
Data Representation and Encoding
The primary distinction between the two approaches lies in the data stored within the texture:
- Standard Normal Mapping: Uses a three-channel (RGB) or two-channel texture to store directional vectors. Each pixel encodes an explicit surface normal perturbed relative to the surface's tangent space, where RGB channels correspond directly to the X, Y, and Z vector coordinates.
- EXT_materials_bump: Uses a single-channel (grayscale) height map. Pixels store scalar values representing relative elevation or surface displacement rather than directional vectors.
Runtime Shader Computation
Because the textures store different types of data, the GPU must process them differently to calculate surface lighting:
- Standard Normal Mapping: The fragment shader performs a direct texture lookup, unpacks the sampled color from the \([0, 1]\) range to the \([-1, 1]\) vector range, and transforms it using the Tangent-Bitangent-Normal (TBN) frame. This operation is computationally lightweight and straightforward.
- EXT_materials_bump: The fragment shader cannot use
the sampled scalar value directly. Instead, it must dynamically compute
the surface normal by evaluating the gradient of the height values
across adjacent pixels. This is typically done using screen-space
partial derivatives (such as
dFdxanddFdy) or multi-tap sampling algorithms to approximate the slope of the surface at runtime.
Vertex and Mesh Requirements
Both methods affect the requirements placed on the underlying mesh geometry:
- Standard Normal Mapping: Strictly requires a consistent tangent space across the mesh. To prevent lighting discontinuities, glTF assets typically require precomputed vertex tangents (often adhering to the MikkTSpace standard) stored directly in the mesh attributes.
- EXT_materials_bump: Can generate perturbed normals procedurally using surface position derivatives and texture coordinate gradients. This reduces the strict necessity for precomputed vertex tangents, simplifying mesh export pipelines in specific workflows.
Memory Footprint and Performance
Each technique introduces different performance trade-offs:
- Memory Usage:
EXT_materials_bumpis more memory-efficient. A bump map requires only a single 8-bit or 16-bit channel, reducing texture file size, VRAM usage, and bandwidth compared to a standard normal map that requires two or three channels. - GPU Processing: Standard normal mapping is more computationally efficient in the fragment stage. Bump mapping shifts the burden to the ALU by requiring real-time derivative calculations or multiple texture fetches per pixel to derive the surface slope.
Visual Quality and Artifacts
- Precision: Standard normal maps provide smooth, consistent shading across varying viewing angles and distances because the vector direction is explicitly precalculated.
- Derivative Artifacts: Height-derived bump maps from
EXT_materials_bumpcan suffer from stair-stepping, aliasing, or precision loss, particularly when using standard 8-bit height maps. High-frequency details can become unstable across mipmap levels if the shader's derivative calculations are not properly filtered.