import * as THREE from 'three'; // Keeps the gradient's bright spot gravitating toward the projection wall as // the camera orbits: the wall centre (x = -10 in every scene) is projected into // screen space each frame and eased into the CSS gradient position. const WALL_CENTRE = new THREE.Vector3( -10, 0, 0 ); export function bindGlow( camera ) { const projected = new THREE.Vector3(); let x = 12; let y = 50; let writtenX = null; let writtenY = null; return function update() { projected.copy( WALL_CENTRE ).project( camera ); // when the wall goes behind the camera the projection flips sides; // leave the glow where it last was until the wall swings back if ( projected.z < 1 ) { const targetX = THREE.MathUtils.clamp( ( projected.x + 1 ) * 50, -40, 140 ); const targetY = THREE.MathUtils.clamp( ( 1 - projected.y ) * 50, -40, 140 ); x += ( targetX - x ) * 0.08; y += ( targetY - y ) * 0.08; } // writing the property repaints the whole gradient, so only touch the // DOM while the glow is actually moving if ( writtenX !== null && Math.abs( x - writtenX ) < 0.05 && Math.abs( y - writtenY ) < 0.05 ) return; writtenX = x; writtenY = y; document.body.style.setProperty( '--glow-x', `${x.toFixed( 2 )}%` ); document.body.style.setProperty( '--glow-y', `${y.toFixed( 2 )}%` ); }; }