| | @@ -13,9 +13,9 @@ const vertex = /* glsl */ ` |
| | `; |
| | |
| | // Stomp shockwave stage-floor. Concentric gold rings emanate on a beat and |
| - | // react to the cursor, on the warm-black stage. One signature object, subtle. |
| + | // react to the cursor, on the warm-black stage. Kept cheap: 3 bands, no grain. |
| | const fragment = /* glsl */ ` |
| - | precision highp float; |
| + | precision mediump float; |
| | varying vec2 vUv; |
| | uniform float uTime; |
| | uniform vec2 uMouse; |
| | @@ -24,10 +24,6 @@ const fragment = /* glsl */ ` |
| | const vec3 STAGE = vec3(0.059, 0.055, 0.047); |
| | const vec3 GOLD = vec3(0.784, 0.635, 0.298); |
| | |
| - | float hash(vec2 p) { |
| - | return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); |
| - | } |
| - | |
| | void main() { |
| | vec2 p = vUv - 0.5; |
| | p.x *= uAspect; |
| | @@ -39,23 +35,20 @@ const fragment = /* glsl */ ` |
| | |
| | float rings = 0.0; |
| | float t = uTime * 0.42; |
| - | for (int i = 0; i < 4; i++) { |
| - | float phase = fract(t + float(i) * 0.25); |
| + | for (int i = 0; i < 3; i++) { |
| + | float phase = fract(t + float(i) * 0.333); |
| | float radius = phase * 1.05; |
| - | float band = smoothstep(0.018, 0.0, abs(d - radius)); |
| - | rings += band * (1.0 - phase); |
| + | rings += smoothstep(0.02, 0.0, abs(d - radius)) * (1.0 - phase); |
| | } |
| | rings *= beat; |
| | |
| | float md = length(p - m); |
| | float cursor = smoothstep(0.32, 0.0, md); |
| - | float cursorRing = smoothstep(0.01, 0.0, abs(md - 0.14)) * 0.6; |
| + | float cursorRing = smoothstep(0.012, 0.0, abs(md - 0.14)) * 0.6; |
| | |
| | float energy = rings * 0.55 + cursor * 0.28 + cursorRing; |
| | vec3 col = STAGE + GOLD * energy * 0.6; |
| - | |
| | col *= smoothstep(1.25, 0.15, d); |
| - | col += (hash(vUv * 900.0 + uTime) - 0.5) * 0.012; |
| | |
| | gl_FragColor = vec4(col, 1.0); |
| | } |
| | @@ -79,14 +72,14 @@ function Floor() { |
| | const onMove = (e: MouseEvent) => { |
| | target.current.set(e.clientX / window.innerWidth, 1 - e.clientY / window.innerHeight); |
| | }; |
| - | window.addEventListener("mousemove", onMove); |
| + | window.addEventListener("mousemove", onMove, { passive: true }); |
| | return () => window.removeEventListener("mousemove", onMove); |
| | }, []); |
| | |
| | useFrame((_, dt) => { |
| | const u = mat.current?.uniforms; |
| | if (!u) return; |
| - | u.uTime.value += dt; |
| + | u.uTime.value += Math.min(dt, 0.05); |
| | u.uAspect.value = size.width / size.height; |
| | const m = u.uMouse.value as THREE.Vector2; |
| | m.x += (target.current.x - m.x) * 0.06; |
| | @@ -106,9 +99,14 @@ function Floor() { |
| | ); |
| | } |
| | |
| - | export default function HeroScene() { |
| + | export default function HeroScene({ active = true }: { active?: boolean }) { |
| | return ( |
| - | <Canvas dpr={[1, 2]} gl={{ antialias: true }} style={{ width: "100%", height: "100%" }}> |
| + | <Canvas |
| + | dpr={0.75} |
| + | frameloop={active ? "always" : "never"} |
| + | gl={{ antialias: false, powerPreference: "low-power" }} |
| + | style={{ width: "100%", height: "100%" }} |
| + | > |
| | <Floor /> |
| | </Canvas> |
| | ); |