glTF KHR_draco_mesh_compression Explained

The KHR_draco_mesh_compression extension dramatically reduces glTF 3D asset file sizes by structurally altering how geometric data—specifically vertex attributes and triangle connectivity—is packaged and stored. This article outlines the specific structural transformations executed by the extension within the glTF file format, detailing how traditional byte-aligned vertex buffers are replaced with highly optimized, compressed bitstreams using Google’s Draco library.

Schema-Level Structural Transformation

In standard glTF 2.0 assets, mesh geometry is stored in raw, uncompressed binary arrays. The mesh.primitives object defines mesh data through an attributes dictionary and an indices property, which point to individual accessors that directly map to byte offsets within bufferViews.

When KHR_draco_mesh_compression is applied, this structure is redirected:

  1. Primitive Redirection: The extension is injected directly into mesh.primitives.extensions.KHR_draco_mesh_compression.
  2. Buffer Consolidation: Instead of referencing separate bufferViews for each vertex attribute (POSITION, NORMAL, TEXCOORD_0) and index array, the extension points to a single bufferView containing the entire compressed Draco bitstream.
  3. Attribute ID Mapping: An attributes dictionary within the extension maps glTF attribute semantics (e.g., "POSITION": 0, "NORMAL": 1) to internal Draco attribute identifiers.
  4. Bypassing Raw Accessors: The standard accessor properties under primitive.attributes and primitive.indices are bypassed at runtime by Draco-capable parsers, functioning only as metadata fallbacks or compatibility placeholders for non-Draco loaders.

Geometry-Level Compression Mechanisms

Inside the Draco bitstream referenced by the consolidated bufferView, the structural compression is executed through several interdependent stages:

1. Connectivity and Topology Compression

Standard glTF files store topology as raw triangle lists (lists of vertex indices such as [0, 1, 2, 2, 3, 0]), which often consume significant storage. Draco replaces this structure using edge-based compression algorithms, primarily variants of the Edgebreaker algorithm. This method traverses the mesh surface and encodes the connectivity of adjacent triangles using a compact sequence of topological symbols (C, L, R, E, S), slashing the memory footprint of triangle indexes to just a few bits per triangle.

2. Attribute Quantization

Standard 3D models define coordinates, normals, and UVs as 32-bit floating-point numbers (FLOAT). Draco applies lossy quantization, converting these continuous floating-point values into discrete fixed-point integers based on user-defined bit depths (e.g., 14-bit for positions, 10-bit for normals). This standardizes the dynamic range and removes unnecessary precision noise.

3. Prediction Schemes (Delta Encoding)

Rather than storing absolute coordinate values, Draco uses topological connectivity to predict the position of adjacent vertices. The most common technique is parallelogram prediction, which assumes that two adjacent triangles forming a quad approximate a flat parallelogram. The decoder estimates the fourth vertex from the first three, requiring the bitstream to store only the small corrective residual (delta) between the predicted and actual position.

4. Entropy Coding

Finally, the quantized delta residuals, connectivity symbols, and attribute headers are compressed using asymmetric numeral systems, specifically rANS (Range Asymmetric Numeral Systems) or adaptive arithmetic coding. This entropy encoding packs frequently occurring symbols into the smallest possible number of bits.

Transmission vs. Runtime Trade-off

The structural compression executed by KHR_draco_mesh_compression is optimized strictly for transmission and storage. Graphics processing units (GPUs) cannot directly render the Draco bitstream. Consequently, the client application must download a Draco WebAssembly (Wasm) or native decoder module to decompress the bitstream back into standard, GPU-ready vertex and index arrays in memory prior to rendering.