# gltf: a Rust crate for loading glTF 2.0 assets

> The gltf crate loads glTF 2.0 files in Rust, with optional support for extras, names, images and eleven glTF extensions. It splits into a loader, a JSON layer and a derive crate, and it ships four runnable examples that double as its documentation.

**gltf-rs/gltf** — A crate for loading glTF 2.0

- Repository: https://github.com/gltf-rs/gltf
- Stars: 644 · Forks: 160
- Language: Rust
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/gltf-rs-gltf

## A loader, not a renderer

The gltf crate is intended to load glTF 2.0, the file format from the Khronos Group designed for the efficient transmission of 3D assets. The description in the package manifest is simply a glTF 2.0 loader, and the keywords are glTF, 3D, asset, model and scene. The important thing to understand is what the crate does not do. There is no rendering, no windowing, no OpenGL context, and although the repository topics include opengl and pbr, those are attributes of the assets it reads rather than features it implements. What you get is a parsed representation of the scene graph, the surface definitions, the meshes, the animations and the textures, as Rust structs you can walk. The reference infographic from the Khronos specification is included in the README, with a link to a PDF version, which is a useful reminder that the format is layered, with a JSON core, buffers, accessors and a set of optional extensions, and that a loader has to understand the layering.

## The workspace is three crates, not one

The Cargo.toml shows the crate as the root of a small workspace with members `gltf-derive` and `gltf-json`, and the top level of the repository matches with a `gltf-derive/` directory, a `gltf-json/` directory, a `src/` directory, an `examples/` directory and a `tests/` directory. The split has a clear purpose. `gltf-json` is the serde layer over the raw glTF JSON, and the feature list is largely a pass-through to it, with `extras` forwarding to `gltf-json/extras`, `names` to `gltf-json/names`, `extensions` to `gltf-json/extensions` and each Khronos extension forwarding to the matching `gltf-json` feature. The `gltf-derive` crate is a procedural macro crate, which is what lets the loader generate typed accessors rather than making you hand write a struct per glTF object type. The root crate is the ergonomic layer over both, and the version is pinned so that the three move together, with `gltf-json` required at exactly the same version.

## The default features decide what you pay for

The default feature set is `import`, `utils` and `names`, and the `import` feature is what pulls in the heavier dependencies, namely `base64`, `image` and `urlencoding`. That matters, because `image` is where the jpeg and png decoders come from, and it is the reason the feature exists as a separate switch. Turning `import` off gives you a crate that reads the JSON and the metadata but does not decode embedded images or handle data URIs, which is a substantial difference in build time and in binary size for a tool that only needs to inspect an asset. The `image` dependency is configured with `default-features = false` and only the jpeg and png features enabled, so even with `import` on you are not pulling in every codec image supports. Two other feature flags exist for assets that break strict validation, `allow_empty_animation_target_node` and `allow_empty_texture`, which are forwarded to the JSON layer, and those are the flags to reach for when a real-world asset has a texture with no data or an animation channel pointing nowhere.

## Eleven extensions, each one a feature flag

Extension support is opt-in per extension, and the list covers eleven of them. The material extensions are the bulk of it, with `KHR_materials_pbrSpecularGlossiness`, `KHR_materials_unlit`, `KHR_texture_transform`, `KHR_materials_variants`, `KHR_materials_volume`, `KHR_materials_specular`, `KHR_materials_transmission`, `KHR_materials_ior` and `KHR_materials_emissive_strength`. There is also `KHR_lights_punctual` for punctual lights and `EXT_texture_webp` for WebP textures. You enable one by naming it in the features section of your dependency, and the README shows that as a Cargo snippet:

```toml
[dependencies.gltf]
features = ["KHR_materials_unlit"]
```

The `extensions` feature is separate and gates the general extension mechanism, while the named features gate the individual ones. The practical consequence is that an asset using an extension you have not enabled will not give you the typed data for it, so if your pipeline receives assets from a variety of exporters it is worth enabling the set you actually expect rather than discovering the gap when a material renders wrong. The `names` and `extras` features work the same way, and by default the crate ignores both, which keeps the common case cheap and predictable.

## The examples are the documentation

The README points to the crate documentation on docs.rs for example usage, but the repository ships four examples that are more informative than the prose. The `gltf-display` example demonstrates how the glTF JSON is deserialized. The `gltf-export` example goes the other way and shows how glTF JSON can be built and exported using the `gltf-json` crate. The `gltf-roundtrip` example deserializes and serializes the JSON part of an asset, which is the one to read if you care about whether a load and save cycle is lossless. And `gltf-tree` visualises the scene hierarchy of an asset, which the README describes as a strict tree of nodes. Each is a single cargo invocation:

