How to Use gltfpack Command-Line Options for glTF Optimization: A Complete Guide

gltfpack is the command-line front-end of the meshoptimizer library that optimizes glTF assets through quantization, compression, and scene simplification by mapping command-line flags to a Settings structure defined in gltf/gltfpack.h.

The gltfpack utility from the zeux/meshoptimizer repository provides a robust pipeline for reducing 3D asset file sizes while preserving runtime performance. Understanding how gltfpack command-line options translate into internal processing stages allows you to fine-tune optimization for web delivery, mobile VR, or high-fidelity desktop applications.

Understanding the gltfpack Architecture

The tool’s architecture follows a straightforward pipeline defined in gltf/gltfpack.cpp. The main() function (lines 1017–1045) handles argument parsing by iterating through argv and populating a Settings structure declared in gltf/gltfpack.h (lines 120–180). Depending on file extensions, it dispatches to parseGltf or parseObj (lines 1049–1055) before invoking the core process() function (lines 1053–1057).

The process() function orchestrates the optimization workflow, calling printMeshStats and printSceneStats when verbose flags (-v or -vv) are set. It then applies transformations guided by the Settings configuration, including quantization preparation via prepareQuantizationPosition and prepareQuantizationTexture (declared in gltfpack.h lines 166–176) before generating the final output.

Essential gltfpack Command-Line Options

All command-line switches directly map to fields in the Settings structure, controlling everything from vertex precision to texture encoding.

I/O and Basic Optimization

The fundamental flags specify input and output paths:

  • -i <file>: Sets the input path (accepts .gltf, .glb, or .obj extensions)
  • -o <file>: Specifies the output path (format inferred from extension)

By default, gltfpack applies integer quantization with 14-bit position precision. To adjust vertex precision or format, use the quantization flags described below.

Mesh Compression Settings

Control geometry compression through the Settings::compress* fields:

  • -c: Enables Draco-style mesh compression by setting Settings::compress = true
  • -cc: Activates higher-ratio compression via Settings::compressmore = true
  • -cz: Uses the KHR_meshopt_compression extension through Settings::compresskhr = true
  • -ce khr|ext: Explicitly chooses between Khronos extension style (khr) or extensible mode (ext)

Vertex Quantization Controls

These flags populate quantization bit fields in the Settings structure, controlling attribute precision:

  • -vp N: Sets position bits (1–16) via Settings::pos_bits
  • -vn N: Sets normal/tangent bits (1–16) via Settings::nrm_bits
  • -vt N: Sets texture coordinate bits (1–16) via Settings::tex_bits
  • -vc N: Sets vertex color bits (1–16) via Settings::col_bits

For position storage formats:

  • -vpi: Integer positions (default; sets pos_float = false; pos_normalized = false)
  • -vpn: Normalized positions (sets pos_float = false; pos_normalized = true)
  • -vpf: Floating-point positions (sets pos_float = true)

Additional format flags:

  • -vtf: Forces floating-point texture coordinates (tex_float = true)
  • -vnf: Forces floating-point normals (nrm_float = true)
  • -vi: Enables interleaved vertex buffers (mesh_interleaved = true)

Texture Optimization

Control texture encoding and dimensions through the texture processing flags:

  • -tu: Encodes textures to KTX2 with UASTC (texture_ktx2 = true; texture_mode = UASTC)
  • -tc: Encodes textures to KTX2 with ETC1S (texture_ktx2 = true; texture_mode = ETC1S)
  • -tw: Encodes textures to WebP (texture_webp = true; texture_mode = WebP)
  • -tq N: Sets compression quality 1–10 via Settings::texture_quality
  • -ts R: Scales texture dimensions by ratio R (0–1) via Settings::texture_scale
  • -tl N: Limits maximum texture size to N pixels via Settings::texture_limit
  • -tp: Resizes textures to power-of-two dimensions (texture_pow2 = true)
  • -tfy: Flips Y-axis during BasisU compression (texture_flipy = true)
  • -tr: Preserves original texture URIs instead of embedding (texture_ref = true)

