Textures are the file
Open a 40 MB GLB and look at what is actually in it. Almost always, the geometry is 1–3 MB and the rest is textures. One 4096×4096 PNG normal map is around 20 MB on its own; a full PBR set at 4K is easily 60 MB before you have drawn a single triangle.
This free online 3D texture optimizer works only on that part of the file — and gives you the per-slot control that generic compressors do not.
Why per-slot settings matter
Treating every texture the same is the mistake that makes optimised models look wrong.
Base colour and emissive maps are perceptual. Your eye is forgiving of small colour errors, so lossy WebP at quality 80 typically removes 90% of the bytes with no visible difference.
Normal maps are not images. Each pixel encodes a direction vector in its RGB channels. JPEG-style chroma subsampling averages colour channels across neighbouring pixels — which, on a normal map, means averaging surface directions. The result is muddy, flattened lighting that people describe as "the model lost its detail" without knowing why. Keep normal maps lossless and downsize them less aggressively than colour.
Metallic-roughness and occlusion maps pack single-channel data into RGB. Roughness varies slowly across a surface, so these downsize extremely well — often to half the resolution of the colour map with no perceptible change.
The defaults here already reflect this: lossy WebP for colour, lossless WebP for normals, and smaller WebP for ORM maps.
Formats
- WebP — supported everywhere that matters, dramatic savings, the sensible default.
- AVIF — smaller again, and encoded here by a bundled libavif build rather than by the browser, so it works the same everywhere. Slower to encode than WebP, and worth it on large colour maps.
- JPEG — no alpha channel; avoid for anything with transparency.
- PNG — lossless, but far larger than lossless WebP. Use it only when a pipeline demands PNG specifically.
KTX2 / Basis Universal is deliberately not offered. It is the best format for GPU memory, but encoding it needs the Basis encoder, which is a large separate toolchain — this tool would have to lie about what it produces.
If a re-encode would come out larger than the original — which happens when you push an already-lossy JPEG into a lossless format — the tool keeps the original and says so.
Check your work in the grid
After processing, every texture appears in a grid with its slot, its final dimensions and its before/after size. If a normal map looks washed out in the thumbnail, it will look washed out on the model. Change that slot's settings and run it again.
Power-of-two dimensions
Some older engines and mipmapping paths require textures whose dimensions are powers of two. The toggle rounds every texture to the nearest one. Leave it off for modern WebGL2 and WebGPU targets, which do not care.
Privacy
Decoding and re-encoding both happen through your browser's own canvas APIs. No texture is ever uploaded.
Tiny Online Tools