```sh
cargo run --example gltf-display path/to/asset.gltf
```

The example directories in the repository are named to match, with `display/`, `export/`, `roundtrip/` and `tree/`, and there are asset files alongside them, a `Box.glb`, a `Box.gltf` and a `Box0.bin` and a `Lantern.gltf`, which are handy for trying a change without hunting for a test asset.

## Testing needs the Khronos sample models

The test setup has one prerequisite that is easy to miss. Running the tests locally requires cloning the KhronosGroup glTF-Sample-Models repository first:

```sh
git clone https://github.com/KhronosGroup/glTF-Sample-Models.git
```

That is not a stylistic choice, it is because the crate's tests run against the reference asset corpus, which is the only way to check a loader against the range of real files that exist in the wild, files with embedded textures, external buffers, compressed extensions and the awkward cases the specification allows. The dev dependencies are small, with `approx` for numeric comparison and `bytemuck` with the derive feature, and the rustfmt and clippy configuration files at the top level, along with a `clippy.toml`, show that the project holds itself to a strict lint and format bar. The licence in the manifest is MIT OR Apache-2.0, with a `LICENSE-APACHE` and a `LICENSE-MIT` file in the repository, which is the usual dual licence for a library that is meant to be usable in both open source and proprietary software.

## Where this is the wrong choice

The limits follow from the design and from the age of the project. First, the crate loads and does not draw. If you want a 3D application you will need a renderer, and the topic tags mentioning opengl and pbr reflect the assets rather than any rendering capability, so a team looking for a Rust 3D engine should look elsewhere. Second, extension coverage is a fixed list, and the list is not exhaustive, so an asset using an extension outside it will load but lose that part of the data, which is a quiet failure rather than a loud one. Third, the versions. The published releases on the repository are 1.0.0 from 2022-02-09, 0.15.0 from 2020 and 0.14.0 from 2019, while the manifest in the repository declares 1.4.1, which means the crate has moved on in the tree without a new tag being cut, and the README's own snippet pins version 1.4. That is workable but it means you should read the CHANGELOG.md before choosing a version, since the gap between the last tag and the manifest version is where the surprises live. Fourth, the Rust floor is 1.61, which is old enough to be a non-issue but new enough to matter if you are pinning a toolchain. Fifth, the corpus dependency, since running the test suite means pulling a large external repository of assets.

## Conclusion

gltf suits a Rust project that has to read 3D assets produced elsewhere, because it handles the glTF container properly, including the external binary and embedded buffer cases, and it leaves the rendering decisions to you. It is the wrong choice if you also want to render, since the crate loads rather than draws, and the wrong choice if you need an extension it does not support, since each one is a feature flag and an unimplemented extension is a silent gap in your asset handling. Before you pin a version, read the CHANGELOG.md, because the crate was published as 1.0.0 in 2022 and the manifest now says 1.4.1, and check that your toolchain is on Rust 1.61 or above. The last push was on 2026-05-11 and the licence is MIT OR Apache-2.0.

## FAQ

### What is the gltf crate used for?

It loads glTF 2.0 files in Rust, the Khronos file format designed for efficient transmission of 3D assets. The package description calls it a glTF 2.0 loader, and the repository ships examples that deserialize the JSON, export it, round trip it and visualise the scene hierarchy.

### How do I enable glTF extension support in the gltf crate?

You list the extension name in the features section of your dependency, for example `features = ["KHR_materials_unlit"]`. The supported extensions include KHR_lights_punctual, KHR_materials_pbrSpecularGlossiness, KHR_materials_unlit, KHR_texture_transform, KHR_materials_variants, KHR_materials_volume, KHR_materials_specular, KHR_materials_transmission, KHR_materials_ior, KHR_materials_emissive_strength and EXT_texture_webp.

### What does the import feature do in the gltf crate?

It is part of the default feature set and it enables the base64, image and urlencoding dependencies, which is what handles embedded and data URI content. The image dependency is configured with default-features = false and only the jpeg and png features, so you are not pulling in every codec image supports.

### What are the default features of the gltf crate?

The default feature set is import, utils and names. Separately, by default the crate ignores all extras and names included with glTF assets, and the names and extras features can be enabled to keep them. There are also allow_empty_animation_target_node and allow_empty_texture flags for assets that would otherwise fail strict validation.

## Sources

- [gltf-rs/gltf on GitHub](https://github.com/gltf-rs/gltf)
- [Issues](https://github.com/gltf-rs/gltf/issues)
- [License: Apache-2.0](https://github.com/gltf-rs/gltf/blob/main/LICENSE)
- [README](https://github.com/gltf-rs/gltf/blob/main/README.md)
- [Releases](https://github.com/gltf-rs/gltf/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gltf-rs-gltf
