← All Baltor Engineering Posts · Post 06 of 08 · 2026-10-18 · 3D Rendering & Shaders · 8 min read · Raw Markdown (.md) · Open Live Studio ↗

Procedural 3D Product Commercials in the Browser: Anisotropic Metals, Rim Lights, and Camera Beats

Why single-directional-light Three.js scenes look like plastic, and how Baltor composes 4-pass studio lighting rigs, brushed anisotropic clearcoats, and Catmull-Rom camera beat splines.


4-PASS STUDIO LIGHTING RIG + PBR CLEARCOAT + CATMULL-ROM CAMERA BEATS 1. 4-PASS STUDIO LIGHT RIG Key: Warm 5200K Area/Spot (45 deg) Fill: Cool 7500K Soft Bounce (-60 deg) Rim: Grazing Backlight (165 deg) Env: Procedural PMREM Studio HDRI 2. PHYSICAL SURFACE MATERIAL MeshPhysicalMaterial (r186) anisotropy: 0.78 | clearcoat: 0.92 ior: 1.52 | sheenRoughness: 0.25 ACES Filmic Tone Mapping (exp 1.15) 3. CAMERA BEAT CHOREOGRAPHY Beat 1 (0-3s): Grazing macro sweep Beat 2 (3-6s): Hero reveal orbit Beat 3 (6-9s): Packshot lock + DoF Verified Luminance Contrast > 4.8:1

When an unassisted language model generates a 3D product showcase in Three.js, it almost always drops a MeshStandardMaterial into a black void with one AmbientLight(0xffffff, 0.8) and one DirectionalLight. Without an environment map (PMREMGenerator) or a grazing rim light, metallic surfaces reflect pure black (0x000000) and dielectric reliefs lose all depth contrast. On compare.baltor.ai and assets.baltor.ai, Baltor binds product scenes to a 4-pass studio lighting rig, procedural HDRI reflections, and chordal Catmull-Rom camera beat splines.

The four-pass studio lighting contract

A metallic or glazed ceramic surface derives its visual read from the luminance gradient across its curvature. Baltor's studio lighting component (studio.lighting.four_pass_pbr.v1) enforces four distinct light contributions and verifies their histogram spread:

// Procedural Studio Softbox Environment via PMREMGenerator
export function buildProceduralStudioEnv(renderer, THREE) {
  const pmrem = new THREE.PMREMGenerator(renderer);
  const envScene = new THREE.Scene();
  envScene.background = new THREE.Color(0x0b0e14);

  const stripGeo = new THREE.PlaneGeometry(10, 2.5);
  const keyMat = new THREE.MeshBasicMaterial({ color: new THREE.Color(6.0, 5.6, 5.0), side: THREE.DoubleSide });
  const keyStrip = new THREE.Mesh(stripGeo, keyMat);
  keyStrip.position.set(6, 7, 5);
  keyStrip.lookAt(0, 0, 0);
  envScene.add(keyStrip);

  const rimMat = new THREE.MeshBasicMaterial({ color: new THREE.Color(3.5, 4.8, 6.5), side: THREE.DoubleSide });
  const rimStrip = new THREE.Mesh(stripGeo, rimMat);
  rimStrip.position.set(-7, 4, -6);
  rimStrip.lookAt(0, 0, 0);
  envScene.add(rimStrip);

  const renderTarget = pmrem.fromScene(envScene, 0.04);
  pmrem.dispose();
  return renderTarget.texture;
}

Camera beat splines and verifier gates

Commercial product spots require intentional pacing rather than a constant mesh.rotation.y += 0.01 turntable. Baltor structures commercials as a sequence of timed camera beats (Macro Sweep -> Hero Reveal -> Packshot Lock) interpolated via centripetal CatmullRomCurve3 with damped look-at targets, verified by an automated luminance-contrast gate that rejects any frame with clipped highlights or silhouette contrast below 4.8:1.


Navigation Post Title Direct Links
Previous Post 60 FPS Motion Graphics: Why Spring Physics and DFT Epicycles Beat CSS Keyframes
Next Post Simulating Backpressure, Consistent Hashing, and Shard Failover Before Writing Production Code
Blog Index & Feeds Return to Baltor Engineering Blog Index (8 Posts)