Skip to main content

Overview

Filament’s gltfio library provides a complete pipeline for loading glTF 2.0 assets and converting them into Filament entities and components. The library handles parsing glTF/GLB files, creating geometry, materials, textures, and animations.

AssetLoader

The AssetLoader class consumes glTF content and produces FilamentAsset objects containing all necessary Filament resources.

Basic Usage

#include <gltfio/AssetLoader.h>
#include <gltfio/ResourceLoader.h>
#include <gltfio/TextureProvider.h>

// Create material provider
auto materials = createJitShaderProvider(engine);
// or for faster startup:
// auto materials = createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA,
//                                            UBERARCHIVE_DEFAULT_SIZE);

// Create asset loader
auto loader = AssetLoader::create({engine, materials});

// Load glTF file
std::vector<uint8_t> buffer = readFile("model.gltf");
FilamentAsset* asset = loader->createAsset(buffer.data(), buffer.size());

// Load external resources (textures, buffers)
ResourceLoader resourceLoader({engine, "."});
auto stbProvider = createStbProvider(engine);
auto ktx2Provider = createKtx2Provider(engine);
resourceLoader.addTextureProvider("image/png", stbProvider);
resourceLoader.addTextureProvider("image/jpeg", stbProvider);
resourceLoader.addTextureProvider("image/ktx2", ktx2Provider);
resourceLoader.asyncBeginLoad(asset);

// Add to scene
scene->addEntities(asset->getEntities(), asset->getEntityCount());

// Cleanup when done
scene->removeEntities(asset->getEntities(), asset->getEntityCount());
loader->destroyAsset(asset);
materials->destroyMaterials();
delete materials;
AssetLoader::destroy(&loader);

Material Providers

gltfio uses a plugin interface for material creation:

JitShaderProvider

Compiles materials at runtime using the filamat library:
auto materials = createJitShaderProvider(engine, OPTIMIZE_MATERIALS);
  • Generates optimal shaders for each material
  • Slower startup time
  • Smaller shader code

UbershaderProvider

Loads precompiled ubershader materials from a .uberz archive:
auto materials = createUbershaderProvider(engine, 
    UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE);
  • Fast startup time
  • Larger, more complex shaders
  • No runtime compilation

Supported glTF Extensions

Filament supports the following glTF 2.0 extensions:

Material Extensions

  • KHR_materials_pbrSpecularGlossiness - Specular-glossiness workflow
  • KHR_materials_clearcoat - Clear coat layer for materials
  • KHR_materials_transmission - Transmission/refraction effects
  • KHR_materials_volume - Volumetric effects and subsurface scattering
  • KHR_materials_ior - Index of refraction
  • KHR_materials_specular - Specular color and strength
  • KHR_materials_sheen - Sheen layer for cloth-like materials
  • KHR_materials_unlit - Unlit materials
  • KHR_materials_emissive_strength - Enhanced emissive control

Texture Extensions

  • KHR_texture_transform - UV transformations (offset, scale, rotation)
  • KHR_texture_basisu - Basis Universal compressed textures

Mesh Extensions

  • KHR_mesh_quantization - Quantized vertex attributes
  • KHR_draco_mesh_compression - Draco mesh compression (platform-dependent)

Other Extensions

  • KHR_lights_punctual - Point, spot, and directional lights

Instancing

Create multiple instances of the same asset to share resources:
FilamentInstance* instances[10];
FilamentAsset* asset = loader->createInstancedAsset(
    buffer.data(), buffer.size(), instances, 10);

// Each instance has unique transforms and material instances
for (int i = 0; i < 10; i++) {
    auto animator = instances[i]->getAnimator();
    // Animate each instance independently
}

Animation

Access the animator from the asset instance:
auto animator = asset->getInstance()->getAnimator();

// Play animation
if (animator->getAnimationCount() > 0) {
    animator->applyAnimation(0, currentTime);
    animator->updateBoneMatrices();
}

Resource Loading

The ResourceLoader handles asynchronous loading of external resources:
ResourceLoader resourceLoader({engine, gltfPath.c_str()});
resourceLoader.normalizeSkinningWeights = true;

// Add texture decoders
resourceLoader.addTextureProvider("image/png", stbProvider);
resourceLoader.addTextureProvider("image/jpeg", stbProvider);
resourceLoader.addTextureProvider("image/ktx2", ktx2Provider);

// Start async loading
resourceLoader.asyncBeginLoad(asset);

// Poll progress in render loop
float progress = resourceLoader.asyncGetLoadProgress();
if (progress < 1.0f) {
    // Still loading...
}

// Update loading state
resourceLoader.asyncUpdateLoad();

Best Practices

  1. Release source data after resource loading completes:
    asset->releaseSourceData();
    
  2. Recompute bounding boxes if needed:
    asset->getInstance()->recomputeBoundingBoxes();
    
  3. Use ubershaders for faster startup in production builds
  4. Share AssetLoader across multiple assets to reuse material cache
  5. Prefer instancing over loading the same asset multiple times

See Also

Build docs developers (and LLMs) love