[object Object]

← back to Quadrille Showroom

REAL PICTURE-LIGHT SHADOWS: enable castShadow on the gallery picture-light spot so each board casts a soft, physically-correct shadow onto the wall behind it (and faintly onto neighbours) — genuine depth the fake drop-sprite can't give, esp. on the focused hero board. Tight shadow camera (near 0.4/far 3.6) + 1024 map + wide PCF radius keeps cost low. MEASURED: 2-min soak min 59 / avg 68 FPS (holds the >=55 real-shadow gate, with margin), walkthrough 72 FPS, errorCount 0, specs intact (27x27, China Seas). 2nd shadow-casting light, lights still 6.

ac87a362c4e2408774a30701c1dbed74c2c53267 · 2026-06-27 12:47:07 -0700 · Steve

Files touched

Diff

commit ac87a362c4e2408774a30701c1dbed74c2c53267
Author: Steve <steve@designerwallcoverings.com>
Date:   Sat Jun 27 12:47:07 2026 -0700

    REAL PICTURE-LIGHT SHADOWS: enable castShadow on the gallery picture-light spot so each board casts a soft, physically-correct shadow onto the wall behind it (and faintly onto neighbours) — genuine depth the fake drop-sprite can't give, esp. on the focused hero board. Tight shadow camera (near 0.4/far 3.6) + 1024 map + wide PCF radius keeps cost low. MEASURED: 2-min soak min 59 / avg 68 FPS (holds the >=55 real-shadow gate, with margin), walkthrough 72 FPS, errorCount 0, specs intact (27x27, China Seas). 2nd shadow-casting light, lights still 6.
---
 public/js/showroom.js | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/public/js/showroom.js b/public/js/showroom.js
index d0cce7e..9090399 100644
--- a/public/js/showroom.js
+++ b/public/js/showroom.js
@@ -630,12 +630,21 @@ function buildLighting() {
   rim.target.position.set(0, 1.2, 0); scene.add(rim); scene.add(rim.target);
 
   // PICTURE LIGHT — a soft warm wash grazing the board wall from above, like a
-  // gallery picture light. No shadow (FPS-safe); wide penumbra so no hard hotspot.
+  // gallery picture light. Wide penumbra so no hard hotspot.
   const pic = new THREE.SpotLight(0xfff0d8, 0.55, 8, Math.PI * 0.42, 0.85, 1.2);
   pic.position.set(0, CONFIG.room.height - 0.15, -CONFIG.room.depth / 2 + 1.0);
   pic.target.position.set(0, 1.2, -CONFIG.room.depth / 2);
-  pic.castShadow = false;
+  // PER-BOARD REAL SHADOW — the picture-light casts a soft, physically-correct shadow of
+  // each board onto the wall behind it (and a hair onto its neighbours). Only kept if the
+  // 2-min soak stays ≥55 FPS (gate); a tight shadow camera + 1024 map keeps the cost low.
+  pic.castShadow = true;
+  pic.shadow.mapSize.set(1024, 1024);
+  pic.shadow.camera.near = 0.4; pic.shadow.camera.far = 3.6;  // wall is ~1m from the light cone tip
+  pic.shadow.bias = -0.0006;
+  if ('normalBias' in pic.shadow) pic.shadow.normalBias = 0.02;
+  if ('radius' in pic.shadow) pic.shadow.radius = 4;          // wide PCF penumbra = soft gallery shadow
   scene.add(pic); scene.add(pic.target);
+  window._picLight = pic;
 
   // Light panel meshes (visual only, no light cost)
   const H = CONFIG.room.height;

← ce3b7f3 BOARD WALL DROP-SHADOW: each board casts a faint soft shadow  ·  back to Quadrille Showroom  ·  REVIEW.md: FINAL pass-5 section — honest B- grade (up from D fb6800c →