← back to Scarlet Riverboat Masquerade
Add 3D Three.js orb floating over the riverboat — beat-reactive wireframe icosahedron that pulses to the LIVE Dead stream (via the react analyser), warm ember palette; gentle idle when music is off
4adfed7c17dca30deff2e894433d054fe8d60366 · 2026-09-02 06:44:38 -0700 · Steve Abrams
Files touched
Diff
commit 4adfed7c17dca30deff2e894433d054fe8d60366
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 2 06:44:38 2026 -0700
Add 3D Three.js orb floating over the riverboat — beat-reactive wireframe icosahedron that pulses to the LIVE Dead stream (via the react analyser), warm ember palette; gentle idle when music is off
---
index.html | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/index.html b/index.html
index 6480a9a..0e96dd4 100644
--- a/index.html
+++ b/index.html
@@ -23,6 +23,7 @@
html,body{margin:0;height:100%;background:#0a0406;color:var(--ink);font-family:var(--sans);overflow:hidden}
#stage{position:fixed;inset:0;display:block}
canvas{position:absolute;inset:0;width:100%;height:100%}
+ #orb{z-index:4;pointer-events:none}
/* construction-paper grain — the cutout/South-Park texture over the whole scene */
.grain{position:fixed;inset:0;pointer-events:none;z-index:5;opacity:.10;mix-blend-mode:overlay;
background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 220 220' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
@@ -224,6 +225,7 @@
<canvas id="sky" aria-hidden="true"></canvas>
<canvas id="scene" aria-hidden="true"></canvas>
+ <canvas id="orb" aria-hidden="true"></canvas>
<div class="grain" aria-hidden="true"></div>
<div class="titleplate">
@@ -1672,5 +1674,42 @@ if(_p.endsWith('/room') || /dead\.agentabrams/i.test(location.hostname)){
}
})();
</script>
+
+<!-- 3D orb (Three.js) floating over the boat, pulsing to the LIVE Dead stream. Classic build so it runs from file://; skips if offline. -->
+<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
+<script>
+(function(){
+ if(!window.THREE) return;
+ const canvas=document.getElementById('orb'); if(!canvas) return;
+ let W=innerWidth,H=innerHeight;
+ const renderer=new THREE.WebGLRenderer({canvas,alpha:true,antialias:true});
+ renderer.setPixelRatio(Math.min(2,devicePixelRatio||1)); renderer.setSize(W,H,false);
+ const scene=new THREE.Scene();
+ const camera=new THREE.PerspectiveCamera(50,W/H,0.1,100); camera.position.z=5;
+ const group=new THREE.Group(); group.position.y=1.45; scene.add(group); // floats up in the sky over the boat
+ const wire=new THREE.Mesh(new THREE.IcosahedronGeometry(0.95,2), new THREE.MeshBasicMaterial({wireframe:true,color:0xf2b64a,transparent:true,opacity:0.8}));
+ const core=new THREE.Mesh(new THREE.IcosahedronGeometry(0.76,3), new THREE.MeshStandardMaterial({color:0x2a0810,emissive:0xc9432b,emissiveIntensity:0.7,roughness:0.35,metalness:0.6,transparent:true,opacity:0.85}));
+ group.add(core,wire);
+ const l1=new THREE.PointLight(0xff8a4a,1.3,60); l1.position.set(4,3,5); scene.add(l1);
+ const l2=new THREE.PointLight(0xf2b64a,1.0,60); l2.position.set(-4,-1,4); scene.add(l2);
+ scene.add(new THREE.AmbientLight(0x402028,0.9));
+ const col=new THREE.Color();
+ addEventListener('resize',()=>{ W=innerWidth;H=innerHeight; camera.aspect=W/H; camera.updateProjectionMatrix(); renderer.setSize(W,H,false); });
+ function loop(){ requestAnimationFrame(loop);
+ const s=window.SRM||{}, t=performance.now()/1000;
+ const pulse=s.pulse||0, level=(s.react?(s.level||0):0);
+ const idle=0.5+0.5*Math.sin(t*1.2); // gentle breathing when no music
+ const energy=s.react ? (level*0.6+pulse*0.7) : idle*0.12;
+ group.rotation.y+=0.008+energy*0.02; group.rotation.x=Math.sin(t*0.3)*0.18;
+ group.scale.setScalar(1+energy*0.35);
+ core.material.emissiveIntensity=0.5+energy*1.6;
+ const hue=(28 + Math.sin(t*0.2)*16 + level*40)%360; // warm ember range, shifts with the music
+ wire.material.color.setHSL(((hue+18)%360)/360,0.85,0.6);
+ col.setHSL(hue/360,0.85,0.5); core.material.emissive.copy(col);
+ renderer.render(scene,camera);
+ }
+ loop();
+})();
+</script>
</body>
</html>
← 88dc7e0 Riverboat room: searchable full Grateful Dead archive — type
·
back to Scarlet Riverboat Masquerade
·
Back-link: room now links '← The Main Stage' (stage.agentabr ced8032 →