How Lightmaps Are Structured in glTF Models
This article explores the structural composition of lightmaps embedded in glTF (GL Transmission Format) 3D assets, examining how baked illumination data is integrated into the format's JSON hierarchy and binary payloads. It covers the storage of image and buffer data, the essential role of secondary UV texture coordinates, and the extension mechanisms used to bind baked lighting data to 3D surfaces.
Image Data and Binary Storage
Lightmaps within a glTF container are fundamentally stored as texture
resources, organized across standard glTF top-level arrays:
images, textures, samplers, and
bufferViews.
- The
imagesArray: Defines the raw lightmap asset. If the glTF is stored as an embedded.gltfor binary.glbfile, the image is mapped to a specificbufferViewpointing to a binary chunk. Common formats include PNG, JPEG, or compressed GPU formats like KTX2 (via theKHR_texture_basisuextension) for lower memory consumption. - The
samplersArray: Dictates filtering and wrapping behavior. Lightmaps typically useLINEARorLINEAR_MIPMAP_LINEARfiltering withCLAMP_TO_EDGEwrapping to prevent illumination leaking across tile boundaries. - The
texturesArray: Pairs an image index with a sampler index, creating a complete texture resource that materials can reference.
UV Mapping: The Role of TEXCOORD_1
Unlike diffuse or normal maps that frequently reuse overlapping, mirrored, or tiled UV layouts, lightmaps require unique, non-overlapping UV unwraps for all static surfaces receiving baked illumination.
Inside the glTF hierarchy, this is handled under the mesh primitives:
"primitives": [
{
"attributes": {
"POSITION": 0,
"NORMAL": 1,
"TEXCOORD_0": 2,
"TEXCOORD_1": 3
},
"indices": 4,
"material": 0
}
]TEXCOORD_0typically carries the repeating tiling data for base color and material maps.TEXCOORD_1points to an accessor containing the dedicated, globally unique UV coordinates dedicated to reading the lightmap across the mesh surface.
Material Bindings and glTF Extensions
The core glTF 2.0 specification does not provide a native
lightmapTexture property inside standard PBR materials.
Consequently, lightmaps are structurally integrated through one of three
primary methodologies:
- Vendor and Community Extensions: Extensions such as
MOZ_lightmapor custom engine extensions inject alightmapTextureobject directly into thematerial.extensionsdefinition. This object references the texture index and explicitly states whichtexCoordchannel to evaluate, along with scaling factors for exposure control. - Repurposed Occlusion Slots: In workflows lacking
custom extension support, pipelines sometimes inject the lightmap into
the standard
occlusionTextureslot. While structurally compliant with core glTF 2.0, this approach limits lighting evaluation to single-channel scalar values or non-standard engine interpretations of RGB occlusion maps. - Multi-Material Layering via Composition: Advanced
pipelines split geometries or evaluate secondary primitive passes using
unlit materials (
KHR_materials_unlit) that carry the lightmap data, allowing external rendering engines to multiply the light pass against the diffuse surface pass at runtime.
Data Composition at Runtime
When an engine parses an embedded lightmap in glTF, it resolves the
dependency graph from the material through the designated texture
accessor, fetches the non-overlapping coordinates from
TEXCOORD_1, and decodes the image binary from the
underlying buffer. The rendering engine multiplies or adds this
precomputed radiance directly into the fragment stage of the PBR
pipeline, replacing or augmenting dynamic ambient calculations.