@nous-research/ui 0.11.0 → 0.12.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.
@@ -1,8 +1,22 @@
1
1
  /**
2
2
  * Tiers:
3
- * 0 — no WebGL / software renderer / prefers-reduced-motion
3
+ * 0 — no WebGL / software renderer / prefers-reduced-motion / WebGL ctx creation failed
4
4
  * 1 — low-end GPU (integrated, mobile, or failed perf benchmark)
5
5
  * 2 — capable GPU (discrete / high-end integrated)
6
+ *
7
+ * Detection runs **synchronously** the first time this module is evaluated
8
+ * on the client (see the IIFE at the bottom of the file). That means any
9
+ * consumer reading `$gpuTier` during its first render already sees the
10
+ * post-detection value, so WebGL components can avoid trying to create a
11
+ * `THREE.WebGLRenderer` on hardware where context creation will fail.
12
+ *
13
+ * The previous version ran the probe inside `nanostores`'s `onMount`
14
+ * lifecycle, which fires from a microtask after the first listener
15
+ * subscribes — i.e. after the first React commit. By that point overlay
16
+ * components had already executed `new THREE.WebGLRenderer(...)` against
17
+ * the optimistic default, logged `Error creating WebGL context`, and only
18
+ * unmounted on a follow-up render. Eager module-load detection closes that
19
+ * race.
6
20
  */
7
21
  export declare const $gpuTier: import("nanostores").PreinitializedWritableAtom<GpuTier> & object;
8
22
  export declare function useGpuTier(): GpuTier;
