What GLB to STL Conversion Actually Throws Away, Measured Field by Field
Published 2026-09-14
Converting GLB to STL is usually described as a format change, as though the same thing arrives in a different wrapper. It is closer to a demolition. STL can hold triangles and nothing else, so everything a GLB carries beyond raw geometry has nowhere to land.
We built an asset that carries one of each of those things and measured what came out the other side.
The test asset
One scene, built so that each feature is present exactly once and its absence afterwards is unambiguous:
- TexturedBox, a 20 mm cube with real UV coordinates and a PBR material carrying a checker texture, metallic 0.9, roughness 0.2
- ColouredBall, a sphere with per-vertex colours, moved 40 mm along X so that whether the part transform survives can be read off the bounding box
What came out
| Source scene | After a GLB round trip | After export to STL | |
|---|---|---|---|
| Separate parts | 2 | 2 | 1 |
| Part names | TexturedBox, ColouredBall | TexturedBox, ColouredBall | none |
| Faces | 332 | 332 | 332 |
| Vertices | 170 | 170 | 996 |
| UV coordinates | 8 | 8 | 0 |
| Texture images | 1 | 1 | 0 |
| Materials | BoxMaterial | BoxMaterial | none |
| Vertex colours | yes | yes | no |
| Bounding box | -10,-10,-10 to 50,10,10 | same | same |
| File size | 8,812 bytes | 16,684 bytes |
The GLB column is there as a control. A GLB round trip is lossless for everything we measured, which means every zero in the last column is attributable to STL rather than to the export step or to the asset.
Reading the losses
The parts merge into one object. This is the loss people notice last and regret most. A scene assembled from named components arrives as a single undifferentiated shell. Nothing in the STL records where one part ended and the next began, so selecting, hiding or assigning a different setting to just one of them is no longer possible without cutting the mesh back apart by hand.
Position survives, so the loss is not obvious at a glance. The bounding box is identical, and the sphere is still 40 mm along X where it was put. A converted asset looks right in a viewer, which is exactly why the missing pieces get discovered later, usually in the slicer.
The vertex count triples for a reason that is not waste in the usual sense. 996 is exactly 332 × 3. STL has no way to state that two triangles share a corner, so each triangle stores its own three. That single gap is also why two programs can report completely different topology for the same STL, which is a longer story in what “same vertex” means in an STL.
Normals change meaning. A GLB stores a normal per vertex, so a smoothly shaded curved surface is authored into the file. STL stores one normal per facet. The curvature is still implied by the geometry, but the shading instruction is gone, and a reader has to infer smoothness from the triangles rather than being told.
Why STL is bigger while carrying less
This is the part that surprises people, so it is worth being concrete. STL spends its bytes on repetition. Every triangle writes out three full coordinate triples plus a normal, whether or not its neighbours already wrote the same points. GLB stores each vertex once and then refers to it by index, which is both smaller and the reason it can afford to carry UVs, a material and an embedded texture and still come in at half the size.
The comparison gets more lopsided as models get denser, because the ratio of shared corners to triangles rises with resolution. On a low-poly test asset like this one the penalty is 1.89 times. On a real scan it is worse.
What this means in practice
Convert last, and keep the GLB. The conversion is one way. Nothing in the STL records the material, the UV layout or the part names, so none of it can be recovered from the STL later. Treat the STL as an output of the GLB, not as a copy of it, and re-export whenever you need a fresh one.
If colour has to survive, STL is the wrong target. For a colour print, 3MF carries materials and part structure, and it carries the unit of length as well, which STL does not record either. What else changes on that route is in 3MF vs STL. For a textured model going to another application rather than a printer, OBJ with an MTL file at least keeps the material reference, as covered in OBJ vs STL.
If you are only going to a single colour printer, most of this loss costs you nothing. A slicer wants closed geometry at the right size and ignores UVs and materials entirely. The losses that still matter in that case are the part names, if you were relying on them to configure the print, and the fact that you now have a file that is bigger and harder to analyse than the one you started with.
If you want to see what is in a GLB before deciding whether you can afford to lose it, our GLB viewer reports parts, UVs and textures on upload, and what is a GLB file walks through the container itself.
Method
Test scene built and exported with trimesh 5.1.0 and numpy 2.5.2 on 8 September 2026, using Pillow to generate the checker texture. Each asset was written to disk, read back, and inspected for the same set of fields, so the GLB column is a genuine round trip rather than an in-memory copy. The STL was read with processing disabled so that no vertex merging was applied on load, which is why the 996 figure is the count as stored rather than after reconstruction. Sizes are the bytes on disk, with the texture embedded in the GLB rather than referenced externally.
Not measured here: animation, skinning, cameras and lights, none of which the test asset contains, and all of which STL also has no way to store. Also not measured: what any named converter other than this library produces.
The raw output is published as JSON, produced
by scripts/measure-glb-to-stl-loss.py.
Frequently asked questions
What is lost when converting GLB to STL?
Everything except the triangles and where they sit. We converted a test scene with two named parts, UV coordinates, a texture image, a PBR material and per-vertex colours. The STL kept all 332 faces and the exact bounding box, and kept nothing else: no UVs, no texture, no material, no vertex colours, and the two named parts merged into one unnamed object. Position survives, appearance does not.
Does STL support colour or texture?
Not in any form a converter can use. Plain STL stores a facet normal and three corner coordinates per triangle, with no place for a UV coordinate, a texture image or a material. Some tools write colour into unused header or attribute bytes, but that is a vendor extension rather than part of the format, and nothing guarantees the next program will read it. If colour has to survive, the format has to change: 3MF or OBJ with an MTL file, not STL.
Is an STL file smaller than a GLB?
Usually not, and in our test it was much larger. The same asset came to 8,812 bytes as GLB, including the embedded texture image, and 16,684 bytes as binary STL with no texture, no material and no UVs. That is 1.89 times the size for a fraction of the content, because STL repeats every vertex for every triangle that touches it instead of storing each one once.
Why does my model have more vertices after converting to STL?
Because STL has no way to say that two triangles share a corner, so every triangle carries its own three. Our 170 vertex scene came back as 996 vertices, which is exactly 332 faces times three. The geometry is unchanged; only the way it is stored changed. Any program reading it has to reconstruct the shared corners itself, and different programs do that differently.
Should I keep the GLB after converting to STL?
Yes, and treat the STL as an output rather than a copy. The conversion is one way: nothing in the STL records what the material was, how the UVs were laid out or which part was which, so those cannot be recovered from it. Keep the GLB as the master and re-export whenever you need a new STL.