Mesh Processing and Scene Optimization

Optimize scene structure and geometry complexity:

  • -gt: Generates tangent spaces (mesh_tangents = true)
  • -mi: Converts mesh duplicates to GPU instancing (mesh_instancing = true)
  • -mm: Merges duplicate meshes (mesh_merge = true)
  • -mdd: Disables mesh deduplication (mesh_dedup = false)
  • -si R: Simplifies meshes to R ratio of original triangles (e.g., 0.5 for 50%)
  • -sa: Enables aggressive simplification mode

Preservation Flags

Prevent gltfpack from removing specific data:

  • -kv: Keeps all vertex attributes (keep_attributes = true)
  • -km: Preserves all material definitions (keep_materials = true)
  • -ke: Retains extras JSON blocks (keep_extras = true)
  • -kn: Preserves complete node hierarchy (keep_nodes = true)

Verbosity and Diagnostics

  • -v: Enables basic statistics (verbose = 1)
  • -vv: Enables detailed statistics (verbose = 2)
  • -h: Displays full usage information and exits

Practical gltfpack Usage Examples

Apply default optimization with integer quantization:

gltfpack -i model.gltf -o model_opt.gltf

Enable Khronos compression while preserving scene hierarchy:

gltfpack -c -ce khr -kn -i model.gltf -o model_opt.glb

Convert textures to high-quality UASTC and generate tangents:

gltfpack -tu -tq 10 -gt -i model.gltf -o model_opt.gltf

Reduce texture resolution by 50% and enforce power-of-two dimensions:

gltfpack -ts 0.5 -tp -i model.gltf -o model_opt.gltf

Aggressive mesh simplification to 30% of original triangles:

gltfpack -si 0.3 -sa -i model.gltf -o model_opt.gltf

Summary

  • gltfpack maps command-line arguments to a Settings structure in gltf/gltfpack.h (lines 120–180), with parsing logic in gltf/gltfpack.cpp.
  • Compression options (-c, -cc, -cz, -ce) control whether Draco-style or KHR_meshopt_compression encoding is applied to geometry.
  • Quantization flags (-vp, -vn, -vt, -vc) configure bit precision for vertex attributes, directly affecting memory usage and visual quality.
  • Texture flags (-tu, -tc, -tw, -tq, -ts) support KTX2, WebP, and rescaling workflows for optimized texture delivery.
  • Scene processing (-mi, -mm, -si) enables instancing, merging, and simplification to reduce draw calls and geometry complexity.

Frequently Asked Questions

What is the difference between -c and -cz in gltfpack?

The -c flag enables standard Draco-style mesh compression stored as a buffer extension, while -cz specifically uses the KHR_meshopt_compression Khronos extension format. According to the source code in gltfpack.cpp, -cz sets Settings::compresskhr = true, which produces glTF files compatible with the official Khronos extension rather than the legacy extensible format.

How do I prevent gltfpack from modifying my node hierarchy?

Use the -kn (keep nodes) flag to preserve the complete node hierarchy. This sets Settings::keep_nodes = true in the processing pipeline, preventing gltfpack from optimizing away empty nodes or flattening transforms during the scene optimization stage.

What quantization settings should I use for WebGL applications?

For WebGL deployment, use -vp 14 -vn 10 -vt 12 for balanced quality and size, or -vp 16 for maximum precision. The -vi flag enables interleaved vertex buffers, improving GPU cache coherency. These settings populate the Settings::pos_bits, nrm_bits, and tex_bits fields to compress vertex data while maintaining acceptable visual fidelity for real-time rendering.

Can gltfpack optimize existing glTF files without changing the file format?

Yes, gltfpack preserves the output format based on the file extension specified in -o. If you input a .gltf file and output to .gltf, it maintains the separate JSON/bin structure; outputting to .glb produces a binary glTF. Use -tr to preserve external texture references rather than embedding them, maintaining the original asset structure while still optimizing geometry and compression.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →