Every GLB file you download from BitSoul's marketplace is already GLTF 2.0 under the hood — but vanilla GLTF is just the baseline. Extensions are where the format gets genuinely useful for game production: mesh compression that cuts transfer sizes by 80 %, per-instance transform data that lets a single draw call scatter a thousand props, and material variants that swap skins without extra geometry. The problem is that engine support is fragmented and poorly documented. This guide maps what's actually implemented, what still requires manual workarounds, and how to bake the right extensions into your export pipeline.
What GLTF extensions are and why they matter for game pipelines
GLTF separates the core spec from optional features through a formal extension system. A file declares which extensions it uses in the `extensionsUsed` array and which are non-negotiable in `extensionsRequired`. Importers that don't recognise a required extension must reject the file; optional extensions can be silently ignored.
For game developers, this matters because it means a single `.glb` file can carry compressed geometry, instancing hints, and material variants — all without breaking importers that don't support those features. You build one asset, tag it correctly, and let each engine pick up what it understands.
![]()
The extension landscape breaks into three practical tiers for game artists:
| Tier | Extensions | Status |
|------|-----------|--------|
| Broadly supported | `KHR_materials_unlit`, `KHR_texture_transform` | Unity, UE5, Godot 4 |
| Widely supported | `KHR_draco_mesh_compression`, `KHR_materials_variants` | Unity (via package), Godot 4 native, UE5 plugin |
| Limited / experimental | `EXT_mesh_gpu_instancing`, `KHR_mesh_quantization` | Godot 4 only (partial), manual in Unity/UE5 |
KHR_draco_mesh_compression — shrink assets for faster loads
Draco is Google's open-source mesh compression library. When the `KHR_draco_mesh_compression` extension is applied, vertex buffers are replaced with a Draco-encoded bitstream that typically shrinks geometry data 70–90 % compared to uncompressed GLTF. For a 500-polygon prop, the difference is barely measurable; for a dense environment mesh with 200 k triangles, you can drop from 8 MB to under 1 MB.
![]()
Exporting with Draco from Blender
Blender's built-in GLTF exporter supports Draco natively since Blender 3.3. Enable it under Export → GLTF 2.0 → Geometry → Compression:
```python
# Via bpy for batch export
import bpy
bpy.ops.export_scene.gltf(
filepath="/output/prop.glb",
export_format='GLB',
export_draco_mesh_compression_enable=True,
export_draco_mesh_compression_level=6, # 0–10; 6 is a good default
export_draco_position_quantization=14, # bits; 14 = near-lossless
export_draco_normal_quantization=10,
export_draco_texcoord_quantization=12,
)
```
Quantization trade-offs: lower bit counts = smaller files but visible vertex snapping. For props viewed from 5+ metres, 10-bit position quantization is often acceptable; for hero assets or characters, stay at 14 bits or higher.
Engine support
- Godot 4: Full native support. Import a Draco GLB and the editor decodes it transparently. No extra setup.
- Unity: Requires the `com.unity.cloud.gltfast` package (v6+). Install via Package Manager → Add by name. GLTFast decodes Draco during import and stores the result as a normal Unity mesh — the Draco data is not kept at runtime, so there is no runtime decompression overhead.
- Unreal Engine 5: The built-in GLTF importer does not support Draco. Use the glTFRuntime plugin (MIT licence, available on GitHub) or pre-decompress with `gltf-transform decompress` before handing the file to UE5's native importer.
```bash
# Pre-decompress for UE5 (requires @gltf-transform/cli)
npx @gltf-transform/cli decompress input_draco.glb output_plain.glb
```
EXT_mesh_gpu_instancing — scatter props with a single draw call
`EXT_mesh_gpu_instancing` embeds per-instance transform data (translation, rotation, scale) directly in the GLTF buffer. A single mesh node can describe thousands of placed instances with one accessor — an approach that maps cleanly to GPU instanced rendering and dramatically cuts CPU draw-call overhead.
![]()
The extension works by adding an `extensions` block to a mesh node that references three `VEC3`/`VEC4` accessors for TRS data:
```json
{
"name": "rocks_scattered",
"mesh": 0,
"extensions": {
"EXT_mesh_gpu_instancing": {
"attributes": {
"TRANSLATION": 1,
"ROTATION": 2,
"SCALE": 3
}
}
}
}
```
Engine support
- Godot 4: Partial support as of Godot 4.3. The editor reads instance data but converts it to individual `MeshInstance3D` nodes rather than a `MultiMesh`. If you need true GPU instancing, replace with a `MultiMeshInstance3D` at import time using an `EditorImportPlugin` script.
- Unity (GLTFast): Read-only support added in GLTFast 6.2 — instances are imported as a single `MeshRenderer` with GPU instancing enabled on the material. Verified working; instancing is active at runtime.
- Unreal Engine 5: Not supported natively or via glTFRuntime as of UE 5.4. The recommended path is to export instance positions as a CSV, then use UE5's Foliage Tool or Procedural Content Generation (PCG) to scatter the mesh using that data.
Engine support matrix: Unity, Unreal Engine 5, and Godot 4
The table below covers extensions relevant to assets from BitSoul's marketplace. "Native" means the built-in importer handles it without plugins.
| Extension | Unity (GLTFast) | Unreal Engine 5 | Godot 4 |
|-----------|----------------|-----------------|---------|
| `KHR_draco_mesh_compression` | ✅ v6+ | ❌ (glTFRuntime plugin) | ✅ native |
| `KHR_mesh_quantization` | ✅ v6+ | ❌ | ✅ native |
| `KHR_materials_variants` | ✅ v6+ | ❌ (plugin) | ✅ native |
| `EXT_mesh_gpu_instancing` | ✅ v6.2+ | ❌ | ⚠️ partial |
| `KHR_texture_transform` | ✅ | ✅ | ✅ |
| `KHR_materials_unlit` | ✅ | ✅ | ✅ |
| `KHR_lights_punctual` | ✅ | ✅ | ✅ |
Recommended export presets by target engine
For Godot 4 or Unity (GLTFast): Export from Blender with Draco enabled at level 6, position quantization 14 bits, texture transform if you use tiling. Tag `extensionsRequired` only for Draco.
For Unreal Engine 5: Export standard GLB without Draco. Use `gltf-transform` to strip unsupported extensions before import, or work from a pre-optimised FBX for the UE5 pipeline until Epic ships native Draco support.
For multi-engine distribution: Keep two exports — a Draco-compressed GLB for Godot/Unity and a plain GLB for UE5. Name them `prop_draco.glb` and `prop.glb` respectively.
Getting started with GLTF extensions today
Most assets on BitSoul's marketplace ship as plain GLB without extensions applied — which means maximum compatibility across all importers. Apply Draco compression as a post-process step in your own pipeline using `gltf-transform compress`:
```bash
npm install -g @gltf-transform/cli
gltf-transform compress --draco.method edgebreaker input.glb output_draco.glb
```
Check what extensions a file currently declares before importing:
```bash
python3 -c "
import struct, json, sys
with open(sys.argv[1], 'rb') as f:
f.read(12) # skip header
chunk_len = struct.unpack('<I', f.read(4))[0]
f.read(4) # chunk type JSON
data = json.loads(f.read(chunk_len))
print('extensionsUsed:', data.get('extensionsUsed', []))
print('extensionsRequired:', data.get('extensionsRequired', []))
" your_asset.glb
```
Understanding which extensions your target engine actually supports — not just which ones the exporter can produce — is the most reliable way to avoid silent import failures and unexpected runtime behaviour.
---
*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*