Cinematic experience · real-time 3D car
AUREX MOTORS

Problem
Premium product sites almost always end up as static catalogs: they carry none of the brand's feeling and give no reason to explore.
Solution
A navigable luxury-car commercial: a 14-scene film directed by scroll (the camera moves, the car turns, lights ignite), design close-ups, counting numbers, a horizontal showroom gallery and a 3D configurator. Paint, wheels, cabin light and underglow change the car in real time, with a reactive price.
How it was built
The architecture splits the DOM world from the 3D world with a shared mutable state (world.ts). One ScrollTrigger per section writes (scene, progress) and the camera rig reads it every frame inside the canvas, so scroll never re-renders React. The film script lives in a single file (scenes.ts), with per-scene keyframes for camera position, target and fov, car rotation and every light's intensity, interpolated with exponential damping. The damping is what turns hard cuts into dolly moves. On top, mouse parallax offsets the camera and key light, so the paint reflections follow the cursor.
The car is the Ferrari 458 from the official three.js examples (Draco-compressed GLB, decoder served locally, zero CDN), rebranded by material name at runtime: paint becomes a configurable clearcoat MeshPhysicalMaterial, yellow accents become AUREX red, head and taillights become script-driven emissives (they ignite on cue), chrome goes satin dark and the interior becomes black leather with red piping. The configurator writes straight into the shared state and the car lerps its materials per frame, so color changes feel liquid, with zero 3D-tree re-renders. The studio is fully procedural: Lightformers instead of HDRIs, a MeshReflectorMaterial floor and additive cones as volumetric shafts.
Performance and robustness: PerformanceMonitor steps the DPR down on weak GPUs, the main canvas pauses (frameloop never) while the gallery, which owns its own canvas, covers the screen, Lenis is disabled on touch and prefers-reduced-motion swaps all damping for instant poses. Debugging produced documented gotchas: GSAP parses inline translateY(115%) as pixels (animate y, not yPercent), un-layered CSS beats any utility in Tailwind v4, and headless Chromium renders at ~1fps. A damped camera never converges in screenshots, which became a ?snap visual-testing mode.
Single-file camera script
14 scenes of camera, rotation and light keyframes, scroll-directed with exponential damping.
Re-render-free configurator
The panel writes to shared state; the car lerps materials per frame.
Zero external downloads
Local model, local Draco decoder and Lightformer environment, with no HDRIs and no CDNs.
More screens
Stack
- Next.js
- TypeScript
- React Three Fiber
- Three.js
- GSAP
- Lenis
- Tailwind

