A 3D Corvette C8 Showroom in the Browser, Built with Three.js and Vue
Embedding interactive 3D product configurators in web apps is increasingly common, but the gap between a flat model and a convincing showcase is wide. This walkthrough surfaces the concrete steps — tone mapping, multi-light setups, PBR paint materials, and manual GPU resource disposal — that turn a raw .glb into a production-quality browser showroom without leaking memory.
A full 3D product showcase drops a detailed Corvette C8 model straight into a Vue page. The model, sourced from Sketchfab under a CC Attribution license, is loaded via GLTFLoader and placed into a scene with a PerspectiveCamera, directional and area lights mimicking a photo studio, and an environment map for realistic reflections. A grid-only stage replaces a distracting floor ring, and the initial camera position is pulled closer for a tighter product-shot feel.
Car paint is handled through MeshPhysicalMaterial with per-color PBR parameters — metalness, roughness, clearcoat, and iridescence — so switching colors updates the shared body material without reloading the model. The built-in animations are clamped to their closed state on load, and the car auto-rotates inside a wrapper Group while OrbitControls handles user drag with damping.
Resource disposal is explicit: on Vue component unmount, the render loop is cancelled, geometries and materials are traversed and freed, the environment map and renderer are disposed, and the canvas DOM element is removed. This prevents WebGL memory leaks across route changes in a SPA.
Treating the car body as a single shared material rather than per-mesh instances is a deliberate architectural choice that makes real-time configurators cheap: one property update propagates across every painted surface with zero traversal.
The shift from a TorusGeometry ring to a bare GridHelper is a small visual decision with an outsized effect — removing a competing geometric element lets the car's own reflections and contours dominate the frame.
Explicit material-name matching (`body_color`, `painted_black`) is more fragile across different models than keyword heuristics, but far more precise; it bets on a known asset rather than generalizing, which is the right tradeoff for a single-product showcase.
The cleanup routine is unusually thorough for a demo — traversing and disposing every geometry and material, plus removing the DOM canvas — and reflects the reality that SPAs with route-based 3D views will leak WebGL contexts without manual teardown.