GltfInstance
Places one copy of a GltfAsset in the scene.
Each call creates its own FilamentInstance with independent transform, animation state, and material overrides. GPU resources (geometry, textures) are shared from the asset.
Accepts a nullable asset so it composes naturally with rememberGltfAsset's suspend-lambda overload, which returns null while loading. When asset is null this composable is a no-op.
Typical usage:
// single static model — loading handled internally
GltfInstance(
asset = rememberGltfAsset { Res.readBytes("files/models/Duck.glb") },
position = Position(0f, 0f, 0f),
)
// multiple copies from a shared asset
val tree = rememberGltfAsset { Res.readBytes("files/models/Tree.glb") }
GltfInstance(tree, position = Position(0f, 0f, 0f))
GltfInstance(tree, position = Position(5f, 0f, 0f))Emitting from a list
Wrap each call in key() when the collection can change:
enemies.forEach { enemy -> key(enemy.id) { GltfInstance(enemyAsset, enemy.position) } }Without it, identity follows the slot rather than the item, so inserting or reordering makes every later entry destroy its instance and build a new one — restarting animation playback and re-running onCreate. Appending to the end is the only safe unkeyed case.
Lifecycle Note
Filament's gltfio does not have a destroyInstance API; instances are automatically destroyed when the parent GltfAsset is destroyed. To avoid memory pressure, avoid creating hundreds of dynamic instances from a single long-lived asset.
Parameters
A loaded asset from rememberGltfAsset, or null while still loading.
World-space translation.
World-space rotation. Build one with Rotation.axisAngle/Rotation.euler.
Per-axis scale.
The point in mesh space that rotation and scale revolve around, and that ends up at position in world space. Defaults to (0,0,0) — the glTF's own root origin. Use this to e.g. rotate a model around its centre when the glTF was authored with the origin at one corner.
Index of the skeletal animation to play. Null to disable. Ignored when animationState is supplied.
Current time in seconds for the animation. Ignored when animationState is supplied.
Optional hoisted, auto-advancing playback state from rememberAnimationState. When non-null it drives the animator every frame (with cross-fade blending) and takes precedence over animationIndex/animationTime.
Optional vertex morph-target weights applied to every renderable in the instance that has morph targets. Pass null to leave morph weights untouched.
Overrides shadow casting for every renderable in the instance; null (the default) keeps what the asset authored — matching the primitives' castShadows toggle.
Overrides shadow receiving for every renderable in the instance; null (the default) keeps what the asset authored.
Whether the instance's entities are in the scene. False removes them (cheaply, keeping the instance and its state alive) — a show/hide toggle.
Called once when the instance is first added to the scene. Use for one-time setup such as swapping materials or finding entities by name.
Called on every recomposition (not every frame — a static scene never recomposes). Use it to react to Compose state changes with low-level calls; for genuinely per-frame work use OnFrame or rememberFilamentScene's FilamentEffect.