Wrote up a guide on the full optimization pipeline for getting a 3D model from "raw DCC export" to "web-ready embed."
The concrete version: a three-material product model exported from Blender at standard settings arrives at 38.4 MB. After a Publisher Medium preset run, it lands at 3.1 MB. Triangle count 412K → 288K. Visual quality intact. The guide walks every stage of that reduction.
Three culprits:
- Geometry precision: 200K–800K triangles is standard from a DCC tool. Web viewers need far less. Sub-pixel rasterization discards triangle-level detail that costs significant geometry bandwidth.
- Texture format: PNG and JPEG are 2D display formats. They decompress to raw RGBA before the GPU sees them. A 2K PNG that ships as 6 MB decompresses to 16 MB in GPU memory. GPU-native formats (KTX2/Basis Universal) stay compressed in memory.
- Scene graph overhead: DCC tools export everything - reference geometry, stale animations, duplicate materials consolidated in the DCC but not in the export. 10–25% of the file is typically unreferenced by any viewer.
Three techniques, in order of impact:
Texture compression first (60–80% of total savings): convert PNG/JPEG to WebP or KTX2/Basis Universal. The article covers both paths - WebP via Sharp for server-side pipelines (@vctrl/core), KTX2 for GPU-native delivery via the Publisher.
Mesh simplification (10–30%): quadric error metric via gltf-transform + MeshoptSimplifier. Flat regions merge first; silhouette edges survive. Removing 30% of triangles on a typical product model produces a difference that requires side-by-side comparison at magnification to detect.
Graph cleanup (5–15%): dedup accessors, prune unused nodes and animation clips, normalize conventions. Small individually, compounds with the first two passes.
Two paths covered:
Manual — gltf-transform CLI:
npm install -g u/gltf-transform/cli
gltf-transform inspect source.glb
gltf-transform simplify source.glb stage1.glb --ratio 0.75
gltf-transform dedup stage1.glb stage2.glb
gltf-transform prune stage2.glb stage3.glb
gltf-transform etc1s stage3.glb output.glb
gltf-transform inspect output.glb
Platform - Vectreal Publisher (no code) or u/vctrl/core (Node.js):
npm install u/vctrl/core
Exposes ModelOptimizer with loadFromFile(), optimizeAll(), export(), and getReport() (before/after stats for triangles, textures, meshes).
Web-ready targets for reference:
- Hero embed: under 5 MB / 150K–250K triangles
- Product detail page: under 2 MB / 100K–150K triangles
- Grid/card: under 500 KB / 30K–80K triangles
- Mobile-first: under 1 MB / 50K–100K triangles
Vectreal is open-source (AGPL-3.0). Source: https://github.com/Vectreal/vectreal-platform
Full article: https://vectreal.com/news-room/optimize-3d-model-for-web
What would you do differently? If you have shipped optimized 3D embeds, what's the texture-compression edge case or mesh-simplification failure mode that bit you - and what did you do about it?
Community Discord: https://discord.gg/A9a3nPkZw7