Combining AO, Roughness, and Metallic Textures in glTF

In the glTF 2.0 specification, ambient occlusion, roughness, and metallic maps are combined into a single image using a technique called channel packing. Instead of loading three individual grayscale textures, glTF stores these distinct material properties across the color channels of a single RGB image—commonly referred to as an ORM (Occlusion, Roughness, Metallic) texture. This article details the specific channel assignments defined by the standard, how the glTF JSON structure references them, and why this optimization is standard practice in real-time 3D rendering.

The Standard Channel Assignment

The glTF 2.0 format designates specific color channels within a packed texture to represent each surface property:

  • Red Channel (R): Ambient Occlusion. Defines areas that receive less indirect or ambient light due to self-shadowing and crevice geometry.
  • Green Channel (G): Roughness. Dictates the micro-surface detail of the material, where 0.0 represents a mirror-smooth surface and 1.0 represents a completely rough, diffuse surface.
  • Blue Channel (B): Metallic. Dictates whether the material acts as a dielectric (0.0) or a conductor/metal (1.0).
  • Alpha Channel (A): Unused for PBR parameters. It can be left empty or omitted entirely by using a three-channel RGB format.

How glTF References Packed Textures

Although all three maps share a single image file, the glTF schema separates the material definitions into two distinct properties: occlusionTexture and metallicRoughnessTexture.

To combine them into a single file, both texture definitions point to the exact same texture index in the glTF JSON structure:

  • The pbrMetallicRoughness block points its metallicRoughnessTexture parameter to the shared texture index. The rendering engine is instructed by the specification to sample the green channel for roughness and the blue channel for metalness. The red channel is ignored by this property.
  • The root material block defines an occlusionTexture parameter pointing to the exact same texture index. The renderer samples the red channel for occlusion, while ignoring the green and blue channels.

Because both references share the same texture asset, modern 3D engines recognize the shared index and bind the texture to the GPU only once.

Color Space Requirements

glTF strictly dictates that ambient occlusion, roughness, and metallic textures must be sampled in linear color space.

Unlike base color (albedo) maps, which store human-perceived color values and require an sRGB-to-linear conversion, ORM textures store raw mathematical data. If an authoring tool or renderer incorrectly applies an sRGB gamma curve to the packed texture, the material will render incorrectly, resulting in overly dark ambient shadows, exaggerated reflections, or incorrect metallic response.

Performance Benefits

Packing occlusion, roughness, and metallic data into one file yields significant runtime optimizations:

  • Reduced VRAM Usage: A single three-channel RGB texture requires significantly less memory than three independent grayscale textures, which are often loaded as separate 8-bit or 24-bit assets.
  • Fewer Texture Samplers: Standard graphics pipelines are limited by the number of active texture samplers per draw call. Packing data reduces three potential texture fetch operations down to one in the fragment shader.
  • Faster Load Times: Downloading and decoding one image reduces HTTP requests in web applications and decreases asset decompression overhead.