How to Encode Point Clouds Using glTF and Draco
This article provides an overview of how point cloud datasets are
structured, compressed, and encoded using the glTF 2.0 format paired
with Google Draco compression. It covers the structural definition of
points within glTF primitives, the configuration of the
KHR_draco_mesh_compression extension, the quantization and
spatial encoding of point attributes, and the decoding pathway for
real-time visualization.
glTF Representation of Point Clouds
In the glTF (GL Transmission Format) specification, geometry is
defined through meshes containing arrays of
primitives. A point cloud is defined by setting the
primitive's rendering mode to 0 (which
corresponds to POINTS in WebGL/OpenGL). Unlike standard
polygonal meshes, point clouds do not require triangle index arrays
(indices), though an index buffer can optionally be
provided.
The basic properties of each point are stored as vertex attributes. Standard glTF attributes include:
POSITION: Floating-point coordinates (XYZ) defining point locations.COLOR_0: RGB or RGBA values representing color data.NORMAL: Surface normal vectors, if surface reconstruction or lighting calculations are required.- Application-specific application data, such as LiDAR intensity,
classification, or timestamps, can be represented using custom
attributes prefixed with an underscore (e.g.,
_INTENSITY).
Draco Point Cloud Compression
Raw point cloud datasets containing millions of points result in
massive file sizes that hinder web transmission. Google Draco addresses
this via the KHR_draco_mesh_compression extension in
glTF.
When applied to point clouds, Draco bypasses its edge-breaker connectivity compression (which is used for triangle meshes) and instead utilizes point-cloud-specific compression techniques:
- Quantization: High-precision floating-point values (like 32-bit floats for positions) are scaled and converted into discrete integer grids (e.g., 11-bit to 16-bit integers). This determines the coordinate precision and provides the primary baseline for size reduction.
- Spatial Partitioning: Draco organizes points spatially using a Kd-tree decomposition. Points are recursively split along alternating spatial axes, allowing Draco to encode spatial coordinates as relative deltas within bounding boxes rather than absolute coordinates.
- Prediction Schemes: Attributes like colors and normals are encoded using predictive schemes based on spatial proximity. Once point positions are ordered via the Kd-tree, subsequent attribute values can be predicted from neighboring points.
- Entropy Coding: The resulting quantized and delta-encoded integer streams are compressed using an entropy encoder (such as Shannon entropy or ANS - Asymmetric Numeral Systems) to eliminate bit redundancy.
Encoding Draco Point Attributes in glTF
To bind Draco-compressed point data into a glTF asset, the primitive
definition in the glTF JSON references the
KHR_draco_mesh_compression extension:
{
"meshes": [
{
"primitives": [
{
"mode": 0,
"attributes": {
"POSITION": 0,
"COLOR_0": 1
},
"extensions": {
"KHR_draco_mesh_compression": {
"bufferView": 0,
"attributes": {
"POSITION": 0,
"COLOR_0": 1
}
}
}
}
]
}
]
}The encoding structure requires two parallel definitions:
- Fallback Accessors: The standard
attributesdictionary at the primitive root points to standard glTFaccessors. These provide metadata (such as minimum and maximum bounds) and serve as uncompressed fallbacks for decoders that do not support Draco. - Draco Extension Mapping: Inside
extensions.KHR_draco_mesh_compression, thebufferViewpoints to the contiguous binary blob containing the Draco-compressed payload. The innerattributesmap binds glTF attribute semantics (POSITION,COLOR_0, etc.) to unique integer Draco attribute IDs configured during the Draco encoding process.
Decoding and Rendering Pipeline
When an application loads the glTF point cloud, it checks the
extensionsRequired and extensionsUsed arrays.
If KHR_draco_mesh_compression is detected:
- The Draco payload is extracted from the specified
bufferView. - The WebAssembly or native Draco decoder unpacks the Kd-tree and predictive streams.
- Quantized integers are dequantized back into standard typed arrays
(e.g.,
Float32Array). - The unpacked attribute arrays are bound to standard GPU vertex
buffer objects (VBOs) and rendered using the
POINTSdraw mode.