@@ -1 +1 @@
1
- {"version":3,"file":"use-gpu-tier.d.ts","sourceRoot":"","sources":["../../src/hooks/use-gpu-tier.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,mEAAmB,CAAA;AAmHxC,wBAAgB,UAAU,YAEzB;AAED,KAAK,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA"}
1
+ {"version":3,"file":"use-gpu-tier.d.ts","sourceRoot":"","sources":["../../src/hooks/use-gpu-tier.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,QAAQ,mEAAmB,CAAA;AAuIxC,wBAAgB,UAAU,YAEzB;AAED,KAAK,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA"}
@@ -1,49 +1,79 @@
1
1
  'use client';
2
2
  import { useStore } from '@nanostores/react';
3
- import { atom, onMount } from 'nanostores';
3
+ import { atom } from 'nanostores';
4
4
  /**
5
5
  * Tiers:
6
- * 0 — no WebGL / software renderer / prefers-reduced-motion
6
+ * 0 — no WebGL / software renderer / prefers-reduced-motion / WebGL ctx creation failed
7
7
  * 1 — low-end GPU (integrated, mobile, or failed perf benchmark)
8
8
  * 2 — capable GPU (discrete / high-end integrated)
9
+ *
10
+ * Detection runs **synchronously** the first time this module is evaluated
11
+ * on the client (see the IIFE at the bottom of the file). That means any
12
+ * consumer reading `$gpuTier` during its first render already sees the
13
+ * post-detection value, so WebGL components can avoid trying to create a
14
+ * `THREE.WebGLRenderer` on hardware where context creation will fail.
15
+ *
16
+ * The previous version ran the probe inside `nanostores`'s `onMount`
17
+ * lifecycle, which fires from a microtask after the first listener
18
+ * subscribes — i.e. after the first React commit. By that point overlay
19
+ * components had already executed `new THREE.WebGLRenderer(...)` against
20
+ * the optimistic default, logged `Error creating WebGL context`, and only
21
+ * unmounted on a follow-up render. Eager module-load detection closes that
22
+ * race.
9
23
  */
10
24
  export const $gpuTier = atom(2);
11
25
  const SOFTWARE_PATTERNS = /swiftshader|llvmpipe|softpipe|software|microsoft basic/i;
12
26
  const LOW_END_PATTERNS = /intel.*hd|intel.*uhd|intel.*iris|mali|adreno\s?[1-5]|powervr|apple gpu/i;
13
- onMount($gpuTier, () => {
14
- if (typeof window === 'undefined') {
27
+ let detected = false;
28
+ function detectGpuTier() {
29
+ if (detected || typeof window === 'undefined') {
15
30
  return;
16
31
  }
32
+ detected = true;
17
33
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
18
34
  $gpuTier.set(0);
19
35
  return;
20
36
  }
21
- const canvas = document.createElement('canvas');
22
- const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
37
+ let gl = null;
38
+ try {
39
+ const canvas = document.createElement('canvas');
40
+ gl = (canvas.getContext('webgl') ||
41
+ canvas.getContext('experimental-webgl'));
42
+ }
43
+ catch {
44
+ // Some sandboxed / hardened contexts throw on getContext rather than
45
+ // returning null (e.g. certain corporate browser policies). Treat as
46
+ // "no WebGL available".
47
+ $gpuTier.set(0);
48
+ return;
49
+ }
23
50
  if (!gl) {
24
51
  $gpuTier.set(0);
25
52
  return;
26
53
  }
27
- const glCtx = gl;
28
- const ext = glCtx.getExtension('WEBGL_debug_renderer_info');
29
- const renderer = ext
30
- ? glCtx.getParameter(ext.UNMASKED_RENDERER_WEBGL)
31
- : glCtx.getParameter(glCtx.RENDERER);
54
+ const ext = gl.getExtension('WEBGL_debug_renderer_info');
55
+ const renderer = String(ext
56
+ ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL)
57
+ : gl.getParameter(gl.RENDERER));
32
58
  if (SOFTWARE_PATTERNS.test(renderer)) {
33
59
  $gpuTier.set(0);
34
- glCtx.getExtension('WEBGL_lose_context')?.loseContext();
60
+ gl.getExtension('WEBGL_lose_context')?.loseContext();
35
61
  return;
36
62
  }
37
63
  if (LOW_END_PATTERNS.test(renderer)) {
38
64
  $gpuTier.set(1);
39
- glCtx.getExtension('WEBGL_lose_context')?.loseContext();
65
+ gl.getExtension('WEBGL_lose_context')?.loseContext();
40
66
  return;
41
67
  }
42
- runBenchmark(glCtx).then(fps => {
43
- $gpuTier.set(fps < 30 ? 1 : 2);
44
- glCtx.getExtension('WEBGL_lose_context')?.loseContext();
45
- });
46
- });
68
+ $gpuTier.set(2);
69
+ runBenchmark(gl)
70
+ .then(fps => $gpuTier.set(fps < 30 ? 1 : 2))
71
+ .catch(() => $gpuTier.set(1))
72
+ .finally(() => gl?.getExtension('WEBGL_lose_context')?.loseContext());
73
+ }
74
+ if (typeof window !== 'undefined') {
75
+ detectGpuTier();
76
+ }
47
77
  function runBenchmark(gl) {
48
78
  return new Promise(resolve => {
49
79
  const vs = gl.createShader(gl.VERTEX_SHADER);
@@ -1 +1 @@
1
- {"version":3,"file":"use-gpu-tier.js","sourceRoot":"","sources":["../../src/hooks/use-gpu-tier.ts"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useStore } from '@nanostores/react'\nimport { atom, onMount } from 'nanostores'\n\n/**\n * Tiers:\n * 0 — no WebGL / software renderer / prefers-reduced-motion\n * 1 — low-end GPU (integrated, mobile, or failed perf benchmark)\n * 2 — capable GPU (discrete / high-end integrated)\n */\nexport const $gpuTier = atom<GpuTier>(2)\n\nconst SOFTWARE_PATTERNS =\n /swiftshader|llvmpipe|softpipe|software|microsoft basic/i\n\nconst LOW_END_PATTERNS =\n /intel.*hd|intel.*uhd|intel.*iris|mali|adreno\\s?[1-5]|powervr|apple gpu/i\n\nonMount($gpuTier, () => {\n if (typeof window === 'undefined') {\n return\n }\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n $gpuTier.set(0)\n\n return\n }\n\n const canvas = document.createElement('canvas')\n\n const gl =\n canvas.getContext('webgl') || canvas.getContext('experimental-webgl')\n\n if (!gl) {\n $gpuTier.set(0)\n\n return\n }\n\n const glCtx = gl as WebGLRenderingContext\n const ext = glCtx.getExtension('WEBGL_debug_renderer_info')\n\n const renderer = ext\n ? glCtx.getParameter(ext.UNMASKED_RENDERER_WEBGL)\n : glCtx.getParameter(glCtx.RENDERER)\n\n if (SOFTWARE_PATTERNS.test(renderer)) {\n $gpuTier.set(0)\n glCtx.getExtension('WEBGL_lose_context')?.loseContext()\n\n return\n }\n\n if (LOW_END_PATTERNS.test(renderer)) {\n $gpuTier.set(1)\n glCtx.getExtension('WEBGL_lose_context')?.loseContext()\n\n return\n }\n\n runBenchmark(glCtx).then(fps => {\n $gpuTier.set(fps < 30 ? 1 : 2)\n glCtx.getExtension('WEBGL_lose_context')?.loseContext()\n })\n})\n\nfunction runBenchmark(gl: WebGLRenderingContext): Promise<number> {\n return new Promise(resolve => {\n const vs = gl.createShader(gl.VERTEX_SHADER)!\n const fs = gl.createShader(gl.FRAGMENT_SHADER)!\n gl.shaderSource(\n vs,\n 'attribute vec2 a;void main(){gl_Position=vec4(a,0,1);}'\n )\n gl.shaderSource(\n fs,\n 'precision highp float;uniform float t;void main(){float v=0.;for(int i=0;i<64;i++)v+=sin(float(i)*t*.01);gl_FragColor=vec4(v*.001);}'\n )\n gl.compileShader(vs)\n gl.compileShader(fs)\n\n const prog = gl.createProgram()!\n gl.attachShader(prog, vs)\n gl.attachShader(prog, fs)\n gl.linkProgram(prog)\n gl.useProgram(prog)\n\n const buf = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buf)\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n )\n const a = gl.getAttribLocation(prog, 'a')\n gl.enableVertexAttribArray(a)\n gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0)\n\n const uT = gl.getUniformLocation(prog, 't')\n let frames = 0\n const start = performance.now()\n\n const tick = () => {\n gl.uniform1f(uT, frames)\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n gl.finish()\n frames++\n\n if (performance.now() - start < 200) {\n requestAnimationFrame(tick)\n } else {\n const elapsed = performance.now() - start\n gl.deleteProgram(prog)\n gl.deleteShader(vs)\n gl.deleteShader(fs)\n gl.deleteBuffer(buf)\n resolve((frames / elapsed) * 1000)\n }\n }\n\n requestAnimationFrame(tick)\n })\n}\n\nexport function useGpuTier() {\n return useStore($gpuTier)\n}\n\ntype GpuTier = 0 | 1 | 2"]}
1
+ {"version":3,"file":"use-gpu-tier.js","sourceRoot":"","sources":["../../src/hooks/use-gpu-tier.ts"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { useStore } from '@nanostores/react'\nimport { atom } from 'nanostores'\n\n/**\n * Tiers:\n * 0 — no WebGL / software renderer / prefers-reduced-motion / WebGL ctx creation failed\n * 1 — low-end GPU (integrated, mobile, or failed perf benchmark)\n * 2 — capable GPU (discrete / high-end integrated)\n *\n * Detection runs **synchronously** the first time this module is evaluated\n * on the client (see the IIFE at the bottom of the file). That means any\n * consumer reading `$gpuTier` during its first render already sees the\n * post-detection value, so WebGL components can avoid trying to create a\n * `THREE.WebGLRenderer` on hardware where context creation will fail.\n *\n * The previous version ran the probe inside `nanostores`'s `onMount`\n * lifecycle, which fires from a microtask after the first listener\n * subscribes — i.e. after the first React commit. By that point overlay\n * components had already executed `new THREE.WebGLRenderer(...)` against\n * the optimistic default, logged `Error creating WebGL context`, and only\n * unmounted on a follow-up render. Eager module-load detection closes that\n * race.\n */\nexport const $gpuTier = atom<GpuTier>(2)\n\nconst SOFTWARE_PATTERNS =\n /swiftshader|llvmpipe|softpipe|software|microsoft basic/i\n\nconst LOW_END_PATTERNS =\n /intel.*hd|intel.*uhd|intel.*iris|mali|adreno\\s?[1-5]|powervr|apple gpu/i\n\nlet detected = false\n\nfunction detectGpuTier() {\n if (detected || typeof window === 'undefined') {\n return\n }\n\n detected = true\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n $gpuTier.set(0)\n\n return\n }\n\n let gl: null | WebGLRenderingContext = null\n\n try {\n const canvas = document.createElement('canvas')\n gl = (canvas.getContext('webgl') ||\n canvas.getContext('experimental-webgl')) as null | WebGLRenderingContext\n } catch {\n // Some sandboxed / hardened contexts throw on getContext rather than\n // returning null (e.g. certain corporate browser policies). Treat as\n // \"no WebGL available\".\n $gpuTier.set(0)\n\n return\n }\n\n if (!gl) {\n $gpuTier.set(0)\n\n return\n }\n\n const ext = gl.getExtension('WEBGL_debug_renderer_info')\n const renderer = String(\n ext\n ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL)\n : gl.getParameter(gl.RENDERER)\n )\n\n if (SOFTWARE_PATTERNS.test(renderer)) {\n $gpuTier.set(0)\n gl.getExtension('WEBGL_lose_context')?.loseContext()\n\n return\n }\n\n if (LOW_END_PATTERNS.test(renderer)) {\n $gpuTier.set(1)\n gl.getExtension('WEBGL_lose_context')?.loseContext()\n\n return\n }\n\n $gpuTier.set(2)\n\n runBenchmark(gl)\n .then(fps => $gpuTier.set(fps < 30 ? 1 : 2))\n .catch(() => $gpuTier.set(1))\n .finally(() => gl?.getExtension('WEBGL_lose_context')?.loseContext())\n}\n\nif (typeof window !== 'undefined') {\n detectGpuTier()\n}\n\nfunction runBenchmark(gl: WebGLRenderingContext): Promise<number> {\n return new Promise(resolve => {\n const vs = gl.createShader(gl.VERTEX_SHADER)!\n const fs = gl.createShader(gl.FRAGMENT_SHADER)!\n gl.shaderSource(\n vs,\n 'attribute vec2 a;void main(){gl_Position=vec4(a,0,1);}'\n )\n gl.shaderSource(\n fs,\n 'precision highp float;uniform float t;void main(){float v=0.;for(int i=0;i<64;i++)v+=sin(float(i)*t*.01);gl_FragColor=vec4(v*.001);}'\n )\n gl.compileShader(vs)\n gl.compileShader(fs)\n\n const prog = gl.createProgram()!\n gl.attachShader(prog, vs)\n gl.attachShader(prog, fs)\n gl.linkProgram(prog)\n gl.useProgram(prog)\n\n const buf = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, buf)\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n )\n const a = gl.getAttribLocation(prog, 'a')\n gl.enableVertexAttribArray(a)\n gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0)\n\n const uT = gl.getUniformLocation(prog, 't')\n let frames = 0\n const start = performance.now()\n\n const tick = () => {\n gl.uniform1f(uT, frames)\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n gl.finish()\n frames++\n\n if (performance.now() - start < 200) {\n requestAnimationFrame(tick)\n } else {\n const elapsed = performance.now() - start\n gl.deleteProgram(prog)\n gl.deleteShader(vs)\n gl.deleteShader(fs)\n gl.deleteBuffer(buf)\n resolve((frames / elapsed) * 1000)\n }\n }\n\n requestAnimationFrame(tick)\n })\n}\n\nexport function useGpuTier() {\n return useStore($gpuTier)\n}\n\ntype GpuTier = 0 | 1 | 2\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"glitch.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/glitch.tsx"],"names":[],"mappings":"AA2GA,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,kDAwHvD;AAED,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
1
+ {"version":3,"file":"glitch.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/glitch.tsx"],"names":[],"mappings":"AA2GA,wBAAgB,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,kDAmIvD;AAED,UAAU,WAAW;IACnB,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 } from '../../../utils';
8
8
  import { BLEND_MODES } from './blend-modes';
@@ -120,10 +120,20 @@ export function Glitch({ className, style }) {
120
120
  if (!ref.current || !enabled) {
121
121
  return;
122
122
  }
123
- const renderer = new THREE.WebGLRenderer({
124
- alpha: true,
125
- canvas: ref.current
126
- });
123
+ let renderer;
124
+ try {
125
+ renderer = new THREE.WebGLRenderer({
126
+ alpha: true,
127
+ canvas: ref.current
128
+ });
129
+ }
130
+ catch {
131
+ // See note in noise.tsx — eager gpu-tier detection should keep us
132
+ // out of here, but if the driver fails the renderer constructor
133
+ // anyway, downgrade so other overlays stop trying too.
134
+ $gpuTier.set(0);
135
+ return;
136
+ }
127
137
  const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
128
138
  const geo = new THREE.PlaneGeometry(2, 2);
129
139
  const scene = new THREE.Scene();
@@ -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 { 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 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 +1 @@
1
- {"version":3,"file":"greys.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"AAmKA,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,kDAyMrD;AAED,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
1
+ {"version":3,"file":"greys.d.ts","sourceRoot":"","sources":["../../../../src/ui/components/overlays/greys.tsx"],"names":[],"mappings":"AAmKA,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,kDAoNrD;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, 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
6
  import { useSmoothControls } from '../../../hooks/use-smooth-controls';
7
7
  import { cn } from '../../../utils';
8
8
  import { BLEND_MODES } from './blend-modes';
@@ -184,10 +184,20 @@ export function Greys({ className, style }) {
184
184
  if (!canvasRef.current || !enabled) {
185
185
  return;
186
186
  }
187
- const renderer = new THREE.WebGLRenderer({
188
- alpha: true,
189
- canvas: canvasRef.current
190
- });
187
+ let renderer;
188
+ try {
189
+ renderer = new THREE.WebGLRenderer({
190
+ alpha: true,
191
+ canvas: canvasRef.current
192
+ });
193
+ }
194
+ catch {
195
+ // See note in noise.tsx — eager gpu-tier detection should keep us
196
+ // out of here, but if the driver fails the renderer constructor
197
+ // anyway, downgrade so other overlays stop trying too.
198
+ $gpuTier.set(0);
199
+ return;
200
+ }
191
201
  const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
192
202
  const geo = new THREE.PlaneGeometry(2, 2);
193
203
  const [rtSource, rtA, rtB] = [0, 1, 2].map(() => new THREE.WebGLRenderTarget(innerWidth, innerHeight, {
@@ -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 { 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 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 +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,kDAiHrD;AAED,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B"}
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,kDA6HrD;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';
@@ -48,11 +48,22 @@ export function Noise({ className, style }) {
48
48
  if (!canvasRef.current || !enabled) {
49
49
  return;
50
50
  }
51
- const renderer = new THREE.WebGLRenderer({
52
- alpha: true,
53
- canvas: canvasRef.current,
54
- premultipliedAlpha: false
55
- });
51
+ let renderer;
52
+ try {
53
+ renderer = new THREE.WebGLRenderer({
54
+ alpha: true,
55
+ canvas: canvasRef.current,
56
+ premultipliedAlpha: false
57
+ });
58
+ }
59
+ catch {
60
+ // Belt-and-braces: the gpu-tier hook should already have downgraded
61
+ // to 0 before we render, but if a driver fails the renderer
62
+ // constructor anyway (e.g. context loss between probe and use), make
63
+ // sure no other overlay tries again.
64
+ $gpuTier.set(0);
65
+ return;
66
+ }
56
67
  renderer.setClearColor(0x000000, 0);
57
68
  const scene = new THREE.Scene();
58
69
  const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
@@ -1 +1 @@
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 { 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 const cRef = useRef(c)\n cRef.current = c\n\n const enabled = c.enabled && gpuTier > 0\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 premultipliedAlpha: false\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 const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n renderer.setPixelRatio(devicePixelRatio)\n mat.uniforms.uRes.value.set(\n innerWidth * devicePixelRatio,\n innerHeight * devicePixelRatio\n )\n mat.uniforms.uDpr.value = devicePixelRatio\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let raf: number\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 const v = cRef.current\n mat.uniforms.uSize.value = v.size\n mat.uniforms.uDensity.value = v.density\n mat.uniforms.uColor.value = hexToVec3(v.color)\n mat.uniforms.uOpacity.value = v.opacity\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={canvasRef}\n style={{ mixBlendMode: c.blend, ...style }}\n />\n )\n}\n\ninterface NoiseProps {\n className?: string\n style?: React.CSSProperties\n}\n"]}
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 const cRef = useRef(c)\n cRef.current = c\n\n const enabled = c.enabled && gpuTier > 0\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 premultipliedAlpha: false\n })\n } catch {\n // Belt-and-braces: the gpu-tier hook should already have downgraded\n // to 0 before we render, but if a driver fails the renderer\n // constructor anyway (e.g. context loss between probe and use), make\n // sure no other overlay tries again.\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 const resize = () => {\n renderer.setSize(innerWidth, innerHeight)\n renderer.setPixelRatio(devicePixelRatio)\n mat.uniforms.uRes.value.set(\n innerWidth * devicePixelRatio,\n innerHeight * devicePixelRatio\n )\n mat.uniforms.uDpr.value = devicePixelRatio\n }\n\n resize()\n window.addEventListener('resize', resize)\n\n let raf: number\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 const v = cRef.current\n mat.uniforms.uSize.value = v.size\n mat.uniforms.uDensity.value = v.density\n mat.uniforms.uColor.value = hexToVec3(v.color)\n mat.uniforms.uOpacity.value = v.opacity\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={canvasRef}\n style={{ mixBlendMode: c.blend, ...style }}\n />\n )\n}\n\ninterface NoiseProps {\n className?: string\n style?: React.CSSProperties\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nous-research/ui",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "sideEffects": [