Set up three mesh resolutions in a Unity LOD Group, export the model to glTF, open the `.glb` in another engine or a web viewer, and there's exactly one mesh — full detail, no fallback. Nothing errored, nothing warned. The other levels just aren't in the file. That's not a broken exporter: glTF 2.0's core specification has no concept of LOD levels at all. There's no slot in the format for "here are three versions of this mesh, swap them by distance." Whatever levels you built in your DCC tool or engine either get flattened to one mesh on export, or never make it in to begin with.
Why the glTF file itself has no LOD levels
![]()
The closest thing the format has is `MSFT_lod`, a vendor extension Microsoft published for Windows Mixed Reality years ago. It lets a node or material reference multiple detail levels and a viewer pick one based on distance or a progressive-loading budget. BabylonJS reads it. Windows Mixed Reality's own launchers read it. Unity's import pipeline, Godot's glTF importer, and Unreal's glTF/Datasmith path do not build LOD Groups, import LODs, or Static Mesh LODs from `MSFT_lod` on the way in — so for the three engines this catalog's readers actually ship on, the extension might as well not exist.
Unity's own exporter makes the export side concrete. glTFast's LOD Group support is still an open feature request — tracked as issue #345 on the project's tracker, not a shipped capability. Export a GameObject with a LOD Group today and glTFast writes out whichever mesh is currently active. The rest of the hierarchy doesn't survive the round trip.
What each engine does with your LODs instead
![]()
| Engine / tool | Reads LOD data from the GLB? | What actually happens |
|---|---|---|
| Unity + glTFast | No | Exports one active mesh; LOD Group support is a tracked, unshipped feature request |
| Godot | No | Import dock can *generate* its own LODs after import — a separate mechanism, not read from the file |
| Unreal Engine 5 | No | Static Mesh editor builds LODs post-import regardless of source format |
| BabylonJS / WebXR viewers | Partial | One of the few consumers that actually reads `MSFT_lod` when it's present |
Every row says the same thing: LOD is something each engine reconstructs *after* import, not something the GLB carries for it.
The workaround that holds up across engines
The portable fix is to stop asking one file to carry multiple resolutions and export one GLB per level instead: `tower_LOD0.glb`, `tower_LOD1.glb`, `tower_LOD2.glb`. Every engine loads plain, single-resolution meshes without argument, which means the swap logic is the only thing you have to write yourself — and it's the same handful of lines in any engine with a distance check:
```csharp
// Unity: swap pre-loaded LOD meshes by camera distance
void Update() {
float d = Vector3.Distance(cam.position, transform.position);
int target = d < 15f ? 0 : d < 40f ? 1 : 2;
if (target != activeLOD) {
lodMeshes[activeLOD].SetActive(false);
lodMeshes[target].SetActive(true);
activeLOD = target;
}
}
```
It's more work than a native LOD Group, but it's format-agnostic — the same three files and the same distance bands work whether the runtime is Unity, Godot, or a Three.js scene.
Godot's built-in Generate LODs option
Godot skips the multi-file approach if you're staying inside one project: the Import dock's Advanced Import Settings has a Generate LODs checkbox under Meshes that builds simplified versions after import, no external files needed. Two things to know before flipping it on. First, it's genuinely slow on dense meshes — Godot's tracker has an open report of import times climbing sharply on scenes with large meshes, because the generator casts rays per face to preserve normals. Second, the quality only holds up once triangles shrink to roughly a pixel on screen; inspect a generated LOD up close in the editor and it'll look rough, which is fine, because that's not the distance it's meant to be seen from.
None of this is a reason to hand-build every LOD chain from scratch. A dense hero asset like the Concrete Tower Block — an Eastern Bloc housing-estate piece shipped at full cinematic resolution, 1.85 million triangles — is exactly the case where cutting a high-poly source down to two or three clean fallback levels by hand gets tedious. That's a poly-reduction pass, not a modeling job, and BitSoul's 3D Studio runs that reduction in-browser on your own GPU, free, so the lower levels come from the one GLB before you ever touch an engine's import settings. Licensing is separate from the LOD question: a free account's two monthly downloads cover evaluation; commercial use is included with paid memberships — see pricing for the difference.
Two related reads if LOD chains are the reason you're staring at import settings today: why Unity 6's GPU Resident Drawer ignores imported GLB models covers the batching side of the same performance problem, and cutting demo polygon count before Next Fest walks through getting a whole scene's triangle budget down when there's no time to build per-asset LOD chains at all. If cross-engine format gaps like this one are new territory, which engines support KTX2-compressed GLB textures covers the same "glTF doesn't guarantee it, check per engine" pattern for textures instead of meshes.
---
*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.*