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:
- Primitive Redirection: The extension is injected
directly into
mesh.primitives.extensions.KHR_draco_mesh_compression. - Buffer Consolidation: Instead of referencing
separate
bufferViewsfor each vertex attribute (POSITION,NORMAL,TEXCOORD_0) and index array, the extension points to a singlebufferViewcontaining the entire compressed Draco bitstream. - Attribute ID Mapping: An
attributesdictionary within the extension maps glTF attribute semantics (e.g.,"POSITION": 0,"NORMAL": 1) to internal Draco attribute identifiers. - Bypassing Raw Accessors: The standard
accessorproperties underprimitive.attributesandprimitive.indicesare 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.