@nous-research/ui 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/use-gpu-tier.d.ts +15 -1
- package/dist/hooks/use-gpu-tier.d.ts.map +1 -1
- package/dist/hooks/use-gpu-tier.js +48 -18
- package/dist/hooks/use-gpu-tier.js.map +1 -1
- package/dist/hooks/use-render-loop.d.ts +42 -0
- package/dist/hooks/use-render-loop.d.ts.map +1 -0
- package/dist/hooks/use-render-loop.js +62 -0
- package/dist/hooks/use-render-loop.js.map +1 -0
- package/dist/ui/components/image-distortion.d.ts.map +1 -1
- package/dist/ui/components/image-distortion.js +27 -2
- package/dist/ui/components/image-distortion.js.map +1 -1
- package/dist/ui/components/overlays/glitch.d.ts.map +1 -1
- package/dist/ui/components/overlays/glitch.js +42 -30
- package/dist/ui/components/overlays/glitch.js.map +1 -1
- package/dist/ui/components/overlays/greys.d.ts.map +1 -1
- package/dist/ui/components/overlays/greys.js +56 -39
- package/dist/ui/components/overlays/greys.js.map +1 -1
- package/dist/ui/components/overlays/noise.d.ts.map +1 -1
- package/dist/ui/components/overlays/noise.js +52 -31
- package/dist/ui/components/overlays/noise.js.map +1 -1
- package/dist/ui/components/scene-canvas.d.ts +9 -1
- package/dist/ui/components/scene-canvas.d.ts.map +1 -1
- package/dist/ui/components/scene-canvas.js +13 -2
- package/dist/ui/components/scene-canvas.js.map +1 -1
- package/dist/ui/components/tv.d.ts.map +1 -1
- package/dist/ui/components/tv.js +31 -4
- package/dist/ui/components/tv.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glitch.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/glitch.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef } from 'react'\nimport * as THREE from 'three'\n\nimport { useGpuTier } from '../../../hooks/use-gpu-tier'\nimport { useSmoothControls } from '../../../hooks/use-smooth-controls'\nimport { cn } from '../../../utils'\n\nimport { BLEND_MODES } from './blend-modes'\n\nconst vert = /*glsl*/ `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n`\n\nconst frag = /*glsl*/ `\n uniform float uTime, uAlpha, uIntensity, uChroma, uSpeed, uSparsity;\n uniform vec3 uColor;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }\n\n vec2 hash2(vec2 p) {\n vec3 q = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));\n q += dot(q, q.yzx + 33.33);\n return fract((q.xx + q.yz) * q.zy);\n }\n\n float dither(vec2 p, float a) {\n return step(mod(floor(p.x) + floor(p.y) * 2.0, 4.0) / 4.0, a);\n }\n\n void main() {\n vec3 col = vec3(0.0);\n float t = uTime * uSpeed;\n float tSlow = floor(t / 3.0);\n float dit = dither(gl_FragCoord.xy * 0.5, 0.7);\n\n for (float i = 0.0; i < 6.0; i++) {\n float seed = i * 137.3;\n float epoch = floor((t + hash(vec2(seed, 77.7)) * 200.0) / (4.0 + hash(vec2(seed, 0.0)) * 6.0));\n float life = fract((t + hash(vec2(seed, 77.7)) * 200.0) / (4.0 + hash(vec2(seed, 0.0)) * 6.0));\n\n if (hash(vec2(epoch, seed)) > 1.0 - uSparsity * 0.7) continue;\n\n vec2 center = vec2(hash(vec2(epoch, seed + 13.1)), hash(vec2(epoch, seed + 27.3)));\n vec2 size = vec2(0.015 + hash(vec2(epoch, seed + 41.5)) * 0.08, 0.008 + hash(vec2(epoch, seed + 53.7)) * 0.04);\n vec2 d = abs(vUv - center);\n\n if (d.x < size.x && d.y < size.y) {\n float fade = smoothstep(0.0, 0.05, life) * smoothstep(1.0, 0.95, life);\n vec2 gUV = vUv + (hash2(vec2(epoch, seed + 200.0)) - 0.5) * 0.08 * uIntensity;\n float shift = uChroma * 0.015 * (sin(t * 2.0 + hash(vec2(epoch, seed)) * 6.28) * 0.3 + 0.7);\n\n col += uColor * vec3(\n hash(gUV * 50.0 + vec2(shift, 0.0) + epoch),\n hash(gUV * 50.0 + epoch),\n hash(gUV * 50.0 - vec2(shift, 0.0) + epoch)\n ) * dither(gl_FragCoord.xy * 0.5, fade * 0.8 + 0.2) * uIntensity * 0.7;\n }\n }\n\n for (float i = 0.0; i < 12.0; i++) {\n float seed = i * 211.7 + 1000.0;\n float epoch = floor((t + hash(vec2(seed, 77.7)) * 150.0) / (3.0 + hash(vec2(seed, 0.0)) * 5.0));\n float life = fract((t + hash(vec2(seed, 77.7)) * 150.0) / (3.0 + hash(vec2(seed, 0.0)) * 5.0));\n\n if (hash(vec2(epoch, seed)) > 1.0 - uSparsity * 0.5) continue;\n\n vec2 pos = vec2(hash(vec2(epoch, seed + 13.1)), hash(vec2(epoch, seed + 27.3)));\n float px = 0.003 + hash(vec2(epoch, seed + 41.5)) * 0.008;\n\n if (abs(vUv.x - pos.x) < px && abs(vUv.y - pos.y) < px) {\n float fade = smoothstep(0.0, 0.1, life) * smoothstep(1.0, 0.9, life);\n vec3 c = uColor;\n float cs = hash(vec2(epoch, seed + 700.0));\n\n if (cs < 0.2) c.r *= 1.8 * uChroma;\n else if (cs < 0.4) c.b *= 1.8 * uChroma;\n\n col += c * dither(gl_FragCoord.xy * 0.5, fade * 0.9) * uIntensity;\n }\n }\n\n float tearSize = 25.0 + uSparsity * 10.0;\n float tearThresh = 0.85 + uSparsity * 0.1;\n\n float hY = floor(vUv.y * tearSize);\n if (step(tearThresh, hash(vec2(hY, tSlow))) > 0.0) {\n float shift = (hash(vec2(hY, tSlow + 50.0)) - 0.5) * 0.25 * uIntensity;\n col += uColor * step(0.4, hash(vec2(vUv.x + shift, hY + tSlow))) * dit * uIntensity * 0.5;\n }\n\n float vX = floor(vUv.x * tearSize);\n if (step(tearThresh, hash(vec2(vX, tSlow + 100.0))) > 0.0) {\n float shift = (hash(vec2(vX, tSlow + 150.0)) - 0.5) * 0.25 * uIntensity;\n col += uColor * step(0.4, hash(vec2(vX + tSlow, vUv.y + shift))) * dit * uIntensity * 0.5;\n }\n\n gl_FragColor = vec4(col * uAlpha, max(col.r, max(col.g, col.b)) * uAlpha);\n }\n`\n\nexport function Glitch({ className, style }: GlitchProps) {\n const gpuTier = useGpuTier()\n\n const c = useSmoothControls(\n 'Effects/Glitch',\n {\n alpha: { max: 2, min: 0, step: 0.01, value: 0.25 },\n blend: { options: BLEND_MODES, value: 'difference' },\n chroma: { max: 3, min: 0, step: 0.01, value: 1.17 },\n color: { value: '#ffe6cb' },\n enabled: { value: true },\n intensity: { max: 1, min: 0, step: 0.01, value: 0.59 },\n sparsity: { max: 1, min: 0, step: 0.01, value: 0.21 },\n speed: { max: 10, min: 0.1, step: 0.1, value: 1 }\n },\n { collapsed: true }\n )\n\n const ref = useRef<HTMLCanvasElement>(null)\n const cRef = useRef(c)\n cRef.current = c\n\n const enabled = c.enabled && gpuTier > 0\n\n useEffect(() => {\n if (!ref.current || !enabled) {\n return\n }\n\n const renderer = new THREE.WebGLRenderer({\n alpha: true,\n canvas: ref.current\n })\n\n const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)\n const geo = new THREE.PlaneGeometry(2, 2)\n const scene = new THREE.Scene()\n\n const mat = new THREE.ShaderMaterial({\n fragmentShader: frag,\n transparent: true,\n uniforms: {\n uAlpha: { value: c.alpha },\n uChroma: { value: c.chroma },\n uColor: { value: new THREE.Color(c.color) },\n uIntensity: { value: c.intensity },\n uSparsity: { value: c.sparsity },\n uSpeed: { value: c.speed },\n uTime: { value: 0 }\n },\n vertexShader: vert\n })\n\n scene.add(new THREE.Mesh(geo, mat))\n\n const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n renderer.setPixelRatio(Math.min(devicePixelRatio, 2))\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let raf: number,\n time = 0\n\n const interval = gpuTier === 1 ? 100 : 0\n\n const loop = () => {\n raf = interval\n ? (setTimeout(loop, interval) as unknown as number)\n : requestAnimationFrame(loop)\n\n time += interval ? interval / 1000 : 0.016\n\n const v = cRef.current\n\n mat.uniforms.uTime.value = time\n mat.uniforms.uAlpha.value = v.alpha\n mat.uniforms.uChroma.value = v.chroma\n mat.uniforms.uIntensity.value = v.intensity\n mat.uniforms.uSparsity.value = v.sparsity\n mat.uniforms.uSpeed.value = v.speed\n mat.uniforms.uColor.value.set(v.color)\n\n renderer.render(scene, camera)\n }\n\n loop()\n\n return () => {\n window.removeEventListener('resize', resize)\n\n if (interval) {\n clearTimeout(raf)\n } else {\n cancelAnimationFrame(raf)\n }\n\n mat.dispose()\n geo.dispose()\n renderer.dispose()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, gpuTier])\n\n if (!enabled) {\n return null\n }\n\n return (\n <canvas\n className={cn('h-full w-full', className)}\n ref={ref}\n style={{\n mixBlendMode: c.blend as React.CSSProperties['mixBlendMode'],\n ...style\n }}\n />\n )\n}\n\ninterface GlitchProps {\n className?: string\n style?: React.CSSProperties\n}"]}
|
|
1
|
+
{"version":3,"file":"glitch.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/glitch.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef } from 'react'\nimport * as THREE from 'three'\n\nimport { $gpuTier, useGpuTier } from '../../../hooks/use-gpu-tier'\nimport { runRenderLoop } from '../../../hooks/use-render-loop'\nimport { useSmoothControls } from '../../../hooks/use-smooth-controls'\nimport { cn } from '../../../utils'\n\nimport { BLEND_MODES } from './blend-modes'\n\nconst vert = /*glsl*/ `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n`\n\nconst frag = /*glsl*/ `\n uniform float uTime, uAlpha, uIntensity, uChroma, uSpeed, uSparsity;\n uniform vec3 uColor;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }\n\n vec2 hash2(vec2 p) {\n vec3 q = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));\n q += dot(q, q.yzx + 33.33);\n return fract((q.xx + q.yz) * q.zy);\n }\n\n float dither(vec2 p, float a) {\n return step(mod(floor(p.x) + floor(p.y) * 2.0, 4.0) / 4.0, a);\n }\n\n void main() {\n vec3 col = vec3(0.0);\n float t = uTime * uSpeed;\n float tSlow = floor(t / 3.0);\n float dit = dither(gl_FragCoord.xy * 0.5, 0.7);\n\n for (float i = 0.0; i < 6.0; i++) {\n float seed = i * 137.3;\n float epoch = floor((t + hash(vec2(seed, 77.7)) * 200.0) / (4.0 + hash(vec2(seed, 0.0)) * 6.0));\n float life = fract((t + hash(vec2(seed, 77.7)) * 200.0) / (4.0 + hash(vec2(seed, 0.0)) * 6.0));\n\n if (hash(vec2(epoch, seed)) > 1.0 - uSparsity * 0.7) continue;\n\n vec2 center = vec2(hash(vec2(epoch, seed + 13.1)), hash(vec2(epoch, seed + 27.3)));\n vec2 size = vec2(0.015 + hash(vec2(epoch, seed + 41.5)) * 0.08, 0.008 + hash(vec2(epoch, seed + 53.7)) * 0.04);\n vec2 d = abs(vUv - center);\n\n if (d.x < size.x && d.y < size.y) {\n float fade = smoothstep(0.0, 0.05, life) * smoothstep(1.0, 0.95, life);\n vec2 gUV = vUv + (hash2(vec2(epoch, seed + 200.0)) - 0.5) * 0.08 * uIntensity;\n float shift = uChroma * 0.015 * (sin(t * 2.0 + hash(vec2(epoch, seed)) * 6.28) * 0.3 + 0.7);\n\n col += uColor * vec3(\n hash(gUV * 50.0 + vec2(shift, 0.0) + epoch),\n hash(gUV * 50.0 + epoch),\n hash(gUV * 50.0 - vec2(shift, 0.0) + epoch)\n ) * dither(gl_FragCoord.xy * 0.5, fade * 0.8 + 0.2) * uIntensity * 0.7;\n }\n }\n\n for (float i = 0.0; i < 12.0; i++) {\n float seed = i * 211.7 + 1000.0;\n float epoch = floor((t + hash(vec2(seed, 77.7)) * 150.0) / (3.0 + hash(vec2(seed, 0.0)) * 5.0));\n float life = fract((t + hash(vec2(seed, 77.7)) * 150.0) / (3.0 + hash(vec2(seed, 0.0)) * 5.0));\n\n if (hash(vec2(epoch, seed)) > 1.0 - uSparsity * 0.5) continue;\n\n vec2 pos = vec2(hash(vec2(epoch, seed + 13.1)), hash(vec2(epoch, seed + 27.3)));\n float px = 0.003 + hash(vec2(epoch, seed + 41.5)) * 0.008;\n\n if (abs(vUv.x - pos.x) < px && abs(vUv.y - pos.y) < px) {\n float fade = smoothstep(0.0, 0.1, life) * smoothstep(1.0, 0.9, life);\n vec3 c = uColor;\n float cs = hash(vec2(epoch, seed + 700.0));\n\n if (cs < 0.2) c.r *= 1.8 * uChroma;\n else if (cs < 0.4) c.b *= 1.8 * uChroma;\n\n col += c * dither(gl_FragCoord.xy * 0.5, fade * 0.9) * uIntensity;\n }\n }\n\n float tearSize = 25.0 + uSparsity * 10.0;\n float tearThresh = 0.85 + uSparsity * 0.1;\n\n float hY = floor(vUv.y * tearSize);\n if (step(tearThresh, hash(vec2(hY, tSlow))) > 0.0) {\n float shift = (hash(vec2(hY, tSlow + 50.0)) - 0.5) * 0.25 * uIntensity;\n col += uColor * step(0.4, hash(vec2(vUv.x + shift, hY + tSlow))) * dit * uIntensity * 0.5;\n }\n\n float vX = floor(vUv.x * tearSize);\n if (step(tearThresh, hash(vec2(vX, tSlow + 100.0))) > 0.0) {\n float shift = (hash(vec2(vX, tSlow + 150.0)) - 0.5) * 0.25 * uIntensity;\n col += uColor * step(0.4, hash(vec2(vX + tSlow, vUv.y + shift))) * dit * uIntensity * 0.5;\n }\n\n gl_FragColor = vec4(col * uAlpha, max(col.r, max(col.g, col.b)) * uAlpha);\n }\n`\n\nexport function Glitch({ className, style }: GlitchProps) {\n const gpuTier = useGpuTier()\n\n const c = useSmoothControls(\n 'Effects/Glitch',\n {\n alpha: { max: 2, min: 0, step: 0.01, value: 0.25 },\n blend: { options: BLEND_MODES, value: 'difference' },\n chroma: { max: 3, min: 0, step: 0.01, value: 1.17 },\n color: { value: '#ffe6cb' },\n enabled: { value: true },\n intensity: { max: 1, min: 0, step: 0.01, value: 0.59 },\n sparsity: { max: 1, min: 0, step: 0.01, value: 0.21 },\n speed: { max: 10, min: 0.1, step: 0.1, value: 1 }\n },\n { collapsed: true }\n )\n\n const ref = useRef<HTMLCanvasElement>(null)\n const cRef = useRef(c)\n cRef.current = c\n\n const enabled = c.enabled && gpuTier > 0\n\n useEffect(() => {\n if (!ref.current || !enabled) {\n return\n }\n\n let renderer: THREE.WebGLRenderer\n\n try {\n renderer = new THREE.WebGLRenderer({\n alpha: true,\n canvas: ref.current\n })\n } catch {\n // See note in noise.tsx — eager gpu-tier detection should keep us\n // out of here, but if the driver fails the renderer constructor\n // anyway, downgrade so other overlays stop trying too.\n $gpuTier.set(0)\n\n return\n }\n\n const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)\n const geo = new THREE.PlaneGeometry(2, 2)\n const scene = new THREE.Scene()\n\n const mat = new THREE.ShaderMaterial({\n fragmentShader: frag,\n transparent: true,\n uniforms: {\n uAlpha: { value: c.alpha },\n uChroma: { value: c.chroma },\n uColor: { value: new THREE.Color(c.color) },\n uIntensity: { value: c.intensity },\n uSparsity: { value: c.sparsity },\n uSpeed: { value: c.speed },\n uTime: { value: 0 }\n },\n vertexShader: vert\n })\n\n scene.add(new THREE.Mesh(geo, mat))\n\n const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n // Cap DPR at 1.5 — at full retina (2x) the glitch shader is one\n // of the heaviest fillrate consumers in the app, and the visual\n // difference is tiny because it's a chromatic-noise effect.\n renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5))\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let time = 0\n\n // gpu-tier 1 → ~10fps (legacy), gpu-tier 2 → ~30fps (was 60fps).\n // Glitch is a background ambient effect; users won't notice 30 vs\n // 60 but the GPU absolutely will.\n const minIntervalMs = gpuTier === 1 ? 100 : 33\n\n const dispose = runRenderLoop({\n el: ref.current,\n minIntervalMs,\n onFrame: deltaSeconds => {\n time += deltaSeconds\n\n const v = cRef.current\n\n mat.uniforms.uTime.value = time\n mat.uniforms.uAlpha.value = v.alpha\n mat.uniforms.uChroma.value = v.chroma\n mat.uniforms.uIntensity.value = v.intensity\n mat.uniforms.uSparsity.value = v.sparsity\n mat.uniforms.uSpeed.value = v.speed\n mat.uniforms.uColor.value.set(v.color)\n\n renderer.render(scene, camera)\n }\n })\n\n return () => {\n window.removeEventListener('resize', resize)\n dispose()\n\n mat.dispose()\n geo.dispose()\n renderer.dispose()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, gpuTier])\n\n if (!enabled) {\n return null\n }\n\n return (\n <canvas\n className={cn('h-full w-full', className)}\n ref={ref}\n style={{\n mixBlendMode: c.blend as React.CSSProperties['mixBlendMode'],\n ...style\n }}\n />\n )\n}\n\ninterface GlitchProps {\n className?: string\n style?: React.CSSProperties\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"greys.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"greys.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"AAoKA,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,kDAwNrD;AAED,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
|
-
import { useGpuTier } from '../../../hooks/use-gpu-tier';
|
|
5
|
+
import { $gpuTier, useGpuTier } from '../../../hooks/use-gpu-tier';
|
|
6
|
+
import { runRenderLoop } from '../../../hooks/use-render-loop';
|
|
6
7
|
import { useSmoothControls } from '../../../hooks/use-smooth-controls';
|
|
7
8
|
import { cn } from '../../../utils';
|
|
8
9
|
import { BLEND_MODES } from './blend-modes';
|
|
@@ -184,10 +185,20 @@ export function Greys({ className, style }) {
|
|
|
184
185
|
if (!canvasRef.current || !enabled) {
|
|
185
186
|
return;
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
let renderer;
|
|
189
|
+
try {
|
|
190
|
+
renderer = new THREE.WebGLRenderer({
|
|
191
|
+
alpha: true,
|
|
192
|
+
canvas: canvasRef.current
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// See note in noise.tsx — eager gpu-tier detection should keep us
|
|
197
|
+
// out of here, but if the driver fails the renderer constructor
|
|
198
|
+
// anyway, downgrade so other overlays stop trying too.
|
|
199
|
+
$gpuTier.set(0);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
191
202
|
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
192
203
|
const geo = new THREE.PlaneGeometry(2, 2);
|
|
193
204
|
const [rtSource, rtA, rtB] = [0, 1, 2].map(() => new THREE.WebGLRenderTarget(innerWidth, innerHeight, {
|
|
@@ -243,47 +254,53 @@ export function Greys({ className, style }) {
|
|
|
243
254
|
const outScene = mkScene(outputFrag, outU, true);
|
|
244
255
|
const resize = () => {
|
|
245
256
|
renderer.setSize(innerWidth, innerHeight);
|
|
246
|
-
|
|
257
|
+
// Cap at 1.5x — Greys does triple-buffered ping-pong rendering at
|
|
258
|
+
// every frame, so retina x2 is brutal on fillrate.
|
|
259
|
+
renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5));
|
|
247
260
|
[rtSource, rtA, rtB].forEach(rt => rt.setSize(innerWidth, innerHeight));
|
|
248
261
|
moshU.uRes.value.set(innerWidth, innerHeight);
|
|
249
262
|
};
|
|
250
263
|
resize();
|
|
251
264
|
window.addEventListener('resize', resize);
|
|
252
|
-
let
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
265
|
+
let ping = true, time = 0;
|
|
266
|
+
// 30fps cap — feedback effect, no perceptual loss vs 60fps but
|
|
267
|
+
// halves the cost of the heaviest overlay we ship.
|
|
268
|
+
const dispose = runRenderLoop({
|
|
269
|
+
el: canvasRef.current,
|
|
270
|
+
minIntervalMs: 33,
|
|
271
|
+
onFrame: deltaSeconds => {
|
|
272
|
+
time += deltaSeconds;
|
|
273
|
+
const v = cRef.current;
|
|
274
|
+
srcU.uTime.value = time;
|
|
275
|
+
srcU.uSpeed.value = v.speed;
|
|
276
|
+
srcU.uZoom.value = v.zoom;
|
|
277
|
+
srcU.uRotate.value = v.rotate;
|
|
278
|
+
srcU.uFolds.value = v.folds;
|
|
279
|
+
srcU.uDrift.value = v.drift;
|
|
280
|
+
moshU.uTime.value = time;
|
|
281
|
+
moshU.uIntensity.value = v.intensity;
|
|
282
|
+
moshU.uMotion.value = v.motion;
|
|
283
|
+
moshU.uSpeed.value = v.speed;
|
|
284
|
+
moshU.uZoom.value = v.zoom;
|
|
285
|
+
outU.uTime.value = time;
|
|
286
|
+
outU.uAlpha.value = v.alpha;
|
|
287
|
+
outU.uHue.value = v.hue;
|
|
288
|
+
outU.uColor.value.set(typeof v.color === 'string' ? v.color : '#fff');
|
|
289
|
+
renderer.setRenderTarget(rtSource);
|
|
290
|
+
renderer.render(srcScene, camera);
|
|
291
|
+
const [read, write] = ping ? [rtA, rtB] : [rtB, rtA];
|
|
292
|
+
moshU.uPrev.value = read.texture;
|
|
293
|
+
renderer.setRenderTarget(write);
|
|
294
|
+
renderer.render(moshScene, camera);
|
|
295
|
+
outU.uInput.value = write.texture;
|
|
296
|
+
renderer.setRenderTarget(null);
|
|
297
|
+
renderer.render(outScene, camera);
|
|
298
|
+
ping = !ping;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
284
301
|
return () => {
|
|
285
302
|
window.removeEventListener('resize', resize);
|
|
286
|
-
|
|
303
|
+
dispose();
|
|
287
304
|
textures.forEach(t => t.dispose());
|
|
288
305
|
[geo, rtSource, rtA, rtB, renderer].forEach(x => x.dispose());
|
|
289
306
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"greys.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState } from 'react'\nimport * as THREE from 'three'\n\nimport { useGpuTier } from '../../../hooks/use-gpu-tier'\nimport { useSmoothControls } from '../../../hooks/use-smooth-controls'\nimport { cn } from '../../../utils'\n\nimport { BLEND_MODES } from './blend-modes'\n\nconst vert = /*glsl*/ `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n`\n\nconst sourceFrag = /*glsl*/ `\n uniform sampler2D uTex0, uTex1, uTex2, uTex3;\n uniform float uTime, uZoom, uSpeed, uRotate, uFolds, uDrift;\n varying vec2 vUv;\n\n vec3 gray(vec3 c) { return vec3(dot(c, vec3(.299, .587, .114))); }\n vec2 rot(vec2 p, float a) { return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a)); }\n\n vec2 kaleid(vec2 p, float n) {\n float a = mod(atan(p.y, p.x), 6.28318 / n) - 3.14159 / n;\n return length(p) * vec2(cos(a), sin(a));\n }\n\n vec4 tex(int i, vec2 uv) {\n if (i == 0) return texture2D(uTex0, uv);\n if (i == 1) return texture2D(uTex1, uv);\n if (i == 2) return texture2D(uTex2, uv);\n return texture2D(uTex3, uv);\n }\n\n void main() {\n vec2 uv = rot(vUv - .5, uTime * uRotate * .05);\n if (uFolds > 1.) uv = kaleid(uv, uFolds);\n\n float dt = uTime * uDrift * .1;\n uv = uv / uZoom + .5 + vec2(sin(dt * .7) * cos(dt * .3), cos(dt * .5) * sin(dt * .9)) * .15 * uDrift;\n\n float cycle = mod(uTime * uSpeed * .01, 4.);\n int i0 = int(floor(cycle)), i1 = int(mod(float(i0) + 1., 4.));\n float t = smoothstep(0., 1., fract(cycle));\n\n vec3 base = mix(gray(vec3(1.) - tex(i0, uv).rgb), gray(vec3(1.) - tex(i1, uv).rgb), t);\n vec2 uvF = vec2(1. - uv.x, uv.y);\n vec3 flip = mix(gray(vec3(1.) - tex(i0, uvF).rgb), gray(vec3(1.) - tex(i1, uvF).rgb), t);\n\n gl_FragColor = vec4(mix(base, flip, .3 + sin(uTime * .2) * .2), 1.);\n }\n`\n\nconst moshFrag = /*glsl*/ `\n uniform sampler2D uCurrent, uPrev, uTex0, uTex1, uTex2, uTex3;\n uniform float uTime, uIntensity, uMotion, uZoom, uSpeed;\n uniform vec2 uRes;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); }\n vec2 hash2(vec2 p) { return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453); }\n\n float noise(vec2 p) {\n vec2 i = floor(p), f = fract(p) * fract(p) * (3. - 2. * fract(p));\n return mix(mix(hash(i), hash(i + vec2(1., 0.)), f.x), mix(hash(i + vec2(0., 1.)), hash(i + vec2(1., 1.)), f.x), f.y);\n }\n\n vec3 gray(vec3 c) { return vec3(dot(c, vec3(.299, .587, .114))); }\n\n vec2 distort(vec2 uv, float k, float t) {\n float n1 = noise(uv * 8. + t * .5), n2 = noise(uv * 12. + t * .7), flow = noise(uv * 4. + t * .3);\n return uv + vec2(cos(n1 * 6.28 + t * 1.2), sin(n2 * 6.28 + t * .9)) * .02 * k\n + vec2(cos(flow * 6.28 + uv.y * 10.), sin(flow * 6.28 + uv.x * 10.)) * .015 * k;\n }\n\n vec3 tex(int i, vec2 uv) {\n vec2 zuv = (uv - .5) / uZoom + .5;\n if (i == 0) return gray(vec3(1.) - texture2D(uTex0, zuv).rgb);\n if (i == 1) return gray(vec3(1.) - texture2D(uTex1, zuv).rgb);\n if (i == 2) return gray(vec3(1.) - texture2D(uTex2, zuv).rgb);\n return gray(vec3(1.) - texture2D(uTex3, zuv).rgb);\n }\n\n void main() {\n vec2 uv = vUv;\n float t = uTime * uSpeed, tS = floor(t * .1), pS = 80.;\n float amt = uIntensity * uMotion * .8 * (.7 + (sin(t * .5) * .5 + .5) * .3);\n\n vec2 mUV = distort(uv, uIntensity * .4, t);\n\n float hS = floor(uv.y * pS), hA = smoothstep(0., .8, hash(vec2(hS, tS)));\n float hO = (hash(vec2(hS, tS + 50.)) - .5) * .25 * hA * amt;\n float vS = floor(uv.x * pS), vA = smoothstep(0., .8, hash(vec2(vS, tS + 100.)));\n float vO = (hash(vec2(vS, tS + 150.)) - .5) * .25 * vA * amt;\n mUV += vec2(hO, vO);\n\n float bS = pS * .25;\n float hBA = step(.5, hash(vec2(floor(uv.y * bS), tS + 200.)));\n float hBO = (hash(vec2(floor(uv.y * bS), 200.)) - .5) * .35 * hBA * amt;\n float vBA = step(.5, hash(vec2(floor(uv.x * bS), tS + 300.)));\n float vBO = (hash(vec2(floor(uv.x * bS), 250.)) - .5) * .35 * vBA * amt;\n mUV += vec2(hBO, vBO);\n\n vec2 blk = floor(uv * pS * .15);\n mUV += (hash2(vec2(blk.x, blk.y + 500.)) - .5) * .4 * step(.7, hash(vec2(blk.x, blk.y + tS))) * amt;\n mUV = clamp(mUV, 0., 1.);\n\n vec3 prev = texture2D(uPrev, mUV).rgb;\n prev = mix(prev, texture2D(uPrev, clamp(uv + vec2(hBO, vBO), 0., 1.)).rgb, max(hBA, vBA) * .9);\n\n float tY = floor(uv.y * pS * .4);\n if (hash(vec2(tY, tS + 400.)) > .75) {\n prev = mix(prev, texture2D(uPrev, clamp(vec2(uv.x + (hash(vec2(tY, 400.)) - .5) * .5 * amt, uv.y), 0., 1.)).rgb, .85);\n }\n\n if (hA > 0. && amt > .01) {\n prev = mix(prev, gray(texture2D(uPrev, clamp(vec2(uv.x + (gray(prev).r - uv.x) * amt + hO, uv.y), 0., 1.)).rgb), hA);\n }\n\n float d = mix(mix(.97, .99, noise(uv * 8. + t * .2)), 0., step(.994, hash(vec2(tS, 0.))));\n gl_FragColor = vec4(mix(texture2D(uCurrent, uv).rgb, prev, d), 1.);\n }\n`\n\nconst outputFrag = /*glsl*/ `\n uniform sampler2D uInput;\n uniform float uTime, uAlpha, uHue;\n uniform vec3 uColor;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }\n\n vec3 hueShift(vec3 c, float h) {\n float a = h * 6.28318, s = sin(a), co = cos(a);\n vec3 w = vec3(.299, .587, .114);\n return clamp(vec3(\n dot(c, w) + dot(c, vec3(.701, -.587, -.114) * co + vec3(.168, .330, -.497) * s),\n dot(c, w) + dot(c, vec3(-.299, .413, -.114) * co + vec3(.328, .035, -.363) * s),\n dot(c, w) + dot(c, vec3(-.299, -.587, .886) * co + vec3(-.497, .330, .168) * s)\n ), 0., 1.);\n }\n\n void main() {\n vec3 m = texture2D(uInput, vUv).rgb;\n m *= 1. - step(.5, fract(vUv.y * 200.)) * .06 * step(.97, hash(vec2(floor(vUv.y * 30.), floor(uTime * .5))));\n\n float lum = dot(m, vec3(.299, .587, .114));\n gl_FragColor = vec4(hueShift(mix(vec3(lum), uColor * lum * 2., length(uColor)), uHue) * uAlpha, smoothstep(.08, .18, lum * uAlpha));\n }\n`\n\nconst TEXTURES = [\n '/anatomy/grays-0.jpg',\n '/anatomy/grays-3.jpg',\n '/anatomy/grays-6.jpg',\n '/anatomy/grays-9.jpg'\n]\n\nexport function Greys({ className, style }: GreysProps) {\n const gpuTier = useGpuTier()\n const [blendOverride, setBlendOverride] = useState<string | null>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n const c = useSmoothControls(\n 'Effects/Greys',\n {\n alpha: { max: 1, min: 0, step: 0.01, value: 0.19 },\n blend: { options: BLEND_MODES, value: 'color-burn' },\n color: { value: '#ffac02' },\n drift: { max: 2, min: 0, step: 0.1, value: 0.5 },\n enabled: { value: false },\n folds: { max: 12, min: 1, step: 1, value: 1 },\n hue: { max: 1, min: 0, step: 0.01, value: 0.37 },\n intensity: { max: 3, min: 0, step: 0.1, value: 0.1 },\n motion: { max: 2, min: 0, step: 0.1, value: 0.1 },\n rotate: { max: 2, min: -2, step: 0.1, value: 0.3 },\n speed: { max: 1, min: 0.01, step: 0.01, value: 0.21 },\n zoom: { max: 4, min: 0.5, step: 0.1, value: 0.7 }\n },\n { collapsed: true }\n )\n\n const cRef = useRef(c)\n cRef.current = c\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) =>\n e.key.toLowerCase() === 'x' &&\n setBlendOverride(p => (p === 'screen' ? null : 'screen'))\n\n window.addEventListener('keydown', onKey)\n\n return () => window.removeEventListener('keydown', onKey)\n }, [])\n\n const enabled = c.enabled && gpuTier === 2\n\n useEffect(() => {\n if (!canvasRef.current || !enabled) {\n return\n }\n\n const renderer = new THREE.WebGLRenderer({\n alpha: true,\n canvas: canvasRef.current\n })\n\n const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)\n const geo = new THREE.PlaneGeometry(2, 2)\n\n const [rtSource, rtA, rtB] = [0, 1, 2].map(\n () =>\n new THREE.WebGLRenderTarget(innerWidth, innerHeight, {\n magFilter: THREE.NearestFilter,\n minFilter: THREE.NearestFilter\n })\n )\n\n const textures = TEXTURES.map(p => {\n const t = new THREE.TextureLoader().load(p)\n t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping\n t.minFilter = t.magFilter = THREE.LinearFilter\n\n return t\n })\n\n const texU = Object.fromEntries(\n textures.map((t, i) => [`uTex${i}`, { value: t }])\n )\n\n const srcU = {\n ...texU,\n uDrift: { value: 0 },\n uFolds: { value: 0 },\n uRotate: { value: 0 },\n uSpeed: { value: 0 },\n uTime: { value: 0 },\n uZoom: { value: 0 }\n }\n\n const moshU = {\n ...texU,\n uCurrent: { value: rtSource.texture },\n uIntensity: { value: 0 },\n uMotion: { value: 0 },\n uPrev: { value: rtA.texture },\n uRes: { value: new THREE.Vector2(innerWidth, innerHeight) },\n uSpeed: { value: 0 },\n uTime: { value: 0 },\n uZoom: { value: 0 }\n }\n\n const outU = {\n uAlpha: { value: 0 },\n uColor: { value: new THREE.Color() },\n uHue: { value: 0 },\n uInput: { value: rtB.texture },\n uTime: { value: 0 }\n }\n\n const mkScene = (frag: string, uniforms: object, transparent = false) => {\n const s = new THREE.Scene()\n s.add(\n new THREE.Mesh(\n geo.clone(),\n new THREE.ShaderMaterial({\n fragmentShader: frag,\n transparent,\n uniforms: uniforms as Record<string, THREE.IUniform<any>>,\n vertexShader: vert\n })\n )\n )\n\n return s\n }\n\n const srcScene = mkScene(sourceFrag, srcU)\n const moshScene = mkScene(moshFrag, moshU)\n const outScene = mkScene(outputFrag, outU, true)\n\n const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n renderer.setPixelRatio(Math.min(devicePixelRatio, 2))\n ;[rtSource, rtA, rtB].forEach(rt => rt.setSize(innerWidth, innerHeight))\n moshU.uRes.value.set(innerWidth, innerHeight)\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let raf: number,\n ping = true,\n time = 0\n\n const loop = () => {\n raf = requestAnimationFrame(loop)\n time += 0.016\n\n const v = cRef.current\n\n srcU.uTime.value = time\n srcU.uSpeed.value = v.speed\n srcU.uZoom.value = v.zoom\n srcU.uRotate.value = v.rotate\n srcU.uFolds.value = v.folds\n srcU.uDrift.value = v.drift\n\n moshU.uTime.value = time\n moshU.uIntensity.value = v.intensity\n moshU.uMotion.value = v.motion\n moshU.uSpeed.value = v.speed\n moshU.uZoom.value = v.zoom\n\n outU.uTime.value = time\n outU.uAlpha.value = v.alpha\n outU.uHue.value = v.hue\n outU.uColor.value.set(typeof v.color === 'string' ? v.color : '#fff')\n\n renderer.setRenderTarget(rtSource)\n renderer.render(srcScene, camera)\n\n const [read, write] = ping ? [rtA, rtB] : [rtB, rtA]\n moshU.uPrev.value = read.texture\n renderer.setRenderTarget(write)\n renderer.render(moshScene, camera)\n\n outU.uInput.value = write.texture\n renderer.setRenderTarget(null)\n renderer.render(outScene, camera)\n\n ping = !ping\n }\n\n loop()\n\n return () => {\n window.removeEventListener('resize', resize)\n cancelAnimationFrame(raf)\n textures.forEach(t => t.dispose())\n ;[geo, rtSource, rtA, rtB, renderer].forEach(x => x.dispose())\n }\n }, [enabled])\n\n if (!enabled) {\n return null\n }\n\n return (\n <canvas\n className={cn('h-full w-full', className)}\n ref={canvasRef}\n style={{\n mixBlendMode: (blendOverride ??\n c.blend) as React.CSSProperties['mixBlendMode'],\n ...style\n }}\n />\n )\n}\n\ninterface GreysProps {\n className?: string\n style?: React.CSSProperties\n}"]}
|
|
1
|
+
{"version":3,"file":"greys.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState } from 'react'\nimport * as THREE from 'three'\n\nimport { $gpuTier, useGpuTier } from '../../../hooks/use-gpu-tier'\nimport { runRenderLoop } from '../../../hooks/use-render-loop'\nimport { useSmoothControls } from '../../../hooks/use-smooth-controls'\nimport { cn } from '../../../utils'\n\nimport { BLEND_MODES } from './blend-modes'\n\nconst vert = /*glsl*/ `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n`\n\nconst sourceFrag = /*glsl*/ `\n uniform sampler2D uTex0, uTex1, uTex2, uTex3;\n uniform float uTime, uZoom, uSpeed, uRotate, uFolds, uDrift;\n varying vec2 vUv;\n\n vec3 gray(vec3 c) { return vec3(dot(c, vec3(.299, .587, .114))); }\n vec2 rot(vec2 p, float a) { return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a)); }\n\n vec2 kaleid(vec2 p, float n) {\n float a = mod(atan(p.y, p.x), 6.28318 / n) - 3.14159 / n;\n return length(p) * vec2(cos(a), sin(a));\n }\n\n vec4 tex(int i, vec2 uv) {\n if (i == 0) return texture2D(uTex0, uv);\n if (i == 1) return texture2D(uTex1, uv);\n if (i == 2) return texture2D(uTex2, uv);\n return texture2D(uTex3, uv);\n }\n\n void main() {\n vec2 uv = rot(vUv - .5, uTime * uRotate * .05);\n if (uFolds > 1.) uv = kaleid(uv, uFolds);\n\n float dt = uTime * uDrift * .1;\n uv = uv / uZoom + .5 + vec2(sin(dt * .7) * cos(dt * .3), cos(dt * .5) * sin(dt * .9)) * .15 * uDrift;\n\n float cycle = mod(uTime * uSpeed * .01, 4.);\n int i0 = int(floor(cycle)), i1 = int(mod(float(i0) + 1., 4.));\n float t = smoothstep(0., 1., fract(cycle));\n\n vec3 base = mix(gray(vec3(1.) - tex(i0, uv).rgb), gray(vec3(1.) - tex(i1, uv).rgb), t);\n vec2 uvF = vec2(1. - uv.x, uv.y);\n vec3 flip = mix(gray(vec3(1.) - tex(i0, uvF).rgb), gray(vec3(1.) - tex(i1, uvF).rgb), t);\n\n gl_FragColor = vec4(mix(base, flip, .3 + sin(uTime * .2) * .2), 1.);\n }\n`\n\nconst moshFrag = /*glsl*/ `\n uniform sampler2D uCurrent, uPrev, uTex0, uTex1, uTex2, uTex3;\n uniform float uTime, uIntensity, uMotion, uZoom, uSpeed;\n uniform vec2 uRes;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); }\n vec2 hash2(vec2 p) { return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453); }\n\n float noise(vec2 p) {\n vec2 i = floor(p), f = fract(p) * fract(p) * (3. - 2. * fract(p));\n return mix(mix(hash(i), hash(i + vec2(1., 0.)), f.x), mix(hash(i + vec2(0., 1.)), hash(i + vec2(1., 1.)), f.x), f.y);\n }\n\n vec3 gray(vec3 c) { return vec3(dot(c, vec3(.299, .587, .114))); }\n\n vec2 distort(vec2 uv, float k, float t) {\n float n1 = noise(uv * 8. + t * .5), n2 = noise(uv * 12. + t * .7), flow = noise(uv * 4. + t * .3);\n return uv + vec2(cos(n1 * 6.28 + t * 1.2), sin(n2 * 6.28 + t * .9)) * .02 * k\n + vec2(cos(flow * 6.28 + uv.y * 10.), sin(flow * 6.28 + uv.x * 10.)) * .015 * k;\n }\n\n vec3 tex(int i, vec2 uv) {\n vec2 zuv = (uv - .5) / uZoom + .5;\n if (i == 0) return gray(vec3(1.) - texture2D(uTex0, zuv).rgb);\n if (i == 1) return gray(vec3(1.) - texture2D(uTex1, zuv).rgb);\n if (i == 2) return gray(vec3(1.) - texture2D(uTex2, zuv).rgb);\n return gray(vec3(1.) - texture2D(uTex3, zuv).rgb);\n }\n\n void main() {\n vec2 uv = vUv;\n float t = uTime * uSpeed, tS = floor(t * .1), pS = 80.;\n float amt = uIntensity * uMotion * .8 * (.7 + (sin(t * .5) * .5 + .5) * .3);\n\n vec2 mUV = distort(uv, uIntensity * .4, t);\n\n float hS = floor(uv.y * pS), hA = smoothstep(0., .8, hash(vec2(hS, tS)));\n float hO = (hash(vec2(hS, tS + 50.)) - .5) * .25 * hA * amt;\n float vS = floor(uv.x * pS), vA = smoothstep(0., .8, hash(vec2(vS, tS + 100.)));\n float vO = (hash(vec2(vS, tS + 150.)) - .5) * .25 * vA * amt;\n mUV += vec2(hO, vO);\n\n float bS = pS * .25;\n float hBA = step(.5, hash(vec2(floor(uv.y * bS), tS + 200.)));\n float hBO = (hash(vec2(floor(uv.y * bS), 200.)) - .5) * .35 * hBA * amt;\n float vBA = step(.5, hash(vec2(floor(uv.x * bS), tS + 300.)));\n float vBO = (hash(vec2(floor(uv.x * bS), 250.)) - .5) * .35 * vBA * amt;\n mUV += vec2(hBO, vBO);\n\n vec2 blk = floor(uv * pS * .15);\n mUV += (hash2(vec2(blk.x, blk.y + 500.)) - .5) * .4 * step(.7, hash(vec2(blk.x, blk.y + tS))) * amt;\n mUV = clamp(mUV, 0., 1.);\n\n vec3 prev = texture2D(uPrev, mUV).rgb;\n prev = mix(prev, texture2D(uPrev, clamp(uv + vec2(hBO, vBO), 0., 1.)).rgb, max(hBA, vBA) * .9);\n\n float tY = floor(uv.y * pS * .4);\n if (hash(vec2(tY, tS + 400.)) > .75) {\n prev = mix(prev, texture2D(uPrev, clamp(vec2(uv.x + (hash(vec2(tY, 400.)) - .5) * .5 * amt, uv.y), 0., 1.)).rgb, .85);\n }\n\n if (hA > 0. && amt > .01) {\n prev = mix(prev, gray(texture2D(uPrev, clamp(vec2(uv.x + (gray(prev).r - uv.x) * amt + hO, uv.y), 0., 1.)).rgb), hA);\n }\n\n float d = mix(mix(.97, .99, noise(uv * 8. + t * .2)), 0., step(.994, hash(vec2(tS, 0.))));\n gl_FragColor = vec4(mix(texture2D(uCurrent, uv).rgb, prev, d), 1.);\n }\n`\n\nconst outputFrag = /*glsl*/ `\n uniform sampler2D uInput;\n uniform float uTime, uAlpha, uHue;\n uniform vec3 uColor;\n varying vec2 vUv;\n\n float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }\n\n vec3 hueShift(vec3 c, float h) {\n float a = h * 6.28318, s = sin(a), co = cos(a);\n vec3 w = vec3(.299, .587, .114);\n return clamp(vec3(\n dot(c, w) + dot(c, vec3(.701, -.587, -.114) * co + vec3(.168, .330, -.497) * s),\n dot(c, w) + dot(c, vec3(-.299, .413, -.114) * co + vec3(.328, .035, -.363) * s),\n dot(c, w) + dot(c, vec3(-.299, -.587, .886) * co + vec3(-.497, .330, .168) * s)\n ), 0., 1.);\n }\n\n void main() {\n vec3 m = texture2D(uInput, vUv).rgb;\n m *= 1. - step(.5, fract(vUv.y * 200.)) * .06 * step(.97, hash(vec2(floor(vUv.y * 30.), floor(uTime * .5))));\n\n float lum = dot(m, vec3(.299, .587, .114));\n gl_FragColor = vec4(hueShift(mix(vec3(lum), uColor * lum * 2., length(uColor)), uHue) * uAlpha, smoothstep(.08, .18, lum * uAlpha));\n }\n`\n\nconst TEXTURES = [\n '/anatomy/grays-0.jpg',\n '/anatomy/grays-3.jpg',\n '/anatomy/grays-6.jpg',\n '/anatomy/grays-9.jpg'\n]\n\nexport function Greys({ className, style }: GreysProps) {\n const gpuTier = useGpuTier()\n const [blendOverride, setBlendOverride] = useState<string | null>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n const c = useSmoothControls(\n 'Effects/Greys',\n {\n alpha: { max: 1, min: 0, step: 0.01, value: 0.19 },\n blend: { options: BLEND_MODES, value: 'color-burn' },\n color: { value: '#ffac02' },\n drift: { max: 2, min: 0, step: 0.1, value: 0.5 },\n enabled: { value: false },\n folds: { max: 12, min: 1, step: 1, value: 1 },\n hue: { max: 1, min: 0, step: 0.01, value: 0.37 },\n intensity: { max: 3, min: 0, step: 0.1, value: 0.1 },\n motion: { max: 2, min: 0, step: 0.1, value: 0.1 },\n rotate: { max: 2, min: -2, step: 0.1, value: 0.3 },\n speed: { max: 1, min: 0.01, step: 0.01, value: 0.21 },\n zoom: { max: 4, min: 0.5, step: 0.1, value: 0.7 }\n },\n { collapsed: true }\n )\n\n const cRef = useRef(c)\n cRef.current = c\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) =>\n e.key.toLowerCase() === 'x' &&\n setBlendOverride(p => (p === 'screen' ? null : 'screen'))\n\n window.addEventListener('keydown', onKey)\n\n return () => window.removeEventListener('keydown', onKey)\n }, [])\n\n const enabled = c.enabled && gpuTier === 2\n\n useEffect(() => {\n if (!canvasRef.current || !enabled) {\n return\n }\n\n let renderer: THREE.WebGLRenderer\n\n try {\n renderer = new THREE.WebGLRenderer({\n alpha: true,\n canvas: canvasRef.current\n })\n } catch {\n // See note in noise.tsx — eager gpu-tier detection should keep us\n // out of here, but if the driver fails the renderer constructor\n // anyway, downgrade so other overlays stop trying too.\n $gpuTier.set(0)\n\n return\n }\n\n const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)\n const geo = new THREE.PlaneGeometry(2, 2)\n\n const [rtSource, rtA, rtB] = [0, 1, 2].map(\n () =>\n new THREE.WebGLRenderTarget(innerWidth, innerHeight, {\n magFilter: THREE.NearestFilter,\n minFilter: THREE.NearestFilter\n })\n )\n\n const textures = TEXTURES.map(p => {\n const t = new THREE.TextureLoader().load(p)\n t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping\n t.minFilter = t.magFilter = THREE.LinearFilter\n\n return t\n })\n\n const texU = Object.fromEntries(\n textures.map((t, i) => [`uTex${i}`, { value: t }])\n )\n\n const srcU = {\n ...texU,\n uDrift: { value: 0 },\n uFolds: { value: 0 },\n uRotate: { value: 0 },\n uSpeed: { value: 0 },\n uTime: { value: 0 },\n uZoom: { value: 0 }\n }\n\n const moshU = {\n ...texU,\n uCurrent: { value: rtSource.texture },\n uIntensity: { value: 0 },\n uMotion: { value: 0 },\n uPrev: { value: rtA.texture },\n uRes: { value: new THREE.Vector2(innerWidth, innerHeight) },\n uSpeed: { value: 0 },\n uTime: { value: 0 },\n uZoom: { value: 0 }\n }\n\n const outU = {\n uAlpha: { value: 0 },\n uColor: { value: new THREE.Color() },\n uHue: { value: 0 },\n uInput: { value: rtB.texture },\n uTime: { value: 0 }\n }\n\n const mkScene = (frag: string, uniforms: object, transparent = false) => {\n const s = new THREE.Scene()\n s.add(\n new THREE.Mesh(\n geo.clone(),\n new THREE.ShaderMaterial({\n fragmentShader: frag,\n transparent,\n uniforms: uniforms as Record<string, THREE.IUniform<any>>,\n vertexShader: vert\n })\n )\n )\n\n return s\n }\n\n const srcScene = mkScene(sourceFrag, srcU)\n const moshScene = mkScene(moshFrag, moshU)\n const outScene = mkScene(outputFrag, outU, true)\n\n const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n // Cap at 1.5x — Greys does triple-buffered ping-pong rendering at\n // every frame, so retina x2 is brutal on fillrate.\n renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5))\n ;[rtSource, rtA, rtB].forEach(rt => rt.setSize(innerWidth, innerHeight))\n moshU.uRes.value.set(innerWidth, innerHeight)\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let ping = true,\n time = 0\n\n // 30fps cap — feedback effect, no perceptual loss vs 60fps but\n // halves the cost of the heaviest overlay we ship.\n const dispose = runRenderLoop({\n el: canvasRef.current,\n minIntervalMs: 33,\n onFrame: deltaSeconds => {\n time += deltaSeconds\n\n const v = cRef.current\n\n srcU.uTime.value = time\n srcU.uSpeed.value = v.speed\n srcU.uZoom.value = v.zoom\n srcU.uRotate.value = v.rotate\n srcU.uFolds.value = v.folds\n srcU.uDrift.value = v.drift\n\n moshU.uTime.value = time\n moshU.uIntensity.value = v.intensity\n moshU.uMotion.value = v.motion\n moshU.uSpeed.value = v.speed\n moshU.uZoom.value = v.zoom\n\n outU.uTime.value = time\n outU.uAlpha.value = v.alpha\n outU.uHue.value = v.hue\n outU.uColor.value.set(typeof v.color === 'string' ? v.color : '#fff')\n\n renderer.setRenderTarget(rtSource)\n renderer.render(srcScene, camera)\n\n const [read, write] = ping ? [rtA, rtB] : [rtB, rtA]\n moshU.uPrev.value = read.texture\n renderer.setRenderTarget(write)\n renderer.render(moshScene, camera)\n\n outU.uInput.value = write.texture\n renderer.setRenderTarget(null)\n renderer.render(outScene, camera)\n\n ping = !ping\n }\n })\n\n return () => {\n window.removeEventListener('resize', resize)\n dispose()\n textures.forEach(t => t.dispose())\n ;[geo, rtSource, rtA, rtB, renderer].forEach(x => x.dispose())\n }\n }, [enabled])\n\n if (!enabled) {\n return null\n }\n\n return (\n <canvas\n className={cn('h-full w-full', className)}\n ref={canvasRef}\n style={{\n mixBlendMode: (blendOverride ??\n c.blend) as React.CSSProperties['mixBlendMode'],\n ...style\n }}\n />\n )\n}\n\ninterface GreysProps {\n className?: string\n style?: React.CSSProperties\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noise.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/noise.tsx"],"names":[],"mappings":"AAqCA,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"noise.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/noise.tsx"],"names":[],"mappings":"AAqCA,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,kDAmIrD;AAED,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef } from 'react';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
|
-
import { useGpuTier } from '../../../hooks/use-gpu-tier';
|
|
5
|
+
import { $gpuTier, useGpuTier } from '../../../hooks/use-gpu-tier';
|
|
6
6
|
import { useSmoothControls } from '../../../hooks/use-smooth-controls';
|
|
7
7
|
import { cn, hexToVec3 } from '../../../utils';
|
|
8
8
|
import { BLEND_MODES } from './blend-modes';
|
|
@@ -41,18 +41,32 @@ export function Noise({ className, style }) {
|
|
|
41
41
|
size: { max: 10, min: 0.1, step: 0.1, value: 1 }
|
|
42
42
|
}, { collapsed: true });
|
|
43
43
|
const canvasRef = useRef(null);
|
|
44
|
-
const cRef = useRef(c);
|
|
45
|
-
cRef.current = c;
|
|
46
44
|
const enabled = c.enabled && gpuTier > 0;
|
|
45
|
+
// The noise shader is fully deterministic: given the same uniforms it
|
|
46
|
+
// produces an identical output every frame. The previous version ran
|
|
47
|
+
// it at 60fps forever, which on a retina display with mix-blend-mode
|
|
48
|
+
// is enough to peg the GPU/compositor for the entire lifetime of the
|
|
49
|
+
// page (this is the dominant contributor to the "fans go crazy after
|
|
50
|
+
// a few hours of idle" symptom).
|
|
51
|
+
//
|
|
52
|
+
// Instead we render exactly once on mount, and re-render only when
|
|
53
|
+
// the user-controllable uniforms change or the viewport resizes.
|
|
47
54
|
useEffect(() => {
|
|
48
55
|
if (!canvasRef.current || !enabled) {
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
let renderer;
|
|
59
|
+
try {
|
|
60
|
+
renderer = new THREE.WebGLRenderer({
|
|
61
|
+
alpha: true,
|
|
62
|
+
canvas: canvasRef.current,
|
|
63
|
+
premultipliedAlpha: false
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
$gpuTier.set(0);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
56
70
|
renderer.setClearColor(0x000000, 0);
|
|
57
71
|
const scene = new THREE.Scene();
|
|
58
72
|
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
@@ -71,42 +85,49 @@ export function Noise({ className, style }) {
|
|
|
71
85
|
vertexShader: vert
|
|
72
86
|
});
|
|
73
87
|
scene.add(new THREE.Mesh(geo, mat));
|
|
88
|
+
// Cap pixel ratio at 1.5 — noise is intentionally pixelated, so the
|
|
89
|
+
// extra retina samples are wasted fillrate.
|
|
90
|
+
const dpr = Math.min(devicePixelRatio, 1.5);
|
|
91
|
+
const render = () => {
|
|
92
|
+
mat.uniforms.uColor.value = hexToVec3(c.color);
|
|
93
|
+
mat.uniforms.uDensity.value = c.density;
|
|
94
|
+
mat.uniforms.uOpacity.value = c.opacity;
|
|
95
|
+
mat.uniforms.uSize.value = c.size;
|
|
96
|
+
mat.uniforms.uDpr.value = dpr;
|
|
97
|
+
renderer.render(scene, camera);
|
|
98
|
+
};
|
|
74
99
|
const resize = () => {
|
|
75
100
|
renderer.setSize(innerWidth, innerHeight);
|
|
76
|
-
renderer.setPixelRatio(
|
|
77
|
-
mat.uniforms.uRes.value.set(innerWidth *
|
|
78
|
-
|
|
101
|
+
renderer.setPixelRatio(dpr);
|
|
102
|
+
mat.uniforms.uRes.value.set(innerWidth * dpr, innerHeight * dpr);
|
|
103
|
+
render();
|
|
79
104
|
};
|
|
80
105
|
resize();
|
|
81
106
|
window.addEventListener('resize', resize);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const v = cRef.current;
|
|
89
|
-
mat.uniforms.uSize.value = v.size;
|
|
90
|
-
mat.uniforms.uDensity.value = v.density;
|
|
91
|
-
mat.uniforms.uColor.value = hexToVec3(v.color);
|
|
92
|
-
mat.uniforms.uOpacity.value = v.opacity;
|
|
93
|
-
renderer.render(scene, camera);
|
|
107
|
+
// Re-render when the tab becomes visible again, in case the GL
|
|
108
|
+
// context was discarded by the browser while the page was
|
|
109
|
+
// backgrounded — otherwise we can come back to a transparent canvas.
|
|
110
|
+
const onVisibility = () => {
|
|
111
|
+
if (!document.hidden)
|
|
112
|
+
render();
|
|
94
113
|
};
|
|
95
|
-
|
|
114
|
+
document.addEventListener('visibilitychange', onVisibility);
|
|
96
115
|
return () => {
|
|
97
116
|
window.removeEventListener('resize', resize);
|
|
98
|
-
|
|
99
|
-
clearTimeout(raf);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
cancelAnimationFrame(raf);
|
|
103
|
-
}
|
|
117
|
+
document.removeEventListener('visibilitychange', onVisibility);
|
|
104
118
|
mat.dispose();
|
|
105
119
|
geo.dispose();
|
|
106
120
|
renderer.dispose();
|
|
107
121
|
};
|
|
108
122
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
109
|
-
}, [
|
|
123
|
+
}, [
|
|
124
|
+
enabled,
|
|
125
|
+
gpuTier,
|
|
126
|
+
c.color,
|
|
127
|
+
c.density,
|
|
128
|
+
c.opacity,
|
|
129
|
+
c.size
|
|
130
|
+
]);
|
|
110
131
|
if (!enabled) {
|
|
111
132
|
return null;
|
|
112
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noise.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/noise.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"noise.js","sourceRoot":"","sources":["../../../../src/ui/components/overlays/noise.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useEffect, useRef } from 'react'\nimport * as THREE from 'three'\n\nimport { $gpuTier, useGpuTier } from '../../../hooks/use-gpu-tier'\nimport { useSmoothControls } from '../../../hooks/use-smooth-controls'\nimport { cn, hexToVec3 } from '../../../utils'\n\nimport { BLEND_MODES } from './blend-modes'\n\nconst vert = /*glsl*/ `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n`\n\nconst frag = /*glsl*/ `\n uniform vec2 uRes;\n uniform float uDpr, uSize, uDensity, uOpacity;\n uniform vec3 uColor;\n varying vec2 vUv;\n\n float hash(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * 0.1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n }\n\n void main() {\n float n = hash(floor(vUv * uRes / (uSize * uDpr)));\n gl_FragColor = vec4(uColor, step(1.0 - uDensity, n)) * uOpacity;\n }\n`\n\nexport function Noise({ className, style }: NoiseProps) {\n const gpuTier = useGpuTier()\n\n const c = useSmoothControls(\n 'Effects/Noise',\n {\n blend: { options: BLEND_MODES, value: 'color-dodge' as const },\n color: { value: '#eaeaea' },\n density: { max: 1, min: 0, step: 0.01, value: 0.11 },\n enabled: { value: true },\n opacity: { max: 1, min: 0, step: 0.01, value: 0.55 },\n size: { max: 10, min: 0.1, step: 0.1, value: 1 }\n },\n { collapsed: true }\n )\n\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n const enabled = c.enabled && gpuTier > 0\n\n // The noise shader is fully deterministic: given the same uniforms it\n // produces an identical output every frame. The previous version ran\n // it at 60fps forever, which on a retina display with mix-blend-mode\n // is enough to peg the GPU/compositor for the entire lifetime of the\n // page (this is the dominant contributor to the \"fans go crazy after\n // a few hours of idle\" symptom).\n //\n // Instead we render exactly once on mount, and re-render only when\n // the user-controllable uniforms change or the viewport resizes.\n useEffect(() => {\n if (!canvasRef.current || !enabled) {\n return\n }\n\n let renderer: THREE.WebGLRenderer\n\n try {\n renderer = new THREE.WebGLRenderer({\n alpha: true,\n canvas: canvasRef.current,\n premultipliedAlpha: false\n })\n } catch {\n $gpuTier.set(0)\n\n return\n }\n\n renderer.setClearColor(0x000000, 0)\n\n const scene = new THREE.Scene()\n const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1)\n const geo = new THREE.PlaneGeometry(2, 2)\n\n const mat = new THREE.ShaderMaterial({\n fragmentShader: frag,\n transparent: true,\n uniforms: {\n uColor: { value: hexToVec3(c.color) },\n uDensity: { value: c.density },\n uDpr: { value: 1 },\n uOpacity: { value: c.opacity },\n uRes: { value: new THREE.Vector2() },\n uSize: { value: c.size }\n },\n vertexShader: vert\n })\n\n scene.add(new THREE.Mesh(geo, mat))\n\n // Cap pixel ratio at 1.5 — noise is intentionally pixelated, so the\n // extra retina samples are wasted fillrate.\n const dpr = Math.min(devicePixelRatio, 1.5)\n\n const render = () => {\n mat.uniforms.uColor.value = hexToVec3(c.color)\n mat.uniforms.uDensity.value = c.density\n mat.uniforms.uOpacity.value = c.opacity\n mat.uniforms.uSize.value = c.size\n mat.uniforms.uDpr.value = dpr\n renderer.render(scene, camera)\n }\n\n const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n renderer.setPixelRatio(dpr)\n mat.uniforms.uRes.value.set(innerWidth * dpr, innerHeight * dpr)\n render()\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n // Re-render when the tab becomes visible again, in case the GL\n // context was discarded by the browser while the page was\n // backgrounded — otherwise we can come back to a transparent canvas.\n const onVisibility = () => {\n if (!document.hidden) render()\n }\n\n document.addEventListener('visibilitychange', onVisibility)\n\n return () => {\n window.removeEventListener('resize', resize)\n document.removeEventListener('visibilitychange', onVisibility)\n\n mat.dispose()\n geo.dispose()\n renderer.dispose()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n enabled,\n gpuTier,\n c.color,\n c.density,\n c.opacity,\n c.size\n ])\n\n if (!enabled) {\n return null\n }\n\n return (\n <canvas\n className={cn('h-full w-full', className)}\n ref={canvasRef}\n style={{ mixBlendMode: c.blend, ...style }}\n />\n )\n}\n\ninterface NoiseProps {\n className?: string\n style?: React.CSSProperties\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function SceneCanvas({ camera, children, className, contained, noEvents, style }: SceneCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
export declare function SceneCanvas({ camera, children, className, contained, frameloop, noEvents, style }: SceneCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
2
2
|
interface SceneCanvasProps {
|
|
3
3
|
camera?: {
|
|
4
4
|
far?: number;
|
|
@@ -9,6 +9,14 @@ interface SceneCanvasProps {
|
|
|
9
9
|
children: () => React.ReactNode;
|
|
10
10
|
className?: string;
|
|
11
11
|
contained?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* R3F frame-loop mode. Defaults to `'always'` for backwards
|
|
14
|
+
* compatibility, but `'demand'` is strongly preferred for static
|
|
15
|
+
* scenes (use `invalidate()` from `useThree` to request frames). The
|
|
16
|
+
* canvas additionally pauses (forces `'never'`) while the document
|
|
17
|
+
* is hidden, regardless of this setting.
|
|
18
|
+
*/
|
|
19
|
+
frameloop?: 'always' | 'demand' | 'never';
|
|
12
20
|
noEvents?: boolean;
|
|
13
21
|
style?: React.CSSProperties;
|
|
14
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-canvas.d.ts","sourceRoot":"","sources":["../../../src/ui/components/scene-canvas.tsx"],"names":[],"mappings":"AAqHA,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,KAAK,EACN,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"scene-canvas.d.ts","sourceRoot":"","sources":["../../../src/ui/components/scene-canvas.tsx"],"names":[],"mappings":"AAqHA,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAoB,EACpB,QAAQ,EACR,KAAK,EACN,EAAE,gBAAgB,2CA0GlB;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE;QACP,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QACnC,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;IACD,QAAQ,EAAE,MAAM,KAAK,CAAC,SAAS,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
|
|
@@ -70,7 +70,7 @@ function PositionedGroup({ baseZoom, bounds, children }) {
|
|
|
70
70
|
});
|
|
71
71
|
return _jsx("group", { ref: ref, children: children });
|
|
72
72
|
}
|
|
73
|
-
export function SceneCanvas({ camera, children, className, contained, noEvents, style }) {
|
|
73
|
+
export function SceneCanvas({ camera, children, className, contained, frameloop = 'always', noEvents, style }) {
|
|
74
74
|
const [container, setContainer] = useState(null);
|
|
75
75
|
const baseZoom = camera?.zoom ?? 150;
|
|
76
76
|
const bounds = useBounds(contained ? (container?.parentElement ?? null) : null);
|
|
@@ -88,13 +88,24 @@ export function SceneCanvas({ camera, children, className, contained, noEvents,
|
|
|
88
88
|
window.removeEventListener('pointerup', unlock);
|
|
89
89
|
};
|
|
90
90
|
}, [container, contained, noEvents]);
|
|
91
|
+
// Pause the R3F render loop when the tab is hidden. Even on
|
|
92
|
+
// `frameloop="always"` scenes we don't want the GPU running while the
|
|
93
|
+
// user can't see anything — this is the dominant fix for the "fans
|
|
94
|
+
// crank up after hours of idle" symptom.
|
|
95
|
+
const [pageHidden, setPageHidden] = useState(typeof document !== 'undefined' && document.hidden);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const onVisibility = () => setPageHidden(document.hidden);
|
|
98
|
+
document.addEventListener('visibilitychange', onVisibility);
|
|
99
|
+
return () => document.removeEventListener('visibilitychange', onVisibility);
|
|
100
|
+
}, []);
|
|
101
|
+
const effectiveFrameloop = pageHidden ? 'never' : frameloop;
|
|
91
102
|
const cam = useMemo(() => ({
|
|
92
103
|
far: camera?.far ?? 100,
|
|
93
104
|
near: camera?.near ?? -100,
|
|
94
105
|
position: camera?.position ?? [0, 0, 10],
|
|
95
106
|
zoom: baseZoom * (contained ? 1 : 2)
|
|
96
107
|
}), [baseZoom, camera, contained]);
|
|
97
|
-
const canvas = (_jsx(Canvas, { camera: cam, className: className, dpr: [1, 2], eventPrefix: contained ? 'client' : 'offset', eventSource: contained ? (container ?? undefined) : undefined, gl: GL, orthographic: true, style: contained
|
|
108
|
+
const canvas = (_jsx(Canvas, { camera: cam, className: className, dpr: [1, 2], eventPrefix: contained ? 'client' : 'offset', eventSource: contained ? (container ?? undefined) : undefined, frameloop: effectiveFrameloop, gl: GL, orthographic: true, style: contained
|
|
98
109
|
? {
|
|
99
110
|
height: '100dvh',
|
|
100
111
|
inset: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-canvas.js","sourceRoot":"","sources":["../../../src/ui/components/scene-canvas.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { Canvas, useFrame, useThree } from '@react-three/fiber'\nimport {\n Suspense,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport * as THREE from 'three'\n\nconst GL = {\n alpha: true,\n antialias: true,\n depth: true,\n outputColorSpace: 'srgb',\n powerPreference: 'high-performance',\n stencil: false\n} as const\n\nconst tmp = {\n camDir: new THREE.Vector3(),\n hit: new THREE.Vector3(),\n ndc: new THREE.Vector2(),\n origin: new THREE.Vector3(0, 0, 0),\n plane: new THREE.Plane(),\n ray: new THREE.Raycaster()\n}\n\ntype Bounds = { height: number; pageX: number; pageY: number; width: number }\n\nfunction useBounds(target: HTMLElement | null) {\n const bounds = useRef<Bounds | null>(null)\n\n useLayoutEffect(() => {\n if (!target) {\n return\n }\n\n const measure = () => {\n const b = target.getBoundingClientRect()\n bounds.current = {\n height: b.height,\n pageX: b.left + window.scrollX,\n pageY: b.top + window.scrollY,\n width: b.width\n }\n }\n\n measure()\n\n const ro = new ResizeObserver(measure)\n ro.observe(target)\n ro.observe(document.body)\n window.addEventListener('resize', measure, { passive: true })\n\n return () => {\n ro.disconnect()\n window.removeEventListener('resize', measure)\n }\n }, [target])\n\n return bounds\n}\n\nfunction PositionedGroup({\n baseZoom,\n bounds,\n children\n}: React.PropsWithChildren<{\n baseZoom: number\n bounds: React.RefObject<Bounds | null>\n}>) {\n const ref = useRef<THREE.Group>(null)\n const { camera, size, viewport } = useThree()\n\n useFrame(() => {\n const g = ref.current\n const b = bounds.current\n\n if (!g || !b) {\n return\n }\n\n const left = b.pageX - window.scrollX\n const top = b.pageY - window.scrollY\n\n tmp.ndc.set(\n ((left + b.width / 2) / size.width) * 2 - 1,\n 1 - ((top + b.height / 2) / size.height) * 2\n )\n\n camera.getWorldDirection(tmp.camDir)\n tmp.plane.setFromNormalAndCoplanarPoint(tmp.camDir, tmp.origin)\n tmp.ray.setFromCamera(tmp.ndc, camera)\n\n const hit = tmp.ray.ray.intersectPlane(tmp.plane, tmp.hit)\n\n if (hit) {\n g.position.copy(hit)\n }\n\n const zoom = (camera as THREE.Camera & { zoom?: number }).zoom ?? 1\n\n g.scale.setScalar(\n Math.min(\n (b.width / size.width) * viewport.width,\n (b.height / size.height) * viewport.height\n ) * (baseZoom > 0 ? zoom / baseZoom : 1)\n )\n })\n\n return <group ref={ref}>{children}</group>\n}\n\nexport function SceneCanvas({\n camera,\n children,\n className,\n contained,\n noEvents,\n style\n}: SceneCanvasProps) {\n const [container, setContainer] = useState<HTMLDivElement | null>(null)\n const baseZoom = camera?.zoom ?? 150\n\n const bounds = useBounds(\n contained ? (container?.parentElement ?? null) : null\n )\n\n useEffect(() => {\n const el = contained && !noEvents ? container : null\n\n if (!el) {\n return\n }\n\n const lock = () => (document.body.style.userSelect = 'none')\n const unlock = () => (document.body.style.userSelect = '')\n\n el.addEventListener('pointerdown', lock)\n window.addEventListener('pointerup', unlock)\n\n return () => {\n el.removeEventListener('pointerdown', lock)\n window.removeEventListener('pointerup', unlock)\n }\n }, [container, contained, noEvents])\n\n const cam = useMemo(\n () => ({\n far: camera?.far ?? 100,\n near: camera?.near ?? -100,\n position: camera?.position ?? ([0, 0, 10] as [number, number, number]),\n zoom: baseZoom * (contained ? 1 : 2)\n }),\n [baseZoom, camera, contained]\n )\n\n const canvas = (\n <Canvas\n camera={cam}\n className={className}\n dpr={[1, 2]}\n eventPrefix={contained ? 'client' : 'offset'}\n eventSource={contained ? (container ?? undefined) : undefined}\n gl={GL}\n orthographic\n style={\n contained\n ? {\n height: '100dvh',\n inset: 0,\n pointerEvents: 'none',\n position: 'fixed',\n width: '100dvw',\n zIndex: 0,\n ...style\n }\n : { height: '100%', width: '100%', ...style }\n }\n >\n {contained ? (\n <PositionedGroup baseZoom={baseZoom} bounds={bounds}>\n {children()}\n </PositionedGroup>\n ) : (\n children()\n )}\n </Canvas>\n )\n\n return contained ? (\n <Suspense>\n <div\n ref={setContainer}\n style={{\n height: '100%',\n inset: 0,\n pointerEvents: noEvents ? 'none' : 'auto',\n position: 'absolute',\n width: '100%',\n zIndex: 1\n }}\n />\n {canvas}\n </Suspense>\n ) : (\n canvas\n )\n}\n\ninterface SceneCanvasProps {\n camera?: {\n far?: number\n near?: number\n position?: [number, number, number]\n zoom?: number\n }\n children: () => React.ReactNode\n className?: string\n contained?: boolean\n noEvents?: boolean\n style?: React.CSSProperties\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scene-canvas.js","sourceRoot":"","sources":["../../../src/ui/components/scene-canvas.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { Canvas, useFrame, useThree } from '@react-three/fiber'\nimport {\n Suspense,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport * as THREE from 'three'\n\nconst GL = {\n alpha: true,\n antialias: true,\n depth: true,\n outputColorSpace: 'srgb',\n powerPreference: 'high-performance',\n stencil: false\n} as const\n\nconst tmp = {\n camDir: new THREE.Vector3(),\n hit: new THREE.Vector3(),\n ndc: new THREE.Vector2(),\n origin: new THREE.Vector3(0, 0, 0),\n plane: new THREE.Plane(),\n ray: new THREE.Raycaster()\n}\n\ntype Bounds = { height: number; pageX: number; pageY: number; width: number }\n\nfunction useBounds(target: HTMLElement | null) {\n const bounds = useRef<Bounds | null>(null)\n\n useLayoutEffect(() => {\n if (!target) {\n return\n }\n\n const measure = () => {\n const b = target.getBoundingClientRect()\n bounds.current = {\n height: b.height,\n pageX: b.left + window.scrollX,\n pageY: b.top + window.scrollY,\n width: b.width\n }\n }\n\n measure()\n\n const ro = new ResizeObserver(measure)\n ro.observe(target)\n ro.observe(document.body)\n window.addEventListener('resize', measure, { passive: true })\n\n return () => {\n ro.disconnect()\n window.removeEventListener('resize', measure)\n }\n }, [target])\n\n return bounds\n}\n\nfunction PositionedGroup({\n baseZoom,\n bounds,\n children\n}: React.PropsWithChildren<{\n baseZoom: number\n bounds: React.RefObject<Bounds | null>\n}>) {\n const ref = useRef<THREE.Group>(null)\n const { camera, size, viewport } = useThree()\n\n useFrame(() => {\n const g = ref.current\n const b = bounds.current\n\n if (!g || !b) {\n return\n }\n\n const left = b.pageX - window.scrollX\n const top = b.pageY - window.scrollY\n\n tmp.ndc.set(\n ((left + b.width / 2) / size.width) * 2 - 1,\n 1 - ((top + b.height / 2) / size.height) * 2\n )\n\n camera.getWorldDirection(tmp.camDir)\n tmp.plane.setFromNormalAndCoplanarPoint(tmp.camDir, tmp.origin)\n tmp.ray.setFromCamera(tmp.ndc, camera)\n\n const hit = tmp.ray.ray.intersectPlane(tmp.plane, tmp.hit)\n\n if (hit) {\n g.position.copy(hit)\n }\n\n const zoom = (camera as THREE.Camera & { zoom?: number }).zoom ?? 1\n\n g.scale.setScalar(\n Math.min(\n (b.width / size.width) * viewport.width,\n (b.height / size.height) * viewport.height\n ) * (baseZoom > 0 ? zoom / baseZoom : 1)\n )\n })\n\n return <group ref={ref}>{children}</group>\n}\n\nexport function SceneCanvas({\n camera,\n children,\n className,\n contained,\n frameloop = 'always',\n noEvents,\n style\n}: SceneCanvasProps) {\n const [container, setContainer] = useState<HTMLDivElement | null>(null)\n const baseZoom = camera?.zoom ?? 150\n\n const bounds = useBounds(\n contained ? (container?.parentElement ?? null) : null\n )\n\n useEffect(() => {\n const el = contained && !noEvents ? container : null\n\n if (!el) {\n return\n }\n\n const lock = () => (document.body.style.userSelect = 'none')\n const unlock = () => (document.body.style.userSelect = '')\n\n el.addEventListener('pointerdown', lock)\n window.addEventListener('pointerup', unlock)\n\n return () => {\n el.removeEventListener('pointerdown', lock)\n window.removeEventListener('pointerup', unlock)\n }\n }, [container, contained, noEvents])\n\n // Pause the R3F render loop when the tab is hidden. Even on\n // `frameloop=\"always\"` scenes we don't want the GPU running while the\n // user can't see anything — this is the dominant fix for the \"fans\n // crank up after hours of idle\" symptom.\n const [pageHidden, setPageHidden] = useState(\n typeof document !== 'undefined' && document.hidden\n )\n\n useEffect(() => {\n const onVisibility = () => setPageHidden(document.hidden)\n document.addEventListener('visibilitychange', onVisibility)\n\n return () => document.removeEventListener('visibilitychange', onVisibility)\n }, [])\n\n const effectiveFrameloop = pageHidden ? 'never' : frameloop\n\n const cam = useMemo(\n () => ({\n far: camera?.far ?? 100,\n near: camera?.near ?? -100,\n position: camera?.position ?? ([0, 0, 10] as [number, number, number]),\n zoom: baseZoom * (contained ? 1 : 2)\n }),\n [baseZoom, camera, contained]\n )\n\n const canvas = (\n <Canvas\n camera={cam}\n className={className}\n dpr={[1, 2]}\n eventPrefix={contained ? 'client' : 'offset'}\n eventSource={contained ? (container ?? undefined) : undefined}\n frameloop={effectiveFrameloop}\n gl={GL}\n orthographic\n style={\n contained\n ? {\n height: '100dvh',\n inset: 0,\n pointerEvents: 'none',\n position: 'fixed',\n width: '100dvw',\n zIndex: 0,\n ...style\n }\n : { height: '100%', width: '100%', ...style }\n }\n >\n {contained ? (\n <PositionedGroup baseZoom={baseZoom} bounds={bounds}>\n {children()}\n </PositionedGroup>\n ) : (\n children()\n )}\n </Canvas>\n )\n\n return contained ? (\n <Suspense>\n <div\n ref={setContainer}\n style={{\n height: '100%',\n inset: 0,\n pointerEvents: noEvents ? 'none' : 'auto',\n position: 'absolute',\n width: '100%',\n zIndex: 1\n }}\n />\n {canvas}\n </Suspense>\n ) : (\n canvas\n )\n}\n\ninterface SceneCanvasProps {\n camera?: {\n far?: number\n near?: number\n position?: [number, number, number]\n zoom?: number\n }\n children: () => React.ReactNode\n className?: string\n contained?: boolean\n /**\n * R3F frame-loop mode. Defaults to `'always'` for backwards\n * compatibility, but `'demand'` is strongly preferred for static\n * scenes (use `invalidate()` from `useThree` to request frames). The\n * canvas additionally pauses (forces `'never'`) while the document\n * is hidden, regardless of this setting.\n */\n frameloop?: 'always' | 'demand' | 'never'\n noEvents?: boolean\n style?: React.CSSProperties\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tv.d.ts","sourceRoot":"","sources":["../../../src/ui/components/tv.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tv.d.ts","sourceRoot":"","sources":["../../../src/ui/components/tv.tsx"],"names":[],"mappings":"AA2NA,wBAAgB,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAqCvD"}
|