@mkbabb/glass-ui 8.0.0 → 9.0.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/aurora.js +371 -349
- package/dist/blob.js +42 -42
- package/dist/{checkbox-BnXuGgJ3.js → checkbox-B1qn65se.js} +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/color.glsl-DTJhdekG.js +34 -0
- package/dist/color.wgsl-BTszLY39.js +398 -0
- package/dist/{command-BuBnYpxF.js → command-tEzAaVY_.js} +1 -1
- package/dist/command.js +1 -1
- package/dist/components/_shared/control.d.ts +0 -1
- package/dist/components/_shared/index.d.ts +0 -1
- package/dist/components/aurora/Aurora.vue.d.ts +1 -0
- package/dist/components/aurora/composables/frameLoop.d.ts +6 -5
- package/dist/components/aurora/composables/runtime.d.ts +26 -1
- package/dist/components/aurora/composables/useAurora.d.ts +28 -0
- package/dist/components/aurora/composables/wgpuSetup.d.ts +1 -1
- package/dist/components/aurora/constants/presets.d.ts +44 -5
- package/dist/components/aurora/index.d.ts +1 -1
- package/dist/components/configurator/Configurator.vue.d.ts +25 -2
- package/dist/components/configurator/ConfiguratorRow.vue.d.ts +4 -2
- package/dist/components/configurator/styles.css +1 -1
- package/dist/components/dock/DockSeparator.vue.d.ts +2 -3
- package/dist/components/dock/GlassDock.vue.d.ts +1 -0
- package/dist/components/dock/composables/dockContext.d.ts +1 -8
- package/dist/components/dock/composables/useDockRun.d.ts +20 -0
- package/dist/components/dock/composables/useDockSearch.d.ts +1 -1
- package/dist/components/dock/composables/useDockShellProps.d.ts +18 -101
- package/dist/components/dock/composables/useDockState.d.ts +2 -9
- package/dist/components/dock/constants.d.ts +15 -0
- package/dist/components/dock/index.d.ts +2 -2
- package/dist/components/dock/styles/controls/icon-button.css +1 -1
- package/dist/components/dock/styles/controls/tab-button.css +1 -1
- package/dist/components/dock/styles/controls/triggers.css +1 -1
- package/dist/components/dock/styles/controls.css +1 -1
- package/dist/components/dock/styles/density.css +1 -1
- package/dist/components/dock/styles/index.css +1 -1
- package/dist/components/dock/styles/layer-group.css +1 -1
- package/dist/components/dock/styles/layers.css +1 -1
- package/dist/components/dock/styles/morph.css +1 -1
- package/dist/components/dock/styles/run.css +1 -0
- package/dist/components/dock/styles/search.css +1 -1
- package/dist/components/dock/styles/shape.css +1 -1
- package/dist/components/dock/styles/shell-regions.css +1 -1
- package/dist/components/dock/styles/shell.css +1 -1
- package/dist/components/fourier-field/FourierField.vue.d.ts +28 -25
- package/dist/components/fourier-field/clock.d.ts +35 -0
- package/dist/components/fourier-field/constants.d.ts +78 -103
- package/dist/components/fourier-field/index.d.ts +3 -28
- package/dist/components/fourier-field/math.d.ts +69 -77
- package/dist/components/fourier-field/renderer/mint.d.ts +50 -0
- package/dist/components/fourier-field/renderer/uniforms.d.ts +84 -0
- package/dist/components/fourier-field/renderer/wgpu.d.ts +28 -0
- package/dist/components/fourier-field/shaders/compute.wgsl.d.ts +1 -0
- package/dist/components/fourier-field/shaders/render.wgsl.d.ts +1 -0
- package/dist/components/fourier-field/useFourierField.d.ts +49 -0
- package/dist/components/handmark/HandMark.vue.d.ts +18 -14
- package/dist/components/handmark/index.d.ts +4 -23
- package/dist/components/handmark/stroke.d.ts +92 -0
- package/dist/composables/dark/darkModeSyncScript.d.ts +19 -0
- package/dist/composables/motion/pointer/pointerFieldMappings.d.ts +0 -41
- package/dist/{components/search/composables → composables/search}/index.d.ts +2 -2
- package/dist/{components/search/composables/fuzzySearchIndex.d.ts → composables/search/match.d.ts} +8 -3
- package/dist/configurator-BHJymdrF.js +339 -0
- package/dist/configurator.js +1 -1
- package/dist/constellation.js +2 -2
- package/dist/control-DJp15L4U.js +7 -0
- package/dist/{dark-z_P5QwqI.js → dark-CLlmo7dD.js} +2 -2
- package/dist/dark-mode-toggle.js +1 -1
- package/dist/dark.js +1 -1
- package/dist/dock.js +712 -486
- package/dist/dom.js +90 -8
- package/dist/easing.js +3 -3
- package/dist/expandable-container-BY1hQXi4.js +142 -0
- package/dist/expandable-container.js +2 -142
- package/dist/fourier-field.js +643 -855
- package/dist/fourier-math.js +6 -6
- package/dist/glass-ui.css +1 -1
- package/dist/glass-ui.js +85 -72
- package/dist/handmark.js +330 -718
- package/dist/index.d.ts +1 -1
- package/dist/labeled-field.js +2 -2
- package/dist/{menu-wLu1XGKn.js → menu-TDMNtZjG.js} +1 -1
- package/dist/menu.js +1 -1
- package/dist/motion-core.js +34 -34
- package/dist/{participation-B0hdsIRo.js → participation-Di4UHbzk.js} +8 -8
- package/dist/{pointerFieldMappings-DP5tla5z.js → pointerFieldMappings-DXwlU5uj.js} +7 -23
- package/dist/{popover-DBMKTPkL.js → popover-C04Rrdcz.js} +1 -1
- package/dist/popover.js +1 -1
- package/dist/{radio-group-Ci8o-pDx.js → radio-group-BNV7PN1O.js} +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/{select-CDgwGH_P.js → select-COox45Kv.js} +1 -1
- package/dist/select.js +1 -1
- package/dist/{slider-gsc8jDIo.js → slider-5ChjjWSR.js} +1 -1
- package/dist/slider.js +1 -1
- package/dist/styles/components.css +1 -1
- package/dist/styles/glass/material.css +1 -1
- package/dist/styles/glass/overlay-plate.css +1 -1
- package/dist/{switch-DxZzDrmV.js → switch-lLkbREB-.js} +1 -1
- package/dist/switch.js +1 -1
- package/dist/{tabs-CYscnq5H.js → tabs-DSJMd1Et.js} +1 -1
- package/dist/tabs.js +1 -1
- package/dist/{toggle-group-11aPGMfE.js → toggle-group-DUcmKnDw.js} +1 -1
- package/dist/toggle-group.js +1 -1
- package/dist/{tooltip-DqKMZ4dn.js → tooltip-BKk2qVDn.js} +1 -1
- package/dist/tooltip.js +1 -1
- package/dist/{resolveCanvasColor-6MCrswTB.js → useCanvas2D-CQRElMyE.js} +1 -11
- package/dist/useResolveTokenColor-B2FfJnd9.js +24 -0
- package/package.json +2 -20
- package/dist/canvas.d.ts +0 -1
- package/dist/canvas.js +0 -2
- package/dist/color.wgsl-B0N3mKMb.js +0 -412
- package/dist/compile-D7VYG3gi.js +0 -19
- package/dist/components/dock/composables/useDockOverflowFit.d.ts +0 -20
- package/dist/components/dock/composables/useDockTouchGate.d.ts +0 -42
- package/dist/components/dock/styles/overflow.css +0 -1
- package/dist/components/fourier-field/composables/fourierFieldGLSetup.d.ts +0 -24
- package/dist/components/fourier-field/composables/fourierFieldWGPUSetup.d.ts +0 -31
- package/dist/components/fourier-field/composables/uniformBridgeWGPU.d.ts +0 -39
- package/dist/components/fourier-field/composables/useFourierField.d.ts +0 -56
- package/dist/components/fourier-field/shaders/fourier-field.compute.wgsl.d.ts +0 -1
- package/dist/components/fourier-field/shaders/fourier-field.glsl.d.ts +0 -4
- package/dist/components/fourier-field/shaders/fourier-field.render.wgsl.d.ts +0 -1
- package/dist/components/fourier-field/shaders/fourier-field.ribbon.d.ts +0 -51
- package/dist/components/handmark/brush.d.ts +0 -269
- package/dist/components/handmark/composables/useHandMark.d.ts +0 -99
- package/dist/components/handmark/constants.d.ts +0 -69
- package/dist/components/handmark/freehand.d.ts +0 -69
- package/dist/components/handmark/geometry.d.ts +0 -62
- package/dist/components/handmark/ink.d.ts +0 -11
- package/dist/components/handmark/noise.d.ts +0 -30
- package/dist/components/handmark/texture.d.ts +0 -39
- package/dist/components/handmark/types.d.ts +0 -70
- package/dist/components/search/SearchBar.vue.d.ts +0 -38
- package/dist/components/search/index.d.ts +0 -8
- package/dist/components/search/searchVariants.d.ts +0 -16
- package/dist/configurator-BoeScnDL.js +0 -311
- package/dist/control-Da4XeT43.js +0 -11
- package/dist/search.d.ts +0 -1
- package/dist/search.js +0 -61
- package/dist/useFuzzySearch-CUnZknpm.js +0 -177
- package/dist/useResolveTokenColor-CspQv_ik.js +0 -107
- /package/dist/{components/search/composables → composables/search}/types.d.ts +0 -0
- /package/dist/{components/search/composables → composables/search}/useFuzzySearch.d.ts +0 -0
package/dist/fourier-field.js
CHANGED
|
@@ -1,104 +1,182 @@
|
|
|
1
|
-
import { n as e } from "./
|
|
2
|
-
import { t } from "./
|
|
3
|
-
import { t as n } from "./
|
|
4
|
-
import { t as r } from "./
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
1
|
+
import { n as e } from "./springPresets-Cbe0Voqg.js";
|
|
2
|
+
import { n as t } from "./useResolveTokenColor-B2FfJnd9.js";
|
|
3
|
+
import { t as n } from "./_plugin-vue_export-helper-B3ysoDQm.js";
|
|
4
|
+
import { t as r } from "./usePointerVelocityField-DsIf7yyq.js";
|
|
5
|
+
import { i } from "./dark-CLlmo7dD.js";
|
|
6
|
+
import { cssToOklch as a, gamutMapStop as o, oklchToLinear as s } from "./color.js";
|
|
7
|
+
import { FOURIER_FIGURES as c, FOURIER_FIGURE_KEYS as l, comp as u, dftFromPoints as d, makeEllipticSpectrum as f, makeHarmonicFigure as p, partialSumAt as m, positionsAt as h } from "./fourier-math.js";
|
|
8
|
+
import { a as g, n as _, r as v } from "./color.wgsl-BTszLY39.js";
|
|
9
|
+
import { a as y } from "./rendererStatus-BxUlBLVy.js";
|
|
10
|
+
import { n as b, t as x } from "./prng-2uS6J_A1.js";
|
|
11
|
+
import { computed as S, createElementBlock as C, createElementVNode as w, defineComponent as T, normalizeClass as E, onMounted as D, onScopeDispose as O, openBlock as k, readonly as A, shallowRef as j, useTemplateRef as M, watch as N } from "vue";
|
|
12
|
+
var P = .5, F = 720;
|
|
13
|
+
function I(e) {
|
|
14
|
+
let t = Infinity, n = Infinity, r = -Infinity, i = -Infinity;
|
|
15
|
+
for (let a = 0; a < F; a++) {
|
|
16
|
+
let [o, s] = m(e, a / F);
|
|
17
|
+
o < t && (t = o), s < n && (n = s), o > r && (r = o), s > i && (i = s);
|
|
18
|
+
}
|
|
19
|
+
return isFinite(t) ? {
|
|
20
|
+
minX: t,
|
|
21
|
+
minY: n,
|
|
22
|
+
maxX: r,
|
|
23
|
+
maxY: i
|
|
24
|
+
} : {
|
|
25
|
+
minX: 0,
|
|
26
|
+
minY: 0,
|
|
27
|
+
maxX: 0,
|
|
28
|
+
maxY: 0
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function L(e) {
|
|
32
|
+
let t = e.find((e) => e.index === 0), n = t ? [t.coefficient[0], t.coefficient[1]] : [0, 0], r = e.filter((e) => e.index !== 0).slice().sort((e, t) => t.amplitude - e.amplitude);
|
|
33
|
+
if (r.length === 0) return R([u(1, .5, 0)], n);
|
|
34
|
+
let i = I(r), a = Math.max(i.maxX - i.minX, 1e-6), o = Math.max(i.maxY - i.minY, 1e-6), s = 856 / Math.hypot(a, o), c = r.filter((e) => 2 * e.amplitude * s >= P);
|
|
35
|
+
return R(c.length > 0 ? c : [r[0]], n);
|
|
36
|
+
}
|
|
37
|
+
function R(e, t) {
|
|
38
|
+
let n = I(e), r = Math.max(n.maxX - n.minX, 1e-6), i = Math.max(n.maxY - n.minY, 1e-6), a = 0;
|
|
39
|
+
for (let t of e) a += t.amplitude;
|
|
40
|
+
return {
|
|
41
|
+
terms: e,
|
|
42
|
+
dc: t,
|
|
43
|
+
halfSpanX: r / 2,
|
|
44
|
+
halfSpanY: i / 2,
|
|
45
|
+
centerX: (n.minX + n.maxX) / 2,
|
|
46
|
+
centerY: (n.minY + n.maxY) / 2,
|
|
47
|
+
diagonal: Math.hypot(r, i),
|
|
48
|
+
chainReach: a
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function z(e, t, n) {
|
|
52
|
+
let r = t / Math.max(e.diagonal, 1e-6), i = 0;
|
|
53
|
+
for (let t of e.terms) 2 * t.amplitude * r >= n && i++;
|
|
54
|
+
return i;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
13
57
|
//#region src/components/fourier-field/constants.ts
|
|
14
|
-
var
|
|
15
|
-
L: .62,
|
|
16
|
-
C: .19,
|
|
17
|
-
h: 34
|
|
18
|
-
}, {
|
|
19
|
-
L: .86,
|
|
20
|
-
C: .06,
|
|
21
|
-
h: 70
|
|
22
|
-
}], te = {
|
|
58
|
+
var B = .1, ee = .22, te = .11, ne = .35, re = .4, ie = .5, ae = .15, V = 1 / 64, H = 1 / 8, U = {
|
|
23
59
|
source: "elliptic",
|
|
24
60
|
harmonics: 6,
|
|
25
|
-
|
|
26
|
-
epicycleArms: 6,
|
|
61
|
+
showMachine: !0,
|
|
27
62
|
rainbowChain: !0,
|
|
28
63
|
trailArc: .43,
|
|
29
|
-
|
|
64
|
+
markStroke: 8,
|
|
65
|
+
inkOffset: .7,
|
|
66
|
+
squash: .55,
|
|
67
|
+
glow: .14,
|
|
30
68
|
intensity: 1,
|
|
31
|
-
|
|
69
|
+
richness: .5,
|
|
32
70
|
speed: 1,
|
|
33
|
-
palette:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
71
|
+
palette: [{
|
|
72
|
+
L: .62,
|
|
73
|
+
C: .19,
|
|
74
|
+
h: 34
|
|
75
|
+
}, {
|
|
76
|
+
L: .86,
|
|
77
|
+
C: .06,
|
|
78
|
+
h: 70
|
|
79
|
+
}],
|
|
80
|
+
respectReducedMotion: !0
|
|
81
|
+
}, W = e("world"), G = 2 * Math.PI / W.response, oe = W.dampingFraction, se = .22, ce = .06, le = ie * G * G;
|
|
82
|
+
function ue() {
|
|
83
|
+
let e = 0, t = 0, n = 0, r = !0;
|
|
84
|
+
function i(e) {
|
|
85
|
+
!Number.isFinite(e) || e === 0 || (n = Math.min(Math.abs(e), le) * Math.sign(e));
|
|
86
|
+
}
|
|
87
|
+
function a(e) {
|
|
88
|
+
if (t === 0 && n === 0) return;
|
|
89
|
+
let r = -G * G * t - 2 * oe * G * n;
|
|
90
|
+
n += r * e, t += n * e, Math.abs(t) < 1e-4 && Math.abs(n) < 1e-4 && (t = 0, n = 0);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
get headT() {
|
|
94
|
+
return e;
|
|
95
|
+
},
|
|
96
|
+
get momentum() {
|
|
97
|
+
return t;
|
|
98
|
+
},
|
|
99
|
+
step(o) {
|
|
100
|
+
if (o.frozen) return t = 0, n = 0, 0;
|
|
101
|
+
let s = Math.min(Math.max(o.dt, 0), .05), c = o.speed / 16;
|
|
102
|
+
return o.engaged ? (c += o.scrubVelocity * ae, r && o.burst >= se ? (r = !1, i(o.burst * 4 * Math.sign(o.scrubVelocity || 1))) : !r && o.burst <= ce && (r = !0)) : r = !0, c = Math.max(0, c + t), e = (e + c * s) % 1, e < 0 && (e += 1), a(s), c;
|
|
103
|
+
},
|
|
104
|
+
set(t) {
|
|
105
|
+
e = (t % 1 + 1) % 1;
|
|
106
|
+
},
|
|
107
|
+
flick(e) {
|
|
108
|
+
i(e);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/components/fourier-field/shaders/compute.wgsl.ts
|
|
114
|
+
var de = "\nconst TAU: f32 = 6.283185307179586;\n\nstruct Phasor {\n // (re, im, index, _pad)\n data: vec4<f32>,\n};\n\nstruct ComputeUniforms {\n // c0: (headT, trailArc, _pad, _pad)\n c0: vec4<f32>,\n // ints: (harmonicN, sampleCount, termCount, _pad)\n ints: vec4<i32>,\n};\n\n@group(0) @binding(0) var<uniform> u: ComputeUniforms;\n@group(0) @binding(1) var<storage, read> phasors: array<Phasor>;\n// curveSamples[i] = (x, y, age, _pad) in MODEL space\n@group(0) @binding(2) var<storage, read_write> curveSamples: array<vec4<f32>>;\n// chainTips[k] = (x, y, _pad, _pad) in MODEL space\n@group(0) @binding(3) var<storage, read_write> chainTips: array<vec4<f32>>;\n\n// The truncated inverse DFT at parameter t over the first n terms — the transcription of\n// math.ts partialSumAt: c += vec2(re*cos - im*sin, re*sin + im*cos), angle = TAU*index*t.\nfn partialSumAt(t: f32, n: i32) -> vec2<f32> {\n var c = vec2<f32>(0.0, 0.0);\n let lim = min(n, i32(arrayLength(&phasors)));\n for (var i = 0; i < lim; i = i + 1) {\n let p = phasors[i].data;\n let angle = TAU * p.z * t;\n let cs = cos(angle);\n let sn = sin(angle);\n c = c + vec2<f32>(p.x * cs - p.y * sn, p.x * sn + p.y * cs);\n }\n return c;\n}\n\n@compute @workgroup_size(64)\nfn cs_main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = i32(gid.x);\n let headT = u.c0.x;\n let trailArc = u.c0.y;\n let harmonicN = u.ints.x;\n let sampleCount = u.ints.y;\n\n // ── The comet body ──\n if (i < sampleCount) {\n let denom = max(f32(sampleCount - 1), 1.0);\n let frac = f32(i) / denom; // 0 = head, 1 = tail\n let age = 1.0 - frac; // 1 = head, 0 = tail\n var t = headT - trailArc * frac;\n t = t - floor(t); // fract -> [0,1)\n let pt = partialSumAt(t, harmonicN);\n curveSamples[i] = vec4<f32>(pt.x, pt.y, age, 0.0);\n }\n\n // ── The chain tips (k = 0..N). chainTips[0] is the origin. ──\n if (i <= harmonicN && i < i32(arrayLength(&chainTips))) {\n let tip = partialSumAt(headT, i);\n chainTips[i] = vec4<f32>(tip.x, tip.y, 0.0, 0.0);\n }\n}\n", fe = `
|
|
115
|
+
// 0 chain · 1 trail · 2 head — a pipeline-overridable constant, three pipelines, one module.
|
|
41
116
|
override LAYER: i32 = 0;
|
|
42
117
|
|
|
118
|
+
// THE SPLICE CONTRACT, honoured. OKLCH_MATRICES_WGSL states it at color.wgsl.ts:52-53 —
|
|
119
|
+
// "PI must be in scope (the consumer defines it first, as the GLSL chunk requires)" — and
|
|
120
|
+
// spends it at :105 folding the OKLCh hue to [0, 2pi). This module splices that chunk
|
|
121
|
+
// below and defined PI nowhere, so every CreateShaderModule on this source failed
|
|
122
|
+
// validation with "unresolved value 'PI'" and the stage painted NOTHING. The two other
|
|
123
|
+
// WGSL primaries carry the same line for the same reason (aurora.wgsl.ts:49,
|
|
124
|
+
// metaball.wgsl.ts:53); this is that house idiom, not a local patch. The CLASS is gated
|
|
125
|
+
// by tests/components/fourier-field/wgsl-splice-contract.test.ts, which resolves every
|
|
126
|
+
// assembled module against the chunks it splices.
|
|
43
127
|
const PI: f32 = 3.141592653589793;
|
|
44
|
-
|
|
45
|
-
// constants.ts and the GL CPU bead path so a cusp resolves identically across both engines.
|
|
128
|
+
|
|
46
129
|
const TANGENT_EPS: f32 = 1e-4;
|
|
47
130
|
const SPEED_REF_HALFWIDTHS: f32 = 6.0;
|
|
48
|
-
// The
|
|
49
|
-
|
|
50
|
-
// two copies are equal so the mid-body floor (RIBBON_HEAD_FLOOR_PX) can never drift off it.
|
|
51
|
-
const RIBBON_TAIL_FRAC: f32 = 0.4;
|
|
52
|
-
const RIBBON_UNDERGLOW_SCALE: f32 = 2.2;
|
|
53
|
-
const RIBBON_UNDERGLOW_ALPHA: f32 = 0.16;
|
|
131
|
+
// The trail's taper: the mark keeps this fraction of its width at the oldest tail.
|
|
132
|
+
const TAIL_TAPER: f32 = 0.55;
|
|
54
133
|
|
|
55
|
-
// ── Render uniforms (the typed-struct source-of-truth — see uniformBridgeWGPU.ts) ──
|
|
56
134
|
struct RenderUniforms {
|
|
57
|
-
// r0: (centerX, centerY, scale, aspect)
|
|
135
|
+
// r0: (centerX, centerY, scale, aspect)
|
|
58
136
|
r0: vec4<f32>,
|
|
59
|
-
// r1: (
|
|
137
|
+
// r1: (markHalf, inkOffsetStrokes, scaffoldFrac, edgeMargin)
|
|
60
138
|
r1: vec4<f32>,
|
|
61
|
-
// r2: (
|
|
139
|
+
// r2: (peakAlpha, glow, squash, trailFadeExp)
|
|
62
140
|
r2: vec4<f32>,
|
|
63
|
-
// r3: (
|
|
141
|
+
// r3: (trailFloor, hueSweep, ringStrokeModel, showMachine)
|
|
64
142
|
r3: vec4<f32>,
|
|
65
|
-
//
|
|
143
|
+
// ink: (linear rgb, rainbowChain)
|
|
144
|
+
ink: vec4<f32>,
|
|
145
|
+
// head: (linear rgb, _pad)
|
|
146
|
+
head: vec4<f32>,
|
|
147
|
+
// ints: (sampleCount, lutSize, chainCount, _pad)
|
|
66
148
|
ints: vec4<i32>,
|
|
67
|
-
//
|
|
68
|
-
|
|
149
|
+
// the CPU-resolved linear-sRGB ramp — the length is the TS constant, not a second copy
|
|
150
|
+
lut: array<vec4<f32>, 16>,
|
|
69
151
|
};
|
|
70
152
|
|
|
71
153
|
@group(0) @binding(0) var<uniform> u: RenderUniforms;
|
|
72
|
-
// curveSamples[i] = (x, y, age, _pad) in MODEL space — the render VERTEX-PULLS these.
|
|
73
154
|
@group(0) @binding(1) var<storage, read> curveSamples: array<vec4<f32>>;
|
|
74
|
-
// chainTips[k] = (x, y, _pad, _pad) in MODEL space.
|
|
75
155
|
@group(0) @binding(2) var<storage, read> chainTips: array<vec4<f32>>;
|
|
76
156
|
|
|
157
|
+
${_}
|
|
77
158
|
${v}
|
|
78
|
-
${b}
|
|
79
159
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
let n =
|
|
84
|
-
let ft = clamp(t, 0.0, 1.0) * (n - 1
|
|
160
|
+
// Read the CPU-resolved ramp. No colour-space conversion happens here — the LUT already
|
|
161
|
+
// carries the chroma floor and the gamut map.
|
|
162
|
+
fn sampleRamp(t: f32) -> vec3<f32> {
|
|
163
|
+
let n = u.ints.y;
|
|
164
|
+
let ft = clamp(t, 0.0, 1.0) * f32(n - 1);
|
|
85
165
|
let i0 = i32(floor(ft));
|
|
86
|
-
let i1 = min(i0 + 1,
|
|
87
|
-
|
|
88
|
-
let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i0].rgb);
|
|
89
|
-
let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i1].rgb);
|
|
90
|
-
return oklabToLinearSrgb(mix(labA, labB, f));
|
|
166
|
+
let i1 = min(i0 + 1, n - 1);
|
|
167
|
+
return mix(u.lut[i0].rgb, u.lut[i1].rgb, ft - f32(i0));
|
|
91
168
|
}
|
|
92
169
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
170
|
+
// The chain's hue sweep, taken ONCE PER INSTANCE in the vertex stage: the ramp entry for
|
|
171
|
+
// this arm, rotated about the palette anchor by ±hueSweep. Anchored warm, the sweep is
|
|
172
|
+
// bounded by its own arithmetic — it cannot arrive anywhere the palette is not.
|
|
173
|
+
fn chainTint(seg: f32) -> vec3<f32> {
|
|
174
|
+
let base = sampleRamp(seg * 0.6);
|
|
175
|
+
if (u.ink.w < 0.5) { return base; }
|
|
176
|
+
let lab = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * base);
|
|
97
177
|
let lch = oklabToOklch(lab);
|
|
98
|
-
let
|
|
99
|
-
|
|
100
|
-
let lifted = vec3<f32>(0.66, max(lch.y, 0.14), h);
|
|
101
|
-
return oklabToLinearSrgb(oklchToOklab(lifted));
|
|
178
|
+
let swept = vec3<f32>(lch.x, lch.y, lch.z + mix(-u.r3.y, u.r3.y, clamp(seg, 0.0, 1.0)));
|
|
179
|
+
return oklabToLinearSrgb(oklchToOklab(swept));
|
|
102
180
|
}
|
|
103
181
|
|
|
104
182
|
fn segDist(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
|
|
@@ -108,10 +186,10 @@ fn segDist(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
|
|
|
108
186
|
return length(pa - ba * h);
|
|
109
187
|
}
|
|
110
188
|
|
|
111
|
-
// The head travel frame +
|
|
189
|
+
// The head's travel frame + its volume-preserving anisotropic metric.
|
|
112
190
|
struct HeadFrame { T: vec2<f32>, sHat: f32, };
|
|
113
|
-
fn headFrame(head: vec2<f32>,
|
|
114
|
-
let d = head -
|
|
191
|
+
fn headFrame(head: vec2<f32>, back: vec2<f32>, halfW: f32) -> HeadFrame {
|
|
192
|
+
let d = head - back;
|
|
115
193
|
let s = length(d);
|
|
116
194
|
var out: HeadFrame;
|
|
117
195
|
if (s <= TANGENT_EPS) {
|
|
@@ -120,8 +198,7 @@ fn headFrame(head: vec2<f32>, headBack: vec2<f32>, halfW: f32) -> HeadFrame {
|
|
|
120
198
|
return out;
|
|
121
199
|
}
|
|
122
200
|
out.T = d / s;
|
|
123
|
-
|
|
124
|
-
out.sHat = clamp(s / refScale, 0.0, 1.0);
|
|
201
|
+
out.sHat = clamp(s / max(halfW * SPEED_REF_HALFWIDTHS, 1e-6), 0.0, 1.0);
|
|
125
202
|
return out;
|
|
126
203
|
}
|
|
127
204
|
|
|
@@ -129,19 +206,9 @@ fn headAniso(p: vec2<f32>, head: vec2<f32>, fr: HeadFrame, k: f32) -> f32 {
|
|
|
129
206
|
let g = 1.0 + k * fr.sHat;
|
|
130
207
|
let n = vec2<f32>(-fr.T.y, fr.T.x);
|
|
131
208
|
let rel = p - head;
|
|
132
|
-
|
|
133
|
-
let across = dot(rel, n) * g;
|
|
134
|
-
return length(vec2<f32>(along, across));
|
|
209
|
+
return length(vec2<f32>(dot(rel, fr.T) / g, dot(rel, n) * g));
|
|
135
210
|
}
|
|
136
211
|
|
|
137
|
-
// The cel ink lags behind the travel — the SAME −T·halfW·1.4 offset both engines apply (the
|
|
138
|
-
// head frame is read straight off the compute-filled curveSamples[0]/[1], parity by construction).
|
|
139
|
-
fn celOffset(halfW: f32) -> vec2<f32> {
|
|
140
|
-
let fr = headFrame(curveSamples[0].xy, curveSamples[1].xy, halfW);
|
|
141
|
-
return -fr.T * halfW * 1.4;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// The unit quad as two triangles (6 verts) in [0,1]² — the instanced vertex expands it.
|
|
145
212
|
fn quadCorner(vi: u32) -> vec2<f32> {
|
|
146
213
|
var c = array<vec2<f32>, 6>(
|
|
147
214
|
vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0),
|
|
@@ -152,10 +219,12 @@ fn quadCorner(vi: u32) -> vec2<f32> {
|
|
|
152
219
|
|
|
153
220
|
struct VSOut {
|
|
154
221
|
@builtin(position) pos: vec4<f32>,
|
|
155
|
-
@location(0) p: vec2<f32>,
|
|
222
|
+
@location(0) p: vec2<f32>,
|
|
156
223
|
@location(1) a: vec2<f32>,
|
|
157
224
|
@location(2) b: vec2<f32>,
|
|
158
|
-
|
|
225
|
+
// (age, strokeHalf, drawRing)
|
|
226
|
+
@location(3) seg: vec3<f32>,
|
|
227
|
+
@location(4) @interpolate(flat) tint: vec3<f32>,
|
|
159
228
|
};
|
|
160
229
|
|
|
161
230
|
@vertex
|
|
@@ -164,54 +233,44 @@ fn vs_main(@builtin(vertex_index) vi: u32, @builtin(instance_index) inst: u32) -
|
|
|
164
233
|
let center = u.r0.xy;
|
|
165
234
|
let scale = max(u.r0.z, 1e-6);
|
|
166
235
|
let aspect = max(u.r0.w, 1e-4);
|
|
167
|
-
let
|
|
168
|
-
let margin = u.
|
|
169
|
-
|
|
170
|
-
var a
|
|
171
|
-
var b
|
|
172
|
-
var strokeHalf
|
|
173
|
-
var age
|
|
174
|
-
var
|
|
175
|
-
var
|
|
176
|
-
var
|
|
236
|
+
let markHalf = u.r1.x;
|
|
237
|
+
let margin = u.r1.w;
|
|
238
|
+
|
|
239
|
+
var a = vec2<f32>(0.0);
|
|
240
|
+
var b = vec2<f32>(0.0);
|
|
241
|
+
var strokeHalf = markHalf;
|
|
242
|
+
var age = 0.0;
|
|
243
|
+
var drawRing = 0.0;
|
|
244
|
+
var tint = vec3<f32>(0.0);
|
|
245
|
+
var isCapsule = true;
|
|
246
|
+
var ext = markHalf;
|
|
177
247
|
|
|
178
248
|
if (LAYER == 0) {
|
|
179
|
-
//
|
|
249
|
+
// CHAIN — the AABB around this arm's own orbit (radius = |b − a| = |c_k|).
|
|
250
|
+
a = chainTips[inst].xy;
|
|
251
|
+
b = chainTips[inst + 1u].xy;
|
|
252
|
+
let radius = length(b - a);
|
|
253
|
+
// THE RING LAW, asked of the live stage: a circle narrower than its own line is a blob.
|
|
254
|
+
if (2.0 * radius >= u.r3.z) { drawRing = 1.0; }
|
|
255
|
+
strokeHalf = markHalf * u.r1.z;
|
|
256
|
+
tint = chainTint(f32(inst) / max(f32(u.ints.z) - 1.0, 1.0));
|
|
257
|
+
ext = radius + strokeHalf * 2.0;
|
|
258
|
+
isCapsule = false;
|
|
259
|
+
} else if (LAYER == 1) {
|
|
260
|
+
// TRAIL — the curve capsule, padded for the ink's own offset.
|
|
180
261
|
a = curveSamples[inst].xy;
|
|
181
262
|
b = curveSamples[inst + 1u].xy;
|
|
182
263
|
age = max(curveSamples[inst].z, curveSamples[inst + 1u].z);
|
|
183
|
-
|
|
264
|
+
tint = sampleRamp(1.0 - age);
|
|
265
|
+
ext = markHalf * (1.0 + 2.0 * max(u.r1.y, 0.0));
|
|
184
266
|
isCapsule = true;
|
|
185
|
-
} else
|
|
186
|
-
//
|
|
187
|
-
a = chainTips[inst].xy;
|
|
188
|
-
b = chainTips[inst + 1u].xy;
|
|
189
|
-
arg2 = f32(inst) / max(f32(u.ints.y - 1), 1.0);
|
|
190
|
-
ext = length(b - a) + halfW * 0.7;
|
|
191
|
-
isCapsule = false;
|
|
192
|
-
} else if (LAYER == 2) {
|
|
193
|
-
// HEAD — the comet head at curveSamples[0], AABB by the halo radius.
|
|
267
|
+
} else {
|
|
268
|
+
// HEAD — centred on the newest curve sample; the AABB is the halo.
|
|
194
269
|
a = curveSamples[0].xy;
|
|
195
270
|
b = curveSamples[1].xy;
|
|
196
|
-
|
|
271
|
+
tint = u.head.rgb;
|
|
272
|
+
ext = markHalf * 5.0;
|
|
197
273
|
isCapsule = false;
|
|
198
|
-
} else if (LAYER == 3) {
|
|
199
|
-
// CEL-ROPE — the curve capsule, offset opposite travel; full-width ink.
|
|
200
|
-
let off = celOffset(halfW);
|
|
201
|
-
a = curveSamples[inst].xy + off;
|
|
202
|
-
b = curveSamples[inst + 1u].xy + off;
|
|
203
|
-
arg2 = 1.0;
|
|
204
|
-
ext = halfW;
|
|
205
|
-
isCapsule = true;
|
|
206
|
-
} else {
|
|
207
|
-
// CEL-ARM (LAYER == 4) — the chain capsule, offset; the narrower arm ink (0.55·halfW).
|
|
208
|
-
let off = celOffset(halfW);
|
|
209
|
-
a = chainTips[inst].xy + off;
|
|
210
|
-
b = chainTips[inst + 1u].xy + off;
|
|
211
|
-
strokeHalf = halfW * 0.55;
|
|
212
|
-
arg2 = 0.7;
|
|
213
|
-
ext = halfW * 0.55;
|
|
214
|
-
isCapsule = true;
|
|
215
274
|
}
|
|
216
275
|
ext = ext + margin;
|
|
217
276
|
|
|
@@ -222,20 +281,18 @@ fn vs_main(@builtin(vertex_index) vi: u32, @builtin(instance_index) inst: u32) -
|
|
|
222
281
|
var dir = vec2<f32>(1.0, 0.0);
|
|
223
282
|
if (len > 1e-6) { dir = d / len; }
|
|
224
283
|
let perp = vec2<f32>(-dir.y, dir.x);
|
|
225
|
-
|
|
226
|
-
pos = along + perp * (corner.y * 2.0 - 1.0) * ext;
|
|
284
|
+
pos = mix(a - dir * ext, b + dir * ext, corner.x) + perp * (corner.y * 2.0 - 1.0) * ext;
|
|
227
285
|
} else {
|
|
228
286
|
pos = a + (corner * 2.0 - vec2<f32>(1.0)) * ext;
|
|
229
287
|
}
|
|
230
288
|
|
|
231
|
-
let clipX = (pos.x - center.x) * scale / aspect;
|
|
232
|
-
let clipY = (pos.y - center.y) * scale;
|
|
233
289
|
var out: VSOut;
|
|
234
|
-
out.pos = vec4<f32>(
|
|
290
|
+
out.pos = vec4<f32>((pos.x - center.x) * scale / aspect, (pos.y - center.y) * scale, 0.0, 1.0);
|
|
235
291
|
out.p = pos;
|
|
236
292
|
out.a = a;
|
|
237
293
|
out.b = b;
|
|
238
|
-
out.
|
|
294
|
+
out.seg = vec3<f32>(age, strokeHalf, drawRing);
|
|
295
|
+
out.tint = tint;
|
|
239
296
|
return out;
|
|
240
297
|
}
|
|
241
298
|
|
|
@@ -243,270 +300,223 @@ fn vs_main(@builtin(vertex_index) vi: u32, @builtin(instance_index) inst: u32) -
|
|
|
243
300
|
fn fs_main(in: VSOut) -> @location(0) vec4<f32> {
|
|
244
301
|
let p = in.p;
|
|
245
302
|
let aa = max(fwidth(p.x) + fwidth(p.y), 1e-5) * 0.75;
|
|
246
|
-
let peak = u.
|
|
247
|
-
let
|
|
248
|
-
let
|
|
249
|
-
let
|
|
250
|
-
let
|
|
251
|
-
let
|
|
252
|
-
let
|
|
253
|
-
let
|
|
254
|
-
let age = in.segData.x;
|
|
255
|
-
let arg2 = in.segData.z;
|
|
303
|
+
let peak = u.r2.x;
|
|
304
|
+
let glow = u.r2.y;
|
|
305
|
+
let squash = u.r2.z;
|
|
306
|
+
let fadeExp = u.r2.w;
|
|
307
|
+
let trailFloor = u.r3.x;
|
|
308
|
+
let markHalf = u.r1.x;
|
|
309
|
+
let strokeHalf = in.seg.y;
|
|
310
|
+
let age = in.seg.x;
|
|
256
311
|
let a = in.a;
|
|
257
312
|
let b = in.b;
|
|
258
313
|
|
|
259
314
|
if (LAYER == 0) {
|
|
260
|
-
// ──
|
|
261
|
-
let d = segDist(p, a, b);
|
|
262
|
-
let ribbonHalf = halfW * (RIBBON_TAIL_FRAC + (1.0 - RIBBON_TAIL_FRAC) * age);
|
|
263
|
-
let lin = samplePaletteLin(1.0 - age * 0.4);
|
|
264
|
-
let rgb = clamp(linearToSrgb(lin), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
265
|
-
let glowHalf = ribbonHalf * RIBBON_UNDERGLOW_SCALE;
|
|
266
|
-
let glowCover = 1.0 - smoothstep(glowHalf, glowHalf + aa * 3.0, d);
|
|
267
|
-
let ga = peak * RIBBON_UNDERGLOW_ALPHA * pow(age, fadeExp) * glowCover;
|
|
268
|
-
let cover = 1.0 - smoothstep(ribbonHalf, ribbonHalf + aa, d);
|
|
269
|
-
let ca = max(peak * pow(age, fadeExp), peak * trailFloor) * cover;
|
|
270
|
-
let outA = ca + ga * (1.0 - ca);
|
|
271
|
-
return vec4<f32>(rgb * outA, outA);
|
|
272
|
-
} else if (LAYER == 1) {
|
|
273
|
-
// ── EPICYCLE — orbit RING + ARM + joint DOT union (MAX-blended, no join seam) ──
|
|
274
|
-
let lin = chainColorLin(arg2, rainbow);
|
|
275
|
-
let rgb = clamp(linearToSrgb(lin), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
315
|
+
// ── THE MACHINE — ring (conditionally), arm, joint dot; one scaffold rung ──
|
|
276
316
|
let radius = length(b - a);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
let
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
let
|
|
291
|
-
let
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
let
|
|
296
|
-
let
|
|
297
|
-
|
|
298
|
-
let
|
|
299
|
-
|
|
300
|
-
let
|
|
301
|
-
|
|
302
|
-
|
|
317
|
+
var m = 0.0;
|
|
318
|
+
if (in.seg.z > 0.5) {
|
|
319
|
+
let dRing = abs(length(p - a) - radius);
|
|
320
|
+
m = max(m, 1.0 - smoothstep(strokeHalf, strokeHalf + aa, dRing));
|
|
321
|
+
}
|
|
322
|
+
m = max(m, 1.0 - smoothstep(strokeHalf, strokeHalf + aa, segDist(p, a, b)));
|
|
323
|
+
// The joint dot is the mark's own diameter — the machine's one solid rung.
|
|
324
|
+
m = max(m, 1.0 - smoothstep(markHalf, markHalf + aa, length(p - a)));
|
|
325
|
+
let alpha = clamp(m, 0.0, 1.0) * peak;
|
|
326
|
+
let rgb = clamp(linearToSrgb(in.tint), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
327
|
+
return vec4<f32>(rgb * alpha, alpha);
|
|
328
|
+
} else if (LAYER == 1) {
|
|
329
|
+
// ── THE CURVE — ink under mark, composited at α1, then ONE envelope ──
|
|
330
|
+
let taper = TAIL_TAPER + (1.0 - TAIL_TAPER) * age;
|
|
331
|
+
let half = markHalf * taper;
|
|
332
|
+
// The ink rides THIS segment's own tangent, opposite the travel: the head runs from
|
|
333
|
+
// b toward a, so the ink lands behind at (b − a).
|
|
334
|
+
var dir = vec2<f32>(1.0, 0.0);
|
|
335
|
+
let d = b - a;
|
|
336
|
+
let len = length(d);
|
|
337
|
+
if (len > 1e-6) { dir = d / len; }
|
|
338
|
+
let off = dir * (markHalf * 2.0 * u.r1.y);
|
|
339
|
+
|
|
340
|
+
let aMark = 1.0 - smoothstep(half, half + aa, segDist(p, a, b));
|
|
341
|
+
let aInk = 1.0 - smoothstep(half, half + aa, segDist(p, a + off, b + off));
|
|
342
|
+
|
|
343
|
+
let markRgb = clamp(linearToSrgb(in.tint), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
344
|
+
let inkRgb = clamp(linearToSrgb(u.ink.rgb), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
345
|
+
|
|
346
|
+
// Mark OVER ink, both fully opaque where they cover — the pair, then the envelope.
|
|
347
|
+
let aPair = aMark + aInk * (1.0 - aMark);
|
|
348
|
+
let rgbPair = markRgb * aMark + inkRgb * aInk * (1.0 - aMark);
|
|
349
|
+
let env = peak * max(pow(max(age, 0.0), fadeExp), trailFloor);
|
|
350
|
+
return vec4<f32>(rgbPair * env, aPair * env);
|
|
303
351
|
} else {
|
|
304
|
-
// ──
|
|
305
|
-
let
|
|
306
|
-
let
|
|
307
|
-
let
|
|
308
|
-
let
|
|
309
|
-
|
|
352
|
+
// ── THE HEAD — palette-lifted core over its own halo. Light-led, never white. ──
|
|
353
|
+
let fr = headFrame(a, b, markHalf);
|
|
354
|
+
let dHead = headAniso(p, a, fr, squash);
|
|
355
|
+
let coreR = markHalf * 1.5;
|
|
356
|
+
let haloR = coreR * 3.0;
|
|
357
|
+
let rgb = clamp(linearToSrgb(in.tint), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
358
|
+
let halo = (1.0 - smoothstep(0.0, haloR, dHead)) * glow;
|
|
359
|
+
let core = (1.0 - smoothstep(coreR, coreR + aa, dHead)) * peak;
|
|
360
|
+
let alpha = clamp(max(core, halo), 0.0, 1.0);
|
|
361
|
+
return vec4<f32>(rgb * alpha, alpha);
|
|
310
362
|
}
|
|
311
363
|
}
|
|
312
|
-
`,
|
|
313
|
-
trail: 0,
|
|
314
|
-
epicycle: 1,
|
|
315
|
-
head: 2,
|
|
316
|
-
"cel-rope": 3,
|
|
317
|
-
"cel-arm": 4
|
|
318
|
-
};
|
|
319
|
-
function ie(e) {
|
|
320
|
-
let t = Math.max(0, Math.floor(e.sampleCount) - 1), n = e.showEpicycles ? Math.max(0, Math.floor(e.armCount)) : 0, r = e.celGain > .001, i = [];
|
|
321
|
-
return r && t > 0 && i.push({
|
|
322
|
-
kind: "cel-rope",
|
|
323
|
-
instanceCount: t,
|
|
324
|
-
blend: "over"
|
|
325
|
-
}), r && n > 0 && i.push({
|
|
326
|
-
kind: "cel-arm",
|
|
327
|
-
instanceCount: n,
|
|
328
|
-
blend: "over"
|
|
329
|
-
}), n > 0 && i.push({
|
|
330
|
-
kind: "epicycle",
|
|
331
|
-
instanceCount: n,
|
|
332
|
-
blend: "max"
|
|
333
|
-
}), t > 0 && i.push({
|
|
334
|
-
kind: "trail",
|
|
335
|
-
instanceCount: t,
|
|
336
|
-
blend: "over"
|
|
337
|
-
}), i.push({
|
|
338
|
-
kind: "head",
|
|
339
|
-
instanceCount: 1,
|
|
340
|
-
blend: "over"
|
|
341
|
-
}), i;
|
|
342
|
-
}
|
|
343
|
-
var ae = new Float32Array([
|
|
344
|
-
0,
|
|
345
|
-
0,
|
|
346
|
-
1,
|
|
347
|
-
0,
|
|
348
|
-
0,
|
|
349
|
-
1,
|
|
350
|
-
1,
|
|
351
|
-
1
|
|
352
|
-
]), oe = 32, G = {
|
|
364
|
+
`, pe = 32, K = {
|
|
353
365
|
c0: 0,
|
|
354
366
|
ints: 4
|
|
355
367
|
};
|
|
356
|
-
function
|
|
357
|
-
let e = /* @__PURE__ */ new ArrayBuffer(
|
|
368
|
+
function q() {
|
|
369
|
+
let e = /* @__PURE__ */ new ArrayBuffer(pe);
|
|
358
370
|
return {
|
|
359
371
|
buffer: e,
|
|
360
372
|
f32: new Float32Array(e),
|
|
361
373
|
i32: new Int32Array(e)
|
|
362
374
|
};
|
|
363
375
|
}
|
|
364
|
-
function
|
|
365
|
-
let { f32:
|
|
366
|
-
return
|
|
376
|
+
function me(e, t, n, r, i, a) {
|
|
377
|
+
let { f32: o, i32: s } = e;
|
|
378
|
+
return o[K.c0 + 0] = t, o[K.c0 + 1] = n, o[K.c0 + 2] = 0, o[K.c0 + 3] = 0, s[K.ints + 0] = r, s[K.ints + 1] = i, s[K.ints + 2] = a, s[K.ints + 3] = 0, e;
|
|
367
379
|
}
|
|
368
|
-
var
|
|
380
|
+
var he = 368, J = {
|
|
369
381
|
r0: 0,
|
|
370
382
|
r1: 4,
|
|
371
383
|
r2: 8,
|
|
372
384
|
r3: 12,
|
|
373
|
-
|
|
374
|
-
|
|
385
|
+
ink: 16,
|
|
386
|
+
head: 20,
|
|
387
|
+
ints: 24,
|
|
388
|
+
lut: 28
|
|
375
389
|
};
|
|
376
390
|
function Y() {
|
|
377
|
-
let e = new ArrayBuffer(
|
|
391
|
+
let e = new ArrayBuffer(he);
|
|
378
392
|
return {
|
|
379
393
|
buffer: e,
|
|
380
394
|
f32: new Float32Array(e),
|
|
381
395
|
i32: new Int32Array(e)
|
|
382
396
|
};
|
|
383
397
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
let o = g(a, e / 720), [s, c] = o[o.length - 1];
|
|
388
|
-
s < t && (t = s), c < n && (n = c), s > r && (r = s), c > i && (i = c);
|
|
389
|
-
}
|
|
390
|
-
if (!isFinite(t)) return {
|
|
391
|
-
centerX: 0,
|
|
392
|
-
centerY: 0,
|
|
393
|
-
scale: 1
|
|
394
|
-
};
|
|
395
|
-
let o = Math.max(.001, r - t), s = Math.max(.001, i - n), c = 2 * .82 / Math.max(o, s);
|
|
398
|
+
var ge = .82;
|
|
399
|
+
function _e(e, t) {
|
|
400
|
+
let n = Math.max(e.halfSpanX, e.halfSpanY, 1e-6), r = t ? e.chainReach : 0, i = Math.max(n, r, 1e-6);
|
|
396
401
|
return {
|
|
397
|
-
centerX:
|
|
398
|
-
centerY:
|
|
399
|
-
scale:
|
|
402
|
+
centerX: e.centerX,
|
|
403
|
+
centerY: e.centerY,
|
|
404
|
+
scale: ge / i
|
|
400
405
|
};
|
|
401
406
|
}
|
|
402
|
-
function
|
|
403
|
-
let r = Math.max(
|
|
404
|
-
return
|
|
407
|
+
function X(e, t, n) {
|
|
408
|
+
let r = Math.max(n, 1) / 2;
|
|
409
|
+
return e / Math.max(t, 1e-6) / r;
|
|
405
410
|
}
|
|
406
|
-
function
|
|
407
|
-
let
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
411
|
+
function ve(e, t, n) {
|
|
412
|
+
let r = t.h - e.h;
|
|
413
|
+
for (; r > 180;) r -= 360;
|
|
414
|
+
for (; r < -180;) r += 360;
|
|
415
|
+
return {
|
|
416
|
+
L: e.L + (t.L - e.L) * n,
|
|
417
|
+
C: e.C + (t.C - e.C) * n,
|
|
418
|
+
h: e.h + r * n
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function Z(e) {
|
|
422
|
+
let t = e.length > 0 ? e.slice(0, 4) : [], n = t.length > 0 ? t : [{
|
|
423
|
+
L: .62,
|
|
424
|
+
C: .19,
|
|
425
|
+
h: 34
|
|
426
|
+
}], r = /* @__PURE__ */ new Float32Array(64);
|
|
427
|
+
for (let e = 0; e < 16; e++) {
|
|
428
|
+
let t = e / 15 * (n.length - 1), i = Math.min(Math.floor(t), n.length - 1), a = Math.min(i + 1, n.length - 1), c = ve(n[i], n[a], t - i), l = s(o({
|
|
429
|
+
L: c.L,
|
|
430
|
+
C: Math.max(c.C, B),
|
|
431
|
+
h: c.h
|
|
432
|
+
}));
|
|
433
|
+
r[e * 4 + 0] = l[0], r[e * 4 + 1] = l[1], r[e * 4 + 2] = l[2], r[e * 4 + 3] = 0;
|
|
414
434
|
}
|
|
435
|
+
let i = n[0];
|
|
436
|
+
return {
|
|
437
|
+
lut: r,
|
|
438
|
+
ink: s(o({
|
|
439
|
+
L: Math.max(0, i.L - ee),
|
|
440
|
+
C: i.C,
|
|
441
|
+
h: i.h
|
|
442
|
+
})),
|
|
443
|
+
head: s(o({
|
|
444
|
+
L: Math.min(1, i.L + te),
|
|
445
|
+
C: i.C,
|
|
446
|
+
h: i.h
|
|
447
|
+
}))
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
function ye(e, t) {
|
|
451
|
+
let { f32: n, i32: r } = e;
|
|
452
|
+
n[J.r0 + 0] = t.fit.centerX, n[J.r0 + 1] = t.fit.centerY, n[J.r0 + 2] = t.fit.scale, n[J.r0 + 3] = t.aspect, n[J.r1 + 0] = t.markHalfModel, n[J.r1 + 1] = t.inkOffsetStrokes, n[J.r1 + 2] = t.scaffoldFrac, n[J.r1 + 3] = t.edgeMargin, n[J.r2 + 0] = Math.min(Math.max(t.peakAlpha, 0), 1), n[J.r2 + 1] = t.glow, n[J.r2 + 2] = t.squash, n[J.r2 + 3] = t.trailFadeExp, n[J.r3 + 0] = t.trailFloor, n[J.r3 + 1] = t.hueSweep, n[J.r3 + 2] = t.ringStrokeModel, n[J.r3 + 3] = +!!t.showMachine, n[J.ink + 0] = t.ramp.ink[0], n[J.ink + 1] = t.ramp.ink[1], n[J.ink + 2] = t.ramp.ink[2], n[J.ink + 3] = +!!t.rainbowChain, n[J.head + 0] = t.ramp.head[0], n[J.head + 1] = t.ramp.head[1], n[J.head + 2] = t.ramp.head[2], n[J.head + 3] = 0, r[J.ints + 0] = t.sampleCount, r[J.ints + 1] = 16, r[J.ints + 2] = t.chainCount, r[J.ints + 3] = 0;
|
|
453
|
+
for (let e = 0; e < 64; e++) n[J.lut + e] = t.ramp.lut[e];
|
|
415
454
|
return e;
|
|
416
455
|
}
|
|
417
|
-
function
|
|
418
|
-
let t = Math.
|
|
419
|
-
for (let
|
|
420
|
-
let
|
|
421
|
-
|
|
456
|
+
function be(e) {
|
|
457
|
+
let t = new Float32Array(Math.max(e.length, 1) * 4);
|
|
458
|
+
for (let n = 0; n < e.length; n++) {
|
|
459
|
+
let r = e[n], i = n * 4;
|
|
460
|
+
t[i + 0] = r.coefficient[0], t[i + 1] = r.coefficient[1], t[i + 2] = r.index, t[i + 3] = 0;
|
|
422
461
|
}
|
|
423
|
-
return
|
|
462
|
+
return t;
|
|
424
463
|
}
|
|
425
464
|
//#endregion
|
|
426
|
-
//#region src/components/fourier-field/
|
|
427
|
-
var
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}),
|
|
442
|
-
label: "[FourierField] curve-samples",
|
|
443
|
-
size: 384 * 16,
|
|
444
|
-
usage: le
|
|
445
|
-
}), h = e.createBuffer({
|
|
446
|
-
label: "[FourierField] chain-tips",
|
|
447
|
-
size: 1040,
|
|
448
|
-
usage: le
|
|
449
|
-
}), g = e.createBuffer({
|
|
465
|
+
//#region src/components/fourier-field/renderer/wgpu.ts
|
|
466
|
+
var xe = 128, Q = 4, Se = 64, Ce = 1.35, we = .34, Te = .92, $ = {
|
|
467
|
+
chain: 0,
|
|
468
|
+
trail: 1,
|
|
469
|
+
head: 2
|
|
470
|
+
};
|
|
471
|
+
function Ee(e) {
|
|
472
|
+
let { canvas: t, config: n, getSpectrum: r, getPalette: i, getHeadT: a, shouldContinue: o, onFrame: s } = e;
|
|
473
|
+
return function(e, c, l) {
|
|
474
|
+
let u = e.createShaderModule({
|
|
475
|
+
label: "[FourierField] compute.wgsl",
|
|
476
|
+
code: de
|
|
477
|
+
}), d = e.createShaderModule({
|
|
478
|
+
label: "[FourierField] render.wgsl",
|
|
479
|
+
code: fe
|
|
480
|
+
}), f = e.createBuffer({
|
|
450
481
|
label: "[FourierField] compute-uniforms",
|
|
451
|
-
size:
|
|
482
|
+
size: q().buffer.byteLength,
|
|
452
483
|
usage: 72
|
|
453
|
-
}),
|
|
484
|
+
}), p = e.createBuffer({
|
|
454
485
|
label: "[FourierField] render-uniforms",
|
|
455
486
|
size: Y().buffer.byteLength,
|
|
456
487
|
usage: 72
|
|
457
|
-
}),
|
|
488
|
+
}), m = e.createBindGroupLayout({
|
|
458
489
|
label: "[FourierField] compute-bgl",
|
|
459
490
|
entries: [
|
|
460
491
|
{
|
|
461
492
|
binding: 0,
|
|
462
|
-
visibility:
|
|
493
|
+
visibility: Q,
|
|
463
494
|
buffer: { type: "uniform" }
|
|
464
495
|
},
|
|
465
496
|
{
|
|
466
497
|
binding: 1,
|
|
467
|
-
visibility:
|
|
498
|
+
visibility: Q,
|
|
468
499
|
buffer: { type: "read-only-storage" }
|
|
469
500
|
},
|
|
470
501
|
{
|
|
471
502
|
binding: 2,
|
|
472
|
-
visibility:
|
|
503
|
+
visibility: Q,
|
|
473
504
|
buffer: { type: "storage" }
|
|
474
505
|
},
|
|
475
506
|
{
|
|
476
507
|
binding: 3,
|
|
477
|
-
visibility:
|
|
508
|
+
visibility: Q,
|
|
478
509
|
buffer: { type: "storage" }
|
|
479
510
|
}
|
|
480
511
|
]
|
|
481
|
-
}),
|
|
512
|
+
}), h = e.createComputePipeline({
|
|
482
513
|
label: "[FourierField] compute-pipeline",
|
|
483
|
-
layout: e.createPipelineLayout({ bindGroupLayouts: [
|
|
514
|
+
layout: e.createPipelineLayout({ bindGroupLayouts: [m] }),
|
|
484
515
|
compute: {
|
|
485
|
-
module:
|
|
516
|
+
module: u,
|
|
486
517
|
entryPoint: "cs_main"
|
|
487
518
|
}
|
|
488
|
-
}),
|
|
489
|
-
label: "[FourierField] compute-bg",
|
|
490
|
-
layout: y,
|
|
491
|
-
entries: [
|
|
492
|
-
{
|
|
493
|
-
binding: 0,
|
|
494
|
-
resource: { buffer: g }
|
|
495
|
-
},
|
|
496
|
-
{
|
|
497
|
-
binding: 1,
|
|
498
|
-
resource: { buffer: p }
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
binding: 2,
|
|
502
|
-
resource: { buffer: m }
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
binding: 3,
|
|
506
|
-
resource: { buffer: h }
|
|
507
|
-
}
|
|
508
|
-
]
|
|
509
|
-
}), S = e.createBindGroupLayout({
|
|
519
|
+
}), g = e.createBindGroupLayout({
|
|
510
520
|
label: "[FourierField] render-bgl",
|
|
511
521
|
entries: [
|
|
512
522
|
{
|
|
@@ -525,18 +535,7 @@ function he(e) {
|
|
|
525
535
|
buffer: { type: "read-only-storage" }
|
|
526
536
|
}
|
|
527
537
|
]
|
|
528
|
-
}),
|
|
529
|
-
color: {
|
|
530
|
-
srcFactor: "one",
|
|
531
|
-
dstFactor: "one-minus-src-alpha",
|
|
532
|
-
operation: "add"
|
|
533
|
-
},
|
|
534
|
-
alpha: {
|
|
535
|
-
srcFactor: "one",
|
|
536
|
-
dstFactor: "one-minus-src-alpha",
|
|
537
|
-
operation: "add"
|
|
538
|
-
}
|
|
539
|
-
}, T = {
|
|
538
|
+
}), _ = e.createPipelineLayout({ bindGroupLayouts: [g] }), v = {
|
|
540
539
|
color: {
|
|
541
540
|
srcFactor: "one",
|
|
542
541
|
dstFactor: "one",
|
|
@@ -547,74 +546,132 @@ function he(e) {
|
|
|
547
546
|
dstFactor: "one",
|
|
548
547
|
operation: "max"
|
|
549
548
|
}
|
|
550
|
-
},
|
|
551
|
-
label: `[FourierField]
|
|
552
|
-
layout:
|
|
549
|
+
}, y = (t) => e.createRenderPipeline({
|
|
550
|
+
label: `[FourierField] pipeline-L${t}`,
|
|
551
|
+
layout: _,
|
|
553
552
|
vertex: {
|
|
554
|
-
module:
|
|
553
|
+
module: d,
|
|
555
554
|
entryPoint: "vs_main",
|
|
556
555
|
constants: { LAYER: t }
|
|
557
556
|
},
|
|
558
557
|
fragment: {
|
|
559
|
-
module:
|
|
558
|
+
module: d,
|
|
560
559
|
entryPoint: "fs_main",
|
|
561
560
|
constants: { LAYER: t },
|
|
562
561
|
targets: [{
|
|
563
|
-
format:
|
|
564
|
-
blend:
|
|
562
|
+
format: l,
|
|
563
|
+
blend: v
|
|
565
564
|
}]
|
|
566
565
|
},
|
|
567
566
|
primitive: { topology: "triangle-list" }
|
|
568
|
-
}),
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
head:
|
|
572
|
-
|
|
573
|
-
"cel-arm": E(W["cel-arm"], w)
|
|
574
|
-
}, O = e.createBindGroup({
|
|
575
|
-
label: "[FourierField] render-bg",
|
|
576
|
-
layout: S,
|
|
577
|
-
entries: [
|
|
578
|
-
{
|
|
579
|
-
binding: 0,
|
|
580
|
-
resource: { buffer: v }
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
binding: 1,
|
|
584
|
-
resource: { buffer: m }
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
binding: 2,
|
|
588
|
-
resource: { buffer: h }
|
|
589
|
-
}
|
|
590
|
-
]
|
|
591
|
-
}), k = K(), A = Y(), j = null, M = {
|
|
567
|
+
}), b = {
|
|
568
|
+
chain: y($.chain),
|
|
569
|
+
trail: y($.trail),
|
|
570
|
+
head: y($.head)
|
|
571
|
+
}, x = q(), S = Y(), C = null, w = null, T = null, E = null, D = null, O = null, k = {
|
|
592
572
|
centerX: 0,
|
|
593
573
|
centerY: 0,
|
|
594
574
|
scale: 1
|
|
595
|
-
},
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
t !== j && (j = t, N = Math.min(t.length, 64), M = X(t), e.queue.writeBuffer(p, 0, Q(t)));
|
|
575
|
+
}, A = n.showMachine;
|
|
576
|
+
function j() {
|
|
577
|
+
w?.destroy(), T?.destroy(), E?.destroy(), w = null, T = null, E = null;
|
|
599
578
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
579
|
+
function M() {
|
|
580
|
+
let t = r(), i = A !== n.showMachine;
|
|
581
|
+
if (!(t === C && !i)) {
|
|
582
|
+
if (t !== C) {
|
|
583
|
+
C = t, j();
|
|
584
|
+
let n = Math.max(t.terms.length, 1);
|
|
585
|
+
w = e.createBuffer({
|
|
586
|
+
label: "[FourierField] phasors",
|
|
587
|
+
size: n * 16,
|
|
588
|
+
usage: 136
|
|
589
|
+
}), T = e.createBuffer({
|
|
590
|
+
label: "[FourierField] curve-samples",
|
|
591
|
+
size: 384 * 16,
|
|
592
|
+
usage: xe
|
|
593
|
+
}), E = e.createBuffer({
|
|
594
|
+
label: "[FourierField] chain-tips",
|
|
595
|
+
size: (n + 1) * 16,
|
|
596
|
+
usage: xe
|
|
597
|
+
}), e.queue.writeBuffer(w, 0, be(t.terms)), D = e.createBindGroup({
|
|
598
|
+
label: "[FourierField] compute-bg",
|
|
599
|
+
layout: m,
|
|
600
|
+
entries: [
|
|
601
|
+
{
|
|
602
|
+
binding: 0,
|
|
603
|
+
resource: { buffer: f }
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
binding: 1,
|
|
607
|
+
resource: { buffer: w }
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
binding: 2,
|
|
611
|
+
resource: { buffer: T }
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
binding: 3,
|
|
615
|
+
resource: { buffer: E }
|
|
616
|
+
}
|
|
617
|
+
]
|
|
618
|
+
}), O = e.createBindGroup({
|
|
619
|
+
label: "[FourierField] render-bg",
|
|
620
|
+
layout: g,
|
|
621
|
+
entries: [
|
|
622
|
+
{
|
|
623
|
+
binding: 0,
|
|
624
|
+
resource: { buffer: p }
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
binding: 1,
|
|
628
|
+
resource: { buffer: T }
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
binding: 2,
|
|
632
|
+
resource: { buffer: E }
|
|
633
|
+
}
|
|
634
|
+
]
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
A = n.showMachine, k = _e(C, A);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
let N = Z(i()), P = De(i());
|
|
641
|
+
function F() {
|
|
642
|
+
let e = i(), t = De(e);
|
|
643
|
+
t !== P && (P = t, N = Z(e));
|
|
644
|
+
}
|
|
645
|
+
function I(e) {}
|
|
646
|
+
function L(r) {
|
|
647
|
+
if (s?.(r), M(), F(), !C || !D || !O) return;
|
|
648
|
+
let i = C.terms.length, o = Math.max(1, Math.min(Math.round(n.harmonics), i)), l = n.showMachine ? o : 0;
|
|
649
|
+
me(x, a(), n.trailArc, o, 384, i), e.queue.writeBuffer(f, 0, x.buffer);
|
|
650
|
+
let u = Math.min(typeof window > "u" ? 1 : window.devicePixelRatio || 1, 2), d = Math.min(t.width, t.height) / Math.max(u, 1), m = t.width / Math.max(t.height, 1), g = X(n.markStroke, k.scale, d) * .5, _ = X(n.markStroke, k.scale, d), v = 12 / (Math.max(k.scale, 1e-6) * Math.max(d, 1));
|
|
651
|
+
ye(S, {
|
|
652
|
+
fit: k,
|
|
653
|
+
aspect: m,
|
|
654
|
+
markHalfModel: g,
|
|
655
|
+
inkOffsetStrokes: n.inkOffset,
|
|
656
|
+
scaffoldFrac: re,
|
|
657
|
+
edgeMargin: v,
|
|
658
|
+
peakAlpha: Te * n.intensity,
|
|
659
|
+
glow: n.glow,
|
|
660
|
+
squash: n.squash,
|
|
661
|
+
trailFadeExp: Ce,
|
|
662
|
+
trailFloor: we,
|
|
663
|
+
hueSweep: ne,
|
|
664
|
+
ringStrokeModel: _,
|
|
665
|
+
showMachine: n.showMachine,
|
|
666
|
+
rainbowChain: n.rainbowChain,
|
|
667
|
+
sampleCount: 384,
|
|
668
|
+
chainCount: l,
|
|
669
|
+
ramp: N
|
|
670
|
+
}), e.queue.writeBuffer(p, 0, S.buffer);
|
|
671
|
+
let y = e.createCommandEncoder({ label: "[FourierField] frame" }), w = y.beginComputePass();
|
|
672
|
+
w.setPipeline(h), w.setBindGroup(0, D), w.dispatchWorkgroups(Math.ceil(384 / Se)), w.end();
|
|
673
|
+
let T = y.beginRenderPass({ colorAttachments: [{
|
|
674
|
+
view: c.getCurrentTexture().createView(),
|
|
618
675
|
clearValue: {
|
|
619
676
|
r: 0,
|
|
620
677
|
g: 0,
|
|
@@ -624,484 +681,174 @@ function he(e) {
|
|
|
624
681
|
loadOp: "clear",
|
|
625
682
|
storeOp: "store"
|
|
626
683
|
}] });
|
|
627
|
-
|
|
628
|
-
let j = ie({
|
|
629
|
-
sampleCount: 384,
|
|
630
|
-
armCount: d,
|
|
631
|
-
showEpicycles: n.showEpicycles,
|
|
632
|
-
celGain: n.celGain
|
|
633
|
-
});
|
|
634
|
-
for (let e of j) E.setPipeline(D[e.kind]), E.draw(6, e.instanceCount, 0, 0);
|
|
635
|
-
E.end(), e.queue.submit([C.finish()]);
|
|
684
|
+
T.setBindGroup(0, O), l > 0 && (T.setPipeline(b.chain), T.draw(6, l, 0, 0)), T.setPipeline(b.trail), T.draw(6, 383, 0, 0), T.setPipeline(b.head), T.draw(6, 1, 0, 0), T.end(), e.queue.submit([y.finish()]);
|
|
636
685
|
}
|
|
637
686
|
return {
|
|
638
|
-
frame:
|
|
687
|
+
frame: L,
|
|
639
688
|
shouldContinue: o,
|
|
640
|
-
resize:
|
|
689
|
+
resize: I,
|
|
641
690
|
teardown: () => {
|
|
642
|
-
|
|
691
|
+
j(), f.destroy(), p.destroy();
|
|
643
692
|
}
|
|
644
693
|
};
|
|
645
694
|
};
|
|
646
695
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
#define MAX_FOURIER_STOPS 4
|
|
653
|
-
// Must equal the WGSL twin and FOURIER_TANGENT_EPS in constants.ts.
|
|
654
|
-
#define TANGENT_EPS 1e-4
|
|
655
|
-
#define SPEED_REF_HALFWIDTHS 6.0
|
|
656
|
-
// The thick luminous ribbon mirrors RIBBON_TAIL_FRAC verbatim
|
|
657
|
-
// from constants.ts because the GLSL twin cannot import a TS const; parity coverage verifies the
|
|
658
|
-
// two copies are equal so the mid-body floor (RIBBON_HEAD_FLOOR_PX) can never drift off it.
|
|
659
|
-
#define RIBBON_TAIL_FRAC 0.4
|
|
660
|
-
#define RIBBON_UNDERGLOW_SCALE 2.2
|
|
661
|
-
#define RIBBON_UNDERGLOW_ALPHA 0.16
|
|
662
|
-
|
|
663
|
-
in vec2 vP;
|
|
664
|
-
in vec2 vA;
|
|
665
|
-
in vec2 vB;
|
|
666
|
-
in float vAge;
|
|
667
|
-
in float vHalf;
|
|
668
|
-
in float vArg2;
|
|
669
|
-
out vec4 fragColor;
|
|
670
|
-
|
|
671
|
-
uniform vec4 uTrail; // (trailWidth, peakAlpha, headGlowAlpha, trailFadeExp)
|
|
672
|
-
uniform vec4 uEnv; // (trailFloor, intensity, showEpicycles, rainbowChain)
|
|
673
|
-
uniform vec4 uLoom; // (squashGain, celGain, _pad, _pad) — FOURIER-LOOM §2b/§3b
|
|
674
|
-
uniform int uLayer; // 0 trail · 1 epicycle · 2 head · 3 cel-rope · 4 cel-arm
|
|
675
|
-
uniform int uStopCount;
|
|
676
|
-
uniform vec3 uPalette[MAX_FOURIER_STOPS]; // linear-sRGB stops
|
|
677
|
-
|
|
678
|
-
const float PI = 3.141592653589793;
|
|
679
|
-
|
|
680
|
-
${y}
|
|
681
|
-
${x}
|
|
682
|
-
|
|
683
|
-
// Negative-safe cube root (the WGSL chunk's cbrt3 twin; the GLSL chunk inlines it).
|
|
684
|
-
vec3 cbrt3(vec3 v) { return sign(v) * pow(abs(v), vec3(1.0 / 3.0)); }
|
|
685
|
-
|
|
686
|
-
vec3 samplePaletteLin(float t) {
|
|
687
|
-
if (uStopCount <= 1) return uPalette[0];
|
|
688
|
-
float n = float(uStopCount);
|
|
689
|
-
float ft = clamp(t, 0.0, 1.0) * (n - 1.0);
|
|
690
|
-
int i0 = int(floor(ft));
|
|
691
|
-
int i1 = min(i0 + 1, uStopCount - 1);
|
|
692
|
-
float f = ft - float(i0);
|
|
693
|
-
vec3 labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * uPalette[i0]);
|
|
694
|
-
vec3 labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * uPalette[i1]);
|
|
695
|
-
return oklabToLinearSrgb(mix(labA, labB, f));
|
|
696
|
+
function De(e) {
|
|
697
|
+
let t = "";
|
|
698
|
+
for (let n of e) t += `${n.L.toFixed(4)},${n.C.toFixed(4)},${n.h.toFixed(2)};`;
|
|
699
|
+
return t;
|
|
696
700
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
vec3 lab = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * baseLin);
|
|
702
|
-
vec3 lch = oklabToOklch(lab);
|
|
703
|
-
float hueShift = mix(-0.45, 1.15, clamp(seg, 0.0, 1.0));
|
|
704
|
-
vec3 lifted = vec3(0.66, max(lch.y, 0.14), lch.z + hueShift);
|
|
705
|
-
return oklabToLinearSrgb(oklchToOklab(lifted));
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
float segDist(vec2 p, vec2 a, vec2 b) {
|
|
709
|
-
vec2 pa = p - a;
|
|
710
|
-
vec2 ba = b - a;
|
|
711
|
-
float h = clamp(dot(pa, ba) / max(dot(ba, ba), 1e-8), 0.0, 1.0);
|
|
712
|
-
return length(pa - ba * h);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
// The head travel frame (T, ŝ), the GLSL twin of the WGSL headFrame.
|
|
716
|
-
struct HeadFrame { vec2 T; float sHat; };
|
|
717
|
-
HeadFrame headFrame(vec2 head, vec2 headBack, float halfW) {
|
|
718
|
-
vec2 d = head - headBack;
|
|
719
|
-
float s = length(d);
|
|
720
|
-
HeadFrame fr;
|
|
721
|
-
if (s <= TANGENT_EPS) { fr.T = vec2(1.0, 0.0); fr.sHat = 0.0; return fr; }
|
|
722
|
-
fr.T = d / s;
|
|
723
|
-
float refScale = max(halfW * SPEED_REF_HALFWIDTHS, 1e-6);
|
|
724
|
-
fr.sHat = clamp(s / refScale, 0.0, 1.0);
|
|
725
|
-
return fr;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// The volume-preserving anisotropic head distance (the WGSL headAniso twin).
|
|
729
|
-
float headAniso(vec2 p, vec2 head, HeadFrame fr, float k) {
|
|
730
|
-
float g = 1.0 + k * fr.sHat;
|
|
731
|
-
vec2 n = vec2(-fr.T.y, fr.T.x);
|
|
732
|
-
vec2 rel = p - head;
|
|
733
|
-
float along = dot(rel, fr.T) / g;
|
|
734
|
-
float across = dot(rel, n) * g;
|
|
735
|
-
return length(vec2(along, across));
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
void main() {
|
|
739
|
-
vec2 p = vP;
|
|
740
|
-
float aa = max(fwidth(p.x) + fwidth(p.y), 1e-5) * 0.75;
|
|
741
|
-
float peak = uTrail.y * uEnv.y;
|
|
742
|
-
float headGlow = uTrail.z * uEnv.y;
|
|
743
|
-
float fadeExp = uTrail.w;
|
|
744
|
-
float trailFloor = uEnv.x;
|
|
745
|
-
bool rainbow = uEnv.w > 0.5;
|
|
746
|
-
float squashGain = uLoom.x;
|
|
747
|
-
float celGain = uLoom.y;
|
|
748
|
-
float halfW = vHalf;
|
|
749
|
-
|
|
750
|
-
if (uLayer == 0) {
|
|
751
|
-
// ── TRAIL — the tapered luminous ribbon over its own soft under-glow ──
|
|
752
|
-
float age = vAge;
|
|
753
|
-
float d = segDist(p, vA, vB);
|
|
754
|
-
// Head→tail taper: the ribbon half-width scales with age (thick head, thin tail).
|
|
755
|
-
float ribbonHalf = halfW * (RIBBON_TAIL_FRAC + (1.0 - RIBBON_TAIL_FRAC) * age);
|
|
756
|
-
vec3 lin = samplePaletteLin(1.0 - age * 0.4);
|
|
757
|
-
vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));
|
|
758
|
-
// Soft under-glow: a wider, low-alpha copy under the crisp ribbon (one color event).
|
|
759
|
-
float glowHalf = ribbonHalf * RIBBON_UNDERGLOW_SCALE;
|
|
760
|
-
float glowCover = 1.0 - smoothstep(glowHalf, glowHalf + aa * 3.0, d);
|
|
761
|
-
float ga = peak * RIBBON_UNDERGLOW_ALPHA * pow(age, fadeExp) * glowCover;
|
|
762
|
-
// The crisp tapered ribbon core.
|
|
763
|
-
float cover = 1.0 - smoothstep(ribbonHalf, ribbonHalf + aa, d);
|
|
764
|
-
float ca = max(peak * pow(age, fadeExp), peak * trailFloor) * cover;
|
|
765
|
-
// core OVER glow OVER transparent (both premultiplied on the SAME rgb → out = rgb·outA).
|
|
766
|
-
float outA = ca + ga * (1.0 - ca);
|
|
767
|
-
fragColor = vec4(rgb * outA, outA);
|
|
768
|
-
} else if (uLayer == 1) {
|
|
769
|
-
// ── EPICYCLE — orbit RING + ARM + joint DOT union (MAX-blended, no join seam) ──
|
|
770
|
-
float seg = vArg2;
|
|
771
|
-
vec3 lin = chainColorLin(seg, rainbow);
|
|
772
|
-
vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));
|
|
773
|
-
float radius = length(vB - vA);
|
|
774
|
-
float dRing = abs(length(p - vA) - radius);
|
|
775
|
-
float ringW = max(halfW * 0.45, aa);
|
|
776
|
-
float ringMask = (1.0 - smoothstep(ringW, ringW + aa, dRing)) * 0.5;
|
|
777
|
-
float dArm = segDist(p, vA, vB);
|
|
778
|
-
float armMask = 1.0 - smoothstep(halfW * 0.55, halfW * 0.55 + aa, dArm);
|
|
779
|
-
float dotR = max(halfW * 0.7, aa * 2.0);
|
|
780
|
-
float dDot = length(p - vA);
|
|
781
|
-
float dotMask = 1.0 - smoothstep(dotR, dotR + aa, dDot);
|
|
782
|
-
float m = clamp(max(max(ringMask, armMask), dotMask), 0.0, 1.0) * peak * 0.7;
|
|
783
|
-
fragColor = vec4(rgb * m, m);
|
|
784
|
-
} else if (uLayer == 2) {
|
|
785
|
-
// ── HEAD — squash-and-stretch (§2b): halo + saturated core + white specular ──
|
|
786
|
-
vec2 head = vA;
|
|
787
|
-
vec2 headBack = vB;
|
|
788
|
-
HeadFrame fr = headFrame(head, headBack, halfW);
|
|
789
|
-
float dHead = headAniso(p, head, fr, squashGain);
|
|
790
|
-
float coreR = halfW * 1.5;
|
|
791
|
-
float haloR = coreR * 3.0;
|
|
792
|
-
vec3 headRgb = clamp(linearToSrgb(samplePaletteLin(0.0)), vec3(0.0), vec3(1.0));
|
|
793
|
-
float halo = (1.0 - smoothstep(0.0, haloR, dHead)) * headGlow * 0.35;
|
|
794
|
-
vec4 accum = vec4(headRgb * halo, halo);
|
|
795
|
-
float core = (1.0 - smoothstep(coreR, coreR + aa, dHead)) * headGlow;
|
|
796
|
-
accum = vec4(headRgb * core, core) + accum * (1.0 - core);
|
|
797
|
-
float spec = (1.0 - smoothstep(coreR * 0.4, coreR * 0.4 + aa, dHead)) * headGlow * 0.9;
|
|
798
|
-
accum = vec4(vec3(1.0) * spec, spec) + accum * (1.0 - spec);
|
|
799
|
-
fragColor = accum;
|
|
800
|
-
} else {
|
|
801
|
-
// ── CEL — the technicolor ink shadow (rope uLayer==3, arm uLayer==4) ──
|
|
802
|
-
float celA = clamp(celGain, 0.0, 1.0);
|
|
803
|
-
float d = segDist(p, vA, vB);
|
|
804
|
-
float cover = 1.0 - smoothstep(halfW, halfW + aa, d);
|
|
805
|
-
float m = cover * celA * peak * vArg2; // vArg2 = celStrength (1.0 rope / 0.7 arm)
|
|
806
|
-
fragColor = vec4(0.0, 0.0, 0.0, m);
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
`, ve = 256, ye = 64, be = .92, xe = .95, Se = 1.35, Ce = .34;
|
|
810
|
-
function we(e, t, n) {
|
|
811
|
-
let r = e.createShader(t);
|
|
812
|
-
if (e.shaderSource(r, n), e.compileShader(r), !e.getShaderParameter(r, e.COMPILE_STATUS)) {
|
|
813
|
-
let t = e.getShaderInfoLog(r);
|
|
814
|
-
throw e.deleteShader(r), Error(`[FourierField] shader compile failed: ${t}`);
|
|
815
|
-
}
|
|
816
|
-
return r;
|
|
817
|
-
}
|
|
818
|
-
function Te(e) {
|
|
819
|
-
let { canvas: t, config: n, getSpectrum: r, getPalette: i, getHeadT: a, shouldContinue: o, onFrame: s } = e, l = e.getPointerLean;
|
|
820
|
-
return function(e) {
|
|
821
|
-
let u = we(e, e.VERTEX_SHADER, ge), d = we(e, e.FRAGMENT_SHADER, _e), f = e.createProgram();
|
|
822
|
-
if (e.attachShader(f, u), e.attachShader(f, d), e.linkProgram(f), !e.getProgramParameter(f, e.LINK_STATUS)) throw Error(`[FourierField] link failed: ${e.getProgramInfoLog(f)}`);
|
|
823
|
-
e.deleteShader(u), e.deleteShader(d);
|
|
824
|
-
let p = e.createVertexArray();
|
|
825
|
-
e.bindVertexArray(p);
|
|
826
|
-
let m = e.createBuffer();
|
|
827
|
-
e.bindBuffer(e.ARRAY_BUFFER, m), e.bufferData(e.ARRAY_BUFFER, ae, e.STATIC_DRAW);
|
|
828
|
-
let g = e.getAttribLocation(f, "aCorner");
|
|
829
|
-
e.enableVertexAttribArray(g), e.vertexAttribPointer(g, 2, e.FLOAT, !1, 0, 0), e.vertexAttribDivisor(g, 0);
|
|
830
|
-
let v = new Float32Array(639 * 8), y = e.createBuffer();
|
|
831
|
-
e.bindBuffer(e.ARRAY_BUFFER, y), e.bufferData(e.ARRAY_BUFFER, v.byteLength, e.DYNAMIC_DRAW);
|
|
832
|
-
let b = e.getAttribLocation(f, "aSeg"), x = e.getAttribLocation(f, "aData");
|
|
833
|
-
e.enableVertexAttribArray(b), e.enableVertexAttribArray(x), e.vertexAttribPointer(b, 4, e.FLOAT, !1, 32, 0), e.vertexAttribPointer(x, 4, e.FLOAT, !1, 32, 16), e.vertexAttribDivisor(b, 1), e.vertexAttribDivisor(x, 1), e.bindVertexArray(null);
|
|
834
|
-
let S = (t) => e.getUniformLocation(f, t), C = S("uFit"), w = S("uTrail"), T = S("uEnv"), E = S("uLoom"), D = S("uLayer"), O = S("uEdgeMargin"), k = S("uStopCount"), A = S("uPalette[0]"), j = new Float32Array(ve * 3), M = /* @__PURE__ */ new Float32Array(130), N = /* @__PURE__ */ new Float32Array(12), P = null, F = {
|
|
835
|
-
centerX: 0,
|
|
836
|
-
centerY: 0,
|
|
837
|
-
scale: 1
|
|
838
|
-
}, I = 0;
|
|
839
|
-
function L() {
|
|
840
|
-
let e = r();
|
|
841
|
-
e !== P && (P = e, I = Math.min(e.length, ye), F = X(e));
|
|
842
|
-
}
|
|
843
|
-
function R(t) {
|
|
844
|
-
e.viewport(0, 0, t.w, t.h);
|
|
845
|
-
}
|
|
846
|
-
function z(r) {
|
|
847
|
-
s?.(r), L();
|
|
848
|
-
let o = P;
|
|
849
|
-
if (!o) return;
|
|
850
|
-
let u = a(), d = Math.max(1, Math.min(Math.round(n.harmonics), I)), m = n.showEpicycles ? Math.max(1, Math.min(Math.round(n.epicycleArms), d)) : 0, g = ve, S = Math.max(g - 1, 1);
|
|
851
|
-
for (let e = 0; e < g; e++) {
|
|
852
|
-
let t = e / S, r = 1 - t, i = u - n.trailArc * t;
|
|
853
|
-
i -= Math.floor(i);
|
|
854
|
-
let [a, s] = h(o, i, d), c = e * 3;
|
|
855
|
-
j[c + 0] = a, j[c + 1] = s, j[c + 2] = r;
|
|
856
|
-
}
|
|
857
|
-
let R = Math.min(m, d);
|
|
858
|
-
for (let e = 0; e <= ye; e++) {
|
|
859
|
-
let t = e * 2;
|
|
860
|
-
if (e <= R) {
|
|
861
|
-
let [n, r] = h(o, u, e);
|
|
862
|
-
M[t + 0] = n, M[t + 1] = r;
|
|
863
|
-
} else M[t + 0] = 0, M[t + 1] = 0;
|
|
864
|
-
}
|
|
865
|
-
let z = t.width / Math.max(t.height, 1), B = Math.min(t.width, t.height) / Math.max(_(), 1), V = ce(n.trailWidth, F.scale, B), H = V * .5, ee = 12 / (Math.max(F.scale, 1e-6) * Math.max(B, 1)), U = j[0], te = j[1], ne = j[3], re = j[4], ae = U - ne, oe = te - re, G = Math.hypot(ae, oe), K = G > 1e-4 ? ae / G : 1, se = G > 1e-4 ? oe / G : 0, q = -K * H * 1.4, J = -se * H * 1.4, Y = ie({
|
|
866
|
-
sampleCount: g,
|
|
867
|
-
armCount: m,
|
|
868
|
-
showEpicycles: n.showEpicycles,
|
|
869
|
-
celGain: n.celGain
|
|
870
|
-
}), X = /* @__PURE__ */ new Map(), Z = 0, Q = (e, t, n, r, i, a, o) => {
|
|
871
|
-
v[Z++] = e, v[Z++] = t, v[Z++] = n, v[Z++] = r, v[Z++] = i, v[Z++] = a, v[Z++] = o, v[Z++] = 0;
|
|
872
|
-
};
|
|
873
|
-
for (let e of Y) if (X.set(e.kind, Z), e.kind === "cel-rope") for (let e = 0; e < g - 1; e++) {
|
|
874
|
-
let t = e * 3;
|
|
875
|
-
Q(j[t] + q, j[t + 1] + J, j[t + 3] + q, j[t + 4] + J, 0, H, 1);
|
|
876
|
-
}
|
|
877
|
-
else if (e.kind === "cel-arm") for (let e = 0; e < m; e++) {
|
|
878
|
-
let t = e * 2;
|
|
879
|
-
Q(M[t] + q, M[t + 1] + J, M[t + 2] + q, M[t + 3] + J, 0, H * .55, .7);
|
|
880
|
-
}
|
|
881
|
-
else if (e.kind === "epicycle") {
|
|
882
|
-
let e = Math.max(m - 1, 1);
|
|
883
|
-
for (let t = 0; t < m; t++) {
|
|
884
|
-
let n = t * 2;
|
|
885
|
-
Q(M[n], M[n + 1], M[n + 2], M[n + 3], 0, H, t / e);
|
|
886
|
-
}
|
|
887
|
-
} else if (e.kind === "trail") for (let e = 0; e < g - 1; e++) {
|
|
888
|
-
let t = e * 3, n = Math.max(j[t + 2], j[t + 5]);
|
|
889
|
-
Q(j[t], j[t + 1], j[t + 3], j[t + 4], n, H, 0);
|
|
890
|
-
}
|
|
891
|
-
else Q(j[0], j[1], j[3], j[4], 0, H, 0);
|
|
892
|
-
let le = Z, $ = i(), ue = Math.min($.length, 4);
|
|
893
|
-
for (let e = 0; e < 4; e++) {
|
|
894
|
-
let t = c($[Math.min(e, ue - 1)] ?? $[0]);
|
|
895
|
-
N[e * 3 + 0] = t[0], N[e * 3 + 1] = t[1], N[e * 3 + 2] = t[2];
|
|
896
|
-
}
|
|
897
|
-
e.useProgram(f), e.bindVertexArray(p), e.enable(e.BLEND), e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT), e.bindBuffer(e.ARRAY_BUFFER, y), e.bufferSubData(e.ARRAY_BUFFER, 0, v.subarray(0, le));
|
|
898
|
-
let de = l?.() ?? {
|
|
899
|
-
x: 0,
|
|
900
|
-
y: 0
|
|
901
|
-
};
|
|
902
|
-
e.uniform4f(C, F.centerX - de.x, F.centerY - de.y, F.scale, z), e.uniform4f(w, V, be, xe, Se), e.uniform4f(T, Ce, n.intensity, +!!n.showEpicycles, +!!n.rainbowChain), e.uniform4f(E, n.squashGain, n.celGain, 0, 0), e.uniform1f(O, ee), e.uniform1i(k, ue), e.uniform3fv(A, N);
|
|
903
|
-
for (let t of Y) {
|
|
904
|
-
let n = (X.get(t.kind) ?? 0) * 4;
|
|
905
|
-
e.vertexAttribPointer(b, 4, e.FLOAT, !1, 32, n), e.vertexAttribPointer(x, 4, e.FLOAT, !1, 32, n + 16), e.uniform1i(D, W[t.kind]), t.blend === "max" ? (e.blendEquation(e.MAX), e.blendFunc(e.ONE, e.ONE)) : (e.blendEquation(e.FUNC_ADD), e.blendFunc(e.ONE, e.ONE_MINUS_SRC_ALPHA)), e.drawArraysInstanced(e.TRIANGLE_STRIP, 0, 4, t.instanceCount);
|
|
906
|
-
}
|
|
907
|
-
e.blendEquation(e.FUNC_ADD);
|
|
908
|
-
}
|
|
909
|
-
return {
|
|
910
|
-
frame: z,
|
|
911
|
-
shouldContinue: o,
|
|
912
|
-
resize: R,
|
|
913
|
-
teardown: () => {
|
|
914
|
-
e.deleteProgram(f), e.deleteBuffer(m), e.deleteBuffer(y), e.deleteVertexArray(p);
|
|
915
|
-
}
|
|
916
|
-
};
|
|
701
|
+
var Oe = "[FourierField] WebGPU is required. This field paints the transform itself, so it ships one renderer and no lookalike — where WebGPU is absent it declares the failure and paints nothing.";
|
|
702
|
+
function ke() {
|
|
703
|
+
return function() {
|
|
704
|
+
throw Error(Oe);
|
|
917
705
|
};
|
|
918
706
|
}
|
|
919
707
|
//#endregion
|
|
920
|
-
//#region src/components/fourier-field/
|
|
921
|
-
function
|
|
922
|
-
let { config:
|
|
923
|
-
function
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
f = e;
|
|
935
|
-
let i = t.routePointer?.();
|
|
936
|
-
if (t.routePointer && (g.setActive(i?.active ?? !1), i?.active && g.setPointer(i.x, i.y)), g.tick(n), v()) {
|
|
937
|
-
d = l, p = 0, m = 0;
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
940
|
-
let a = Math.min(Math.max(n / 1e3, 0), .05);
|
|
941
|
-
if (r.interactive && g.active.value) {
|
|
942
|
-
let e = r.speed / u + g.velocity.value.x * B + p;
|
|
943
|
-
d = (d + e * a) % 1, d < 0 && (d += 1);
|
|
944
|
-
let t = g.burst.value * 4;
|
|
945
|
-
t !== 0 && (p = t, m = 0), h(a);
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
let o = r.speed / u + p;
|
|
949
|
-
d = (d + o * a) % 1, d < 0 && (d += 1), h(a);
|
|
950
|
-
}
|
|
951
|
-
let x = () => d, w = null, T = {
|
|
952
|
-
centerX: 0,
|
|
953
|
-
centerY: 0,
|
|
954
|
-
scale: 1
|
|
955
|
-
}, E = () => {
|
|
956
|
-
let e = o();
|
|
957
|
-
return e !== w && (w = e, T = X(e)), T;
|
|
958
|
-
}, D = () => {
|
|
959
|
-
if (!r.interactive) return {
|
|
960
|
-
x: 0,
|
|
961
|
-
y: 0
|
|
962
|
-
};
|
|
963
|
-
let t = e.value;
|
|
964
|
-
if (!t || !t.width || !t.height) return {
|
|
965
|
-
x: 0,
|
|
966
|
-
y: 0
|
|
967
|
-
};
|
|
968
|
-
let { leanX: n, leanY: o } = a(i(g), {
|
|
969
|
-
aspect: t.width / t.height,
|
|
970
|
-
scale: Math.max(E().scale, 1e-6)
|
|
708
|
+
//#region src/components/fourier-field/useFourierField.ts
|
|
709
|
+
function Ae(e, t) {
|
|
710
|
+
let { config: n, getSpectrum: i, getPalette: a } = t, o = t.mode ?? "live", s = t.interactive, c = ue(), l = -1, u = j(0), d = -Infinity, f = r({ respectReducedMotion: n.respectReducedMotion }), p = () => (t.freeze?.() ?? !1) || (C?.reducedMotion ?? !1);
|
|
711
|
+
function m(e) {
|
|
712
|
+
let t = l >= 0 ? (e - l) * 1e3 : 16.7;
|
|
713
|
+
l = e, f.tick(t);
|
|
714
|
+
let r = s() && f.active.value;
|
|
715
|
+
c.step({
|
|
716
|
+
dt: t / 1e3,
|
|
717
|
+
speed: n.speed,
|
|
718
|
+
scrubVelocity: r ? f.velocity.value.x : 0,
|
|
719
|
+
burst: r ? f.burst.value : 0,
|
|
720
|
+
engaged: r,
|
|
721
|
+
frozen: p()
|
|
971
722
|
});
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
y: o
|
|
975
|
-
};
|
|
976
|
-
}, O = (e) => {
|
|
977
|
-
g.onPointerMove(e), r.interactive && I?.wake();
|
|
978
|
-
}, k = () => {
|
|
979
|
-
g.onPointerEnter(), r.interactive && I?.wake();
|
|
980
|
-
}, A = (e) => e.parentElement ?? e;
|
|
981
|
-
function j(e) {
|
|
982
|
-
let t = A(e);
|
|
983
|
-
t.addEventListener("pointermove", O), t.addEventListener("pointerenter", k), t.addEventListener("pointerleave", g.onPointerLeave);
|
|
723
|
+
let i = e * 1e3;
|
|
724
|
+
i - d >= 100 && (d = i, u.value = c.headT);
|
|
984
725
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
726
|
+
let h = (e) => {
|
|
727
|
+
f.onPointerMove(e), s() && C?.wake();
|
|
728
|
+
}, _ = () => {
|
|
729
|
+
f.onPointerEnter(), s() && C?.wake();
|
|
730
|
+
}, v = () => {
|
|
731
|
+
f.onPointerLeave();
|
|
732
|
+
}, b = (e) => e.parentElement ?? e;
|
|
733
|
+
function x(e) {
|
|
734
|
+
let t = b(e);
|
|
735
|
+
t.addEventListener("pointermove", h), t.addEventListener("pointerenter", _), t.addEventListener("pointerleave", v);
|
|
988
736
|
}
|
|
989
|
-
|
|
990
|
-
|
|
737
|
+
function S(e) {
|
|
738
|
+
let t = b(e);
|
|
739
|
+
t.removeEventListener("pointermove", h), t.removeEventListener("pointerenter", _), t.removeEventListener("pointerleave", v);
|
|
740
|
+
}
|
|
741
|
+
let C = null, w = j(y("webgpu")), T = (e) => e.engine === "webgpu" ? e : {
|
|
742
|
+
...e,
|
|
743
|
+
engine: "webgpu",
|
|
744
|
+
adapter: "WebGPU unavailable"
|
|
745
|
+
}, E = !1, D = () => {
|
|
746
|
+
if (E) return null;
|
|
991
747
|
let t = e.value;
|
|
992
|
-
return t ? (
|
|
993
|
-
mode:
|
|
994
|
-
respectReducedMotion:
|
|
995
|
-
dprPolicy:
|
|
748
|
+
return t ? (C || (x(t), C = g(t, {
|
|
749
|
+
mode: o,
|
|
750
|
+
respectReducedMotion: n.respectReducedMotion,
|
|
751
|
+
dprPolicy: () => 2,
|
|
752
|
+
composeIntersectionPark: !0,
|
|
996
753
|
revealBloom: !0,
|
|
997
|
-
setupWGPU:
|
|
754
|
+
setupWGPU: Ee({
|
|
998
755
|
canvas: t,
|
|
999
|
-
config:
|
|
1000
|
-
getSpectrum:
|
|
1001
|
-
getPalette:
|
|
1002
|
-
getHeadT:
|
|
756
|
+
config: n,
|
|
757
|
+
getSpectrum: i,
|
|
758
|
+
getPalette: a,
|
|
759
|
+
getHeadT: () => c.headT,
|
|
1003
760
|
shouldContinue: () => !0,
|
|
1004
|
-
onFrame:
|
|
1005
|
-
getPointerLean: D
|
|
761
|
+
onFrame: m
|
|
1006
762
|
}),
|
|
1007
|
-
setupGL:
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
getSpectrum: o,
|
|
1011
|
-
getPalette: s,
|
|
1012
|
-
getHeadT: x,
|
|
1013
|
-
shouldContinue: () => !0,
|
|
1014
|
-
onFrame: y,
|
|
1015
|
-
getPointerLean: D
|
|
1016
|
-
}),
|
|
1017
|
-
onStatus: (e) => L.value = e
|
|
1018
|
-
}), I.armAsync().catch(() => void 0)), I) : null;
|
|
763
|
+
setupGL: ke(),
|
|
764
|
+
onStatus: (e) => w.value = T(e)
|
|
765
|
+
}), C.armAsync().catch(() => void 0)), C) : null;
|
|
1019
766
|
};
|
|
1020
|
-
queueMicrotask(() =>
|
|
1021
|
-
let
|
|
767
|
+
queueMicrotask(() => D());
|
|
768
|
+
let k = {
|
|
1022
769
|
get backend() {
|
|
1023
|
-
return
|
|
770
|
+
return D()?.backend ?? "webgpu";
|
|
1024
771
|
},
|
|
1025
|
-
pause: () =>
|
|
1026
|
-
resume: () =>
|
|
1027
|
-
wake: () =>
|
|
1028
|
-
renderAt: (e) => z()?.renderAt(e),
|
|
772
|
+
pause: () => D()?.suspend("manual"),
|
|
773
|
+
resume: () => D()?.resume("manual"),
|
|
774
|
+
wake: () => D()?.wake(),
|
|
1029
775
|
get reducedMotion() {
|
|
1030
|
-
return
|
|
776
|
+
return C?.reducedMotion ?? !1;
|
|
1031
777
|
},
|
|
1032
778
|
get headT() {
|
|
1033
|
-
return
|
|
779
|
+
return c.headT;
|
|
1034
780
|
},
|
|
1035
|
-
|
|
781
|
+
headTLive: A(u),
|
|
782
|
+
rendererStatus: A(w),
|
|
1036
783
|
setHeadT: (e) => {
|
|
1037
|
-
|
|
784
|
+
c.set(e), u.value = c.headT, D()?.wake();
|
|
785
|
+
},
|
|
786
|
+
flick: (e) => {
|
|
787
|
+
c.flick(e), D()?.wake();
|
|
1038
788
|
},
|
|
1039
789
|
dispose: () => {
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
790
|
+
if (E) return;
|
|
791
|
+
E = !0;
|
|
1042
792
|
let t = e.value;
|
|
1043
|
-
t &&
|
|
793
|
+
t && S(t), f.dispose(), C?.dispose();
|
|
1044
794
|
}
|
|
1045
795
|
};
|
|
1046
|
-
return
|
|
796
|
+
return O(() => k.dispose()), k;
|
|
1047
797
|
}
|
|
1048
798
|
//#endregion
|
|
1049
|
-
//#region src/components/fourier-field/FourierField.vue
|
|
1050
|
-
var
|
|
799
|
+
//#region src/components/fourier-field/FourierField.vue?vue&type=script&setup=true&lang.ts
|
|
800
|
+
var je = [
|
|
801
|
+
"role",
|
|
802
|
+
"tabindex",
|
|
803
|
+
"aria-label",
|
|
804
|
+
"aria-valuemin",
|
|
805
|
+
"aria-valuemax",
|
|
806
|
+
"aria-valuenow",
|
|
807
|
+
"aria-valuetext"
|
|
808
|
+
], Me = /*#__PURE__*/ n(/* @__PURE__ */ T({
|
|
1051
809
|
__name: "FourierField",
|
|
1052
810
|
props: {
|
|
1053
811
|
config: {},
|
|
1054
812
|
spectrum: {},
|
|
1055
813
|
getPalette: {},
|
|
1056
814
|
color: {},
|
|
1057
|
-
colorResolver: {},
|
|
1058
815
|
seed: { default: "" },
|
|
1059
816
|
freeze: {
|
|
1060
817
|
type: Boolean,
|
|
1061
818
|
default: !1
|
|
819
|
+
},
|
|
820
|
+
interactive: {
|
|
821
|
+
type: Boolean,
|
|
822
|
+
default: !0
|
|
1062
823
|
}
|
|
1063
824
|
},
|
|
1064
825
|
emits: ["rendererStatus"],
|
|
1065
|
-
setup(
|
|
1066
|
-
let
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
if (c.spectrum && c.spectrum.length > 0) return c.spectrum;
|
|
1078
|
-
let e = l[g.value.source];
|
|
1079
|
-
return e ? m(e) : p(w(T((c.freeze ? "fourier-field/frozen" : c.seed || "fourier-field") + c.seed)), {
|
|
1080
|
-
harmonics: Math.min(g.value.harmonics + 4, 62),
|
|
1081
|
-
harmonicScale: g.value.harmonicScale
|
|
1082
|
-
});
|
|
1083
|
-
}), b = () => y.value;
|
|
1084
|
-
function x(t) {
|
|
1085
|
-
if (!t.includes("var(") && !t.includes("light-dark(")) return t;
|
|
1086
|
-
let n = u.value;
|
|
1087
|
-
if (typeof window > "u" || !n) return t;
|
|
1088
|
-
if (t.includes("var(")) return e(t, n);
|
|
826
|
+
setup(e, { expose: n, emit: r }) {
|
|
827
|
+
let o = r, s = e, l = M("hostRef"), u = M("canvasRef"), { isDark: d } = i(), m = S(() => s.config ?? U), h = S(() => {
|
|
828
|
+
if (s.spectrum && s.spectrum.length > 0) return L(s.spectrum);
|
|
829
|
+
let e = m.value.source;
|
|
830
|
+
if (e !== "elliptic" && !(e in c)) throw Error(`[FourierField] unknown source "${String(e)}". Pass "elliptic", a key of FOURIER_FIGURES, or an explicit \`spectrum\`.`);
|
|
831
|
+
return L(e === "elliptic" ? f(b(x(`fourier-field/${s.seed}`)), m.value.richness) : p(c[e]));
|
|
832
|
+
}), g = () => h.value, _ = S(() => h.value.terms.length), v = S(() => Math.max(1, Math.min(Math.round(m.value.harmonics), _.value))), y = S(() => `N ${v.value}/${_.value}`);
|
|
833
|
+
function T(e) {
|
|
834
|
+
if (!e.includes("var(") && !e.includes("light-dark(")) return e;
|
|
835
|
+
let n = l.value;
|
|
836
|
+
if (typeof window > "u" || !n) return e;
|
|
837
|
+
if (e.includes("var(")) return t(e, n);
|
|
1089
838
|
let r = n.style.color;
|
|
1090
|
-
n.style.color =
|
|
839
|
+
n.style.color = e;
|
|
1091
840
|
let i = getComputedStyle(n).color;
|
|
1092
|
-
return n.style.color = r, i ||
|
|
841
|
+
return n.style.color = r, i || e;
|
|
1093
842
|
}
|
|
1094
|
-
let
|
|
1095
|
-
function
|
|
1096
|
-
if (
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
if (f.value, c.color) {
|
|
1101
|
-
let e = x(c.color);
|
|
843
|
+
let O = j(m.value.palette);
|
|
844
|
+
function A() {
|
|
845
|
+
if (s.getPalette) O.value = s.getPalette();
|
|
846
|
+
else if (s.color) {
|
|
847
|
+
d.value;
|
|
848
|
+
let e = T(s.color);
|
|
1102
849
|
if (e.includes("var(") || e.includes("light-dark(")) return;
|
|
1103
|
-
let t =
|
|
1104
|
-
|
|
850
|
+
let t = a(e);
|
|
851
|
+
O.value = [{
|
|
1105
852
|
L: Math.max(.5, t.L),
|
|
1106
853
|
C: Math.max(.12, t.C),
|
|
1107
854
|
h: t.h
|
|
@@ -1110,50 +857,91 @@ var De = /*#__PURE__*/ t(/* @__PURE__ */ k({
|
|
|
1110
857
|
C: t.C * .4,
|
|
1111
858
|
h: t.h + 18
|
|
1112
859
|
}];
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
S.value = g.value.palette;
|
|
860
|
+
} else O.value = m.value.palette;
|
|
861
|
+
if (O.value.length === 0) throw Error("[FourierField] the palette is empty — there is nothing to paint with.");
|
|
1116
862
|
}
|
|
1117
|
-
let
|
|
863
|
+
let P = Ae(u, {
|
|
1118
864
|
config: new Proxy({}, {
|
|
1119
|
-
get: (e, t) => Reflect.get(
|
|
1120
|
-
has: (e, t) => Reflect.has(
|
|
1121
|
-
ownKeys: () => Reflect.ownKeys(
|
|
1122
|
-
getOwnPropertyDescriptor: (e, t) => Reflect.getOwnPropertyDescriptor(
|
|
865
|
+
get: (e, t) => Reflect.get(m.value, t),
|
|
866
|
+
has: (e, t) => Reflect.has(m.value, t),
|
|
867
|
+
ownKeys: () => Reflect.ownKeys(m.value),
|
|
868
|
+
getOwnPropertyDescriptor: (e, t) => Reflect.getOwnPropertyDescriptor(m.value, t)
|
|
1123
869
|
}),
|
|
1124
|
-
getSpectrum:
|
|
1125
|
-
getPalette: () =>
|
|
1126
|
-
|
|
1127
|
-
|
|
870
|
+
getSpectrum: g,
|
|
871
|
+
getPalette: () => O.value,
|
|
872
|
+
interactive: () => s.interactive,
|
|
873
|
+
freeze: () => s.freeze
|
|
1128
874
|
});
|
|
1129
|
-
|
|
875
|
+
N(P.rendererStatus, (e) => o("rendererStatus", e), {
|
|
1130
876
|
immediate: !0,
|
|
1131
877
|
flush: "sync"
|
|
1132
|
-
}),
|
|
1133
|
-
() =>
|
|
1134
|
-
() =>
|
|
1135
|
-
|
|
1136
|
-
],
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
878
|
+
}), N(() => s.config, () => P.wake(), { deep: !0 }), N([
|
|
879
|
+
() => s.color,
|
|
880
|
+
() => s.getPalette,
|
|
881
|
+
d
|
|
882
|
+
], A, { immediate: !0 }), D(A), N(d, () => P.wake()), N(() => s.freeze, () => P.wake());
|
|
883
|
+
let F = j(!1), I = S(() => Number(P.headTLive.value.toFixed(3))), R = S(() => `${y.value} · ${Math.round(P.headTLive.value * 100)}% through the period`);
|
|
884
|
+
function z(e) {
|
|
885
|
+
P.setHeadT(P.headT + e);
|
|
886
|
+
}
|
|
887
|
+
function B(e) {
|
|
888
|
+
if (s.interactive) {
|
|
889
|
+
switch (e.key) {
|
|
890
|
+
case "ArrowRight":
|
|
891
|
+
z(V);
|
|
892
|
+
break;
|
|
893
|
+
case "ArrowLeft":
|
|
894
|
+
z(-V);
|
|
895
|
+
break;
|
|
896
|
+
case "ArrowUp":
|
|
897
|
+
z(H);
|
|
898
|
+
break;
|
|
899
|
+
case "ArrowDown":
|
|
900
|
+
z(-H);
|
|
901
|
+
break;
|
|
902
|
+
case "Home":
|
|
903
|
+
P.setHeadT(0);
|
|
904
|
+
break;
|
|
905
|
+
case "End":
|
|
906
|
+
P.setHeadT(.999);
|
|
907
|
+
break;
|
|
908
|
+
case " ":
|
|
909
|
+
case "Spacebar":
|
|
910
|
+
F.value = !F.value, F.value ? P.pause() : P.resume();
|
|
911
|
+
break;
|
|
912
|
+
default: return;
|
|
913
|
+
}
|
|
914
|
+
e.preventDefault();
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return n({
|
|
918
|
+
backend: () => P.backend,
|
|
919
|
+
pause: P.pause,
|
|
920
|
+
resume: P.resume,
|
|
921
|
+
wake: P.wake,
|
|
922
|
+
setHeadT: P.setHeadT,
|
|
923
|
+
headT: P.headTLive,
|
|
924
|
+
flick: P.flick,
|
|
925
|
+
rendererStatus: P.rendererStatus
|
|
926
|
+
}), (e, t) => (k(), C("div", {
|
|
1147
927
|
ref_key: "hostRef",
|
|
1148
|
-
ref:
|
|
1149
|
-
class:
|
|
1150
|
-
|
|
928
|
+
ref: l,
|
|
929
|
+
class: E(["fourier-field", { "fourier-field--interactive": s.interactive }]),
|
|
930
|
+
role: s.interactive ? "slider" : void 0,
|
|
931
|
+
tabindex: s.interactive ? 0 : void 0,
|
|
932
|
+
"aria-label": s.interactive ? "Fourier reconstruction parameter" : void 0,
|
|
933
|
+
"aria-valuemin": s.interactive ? 0 : void 0,
|
|
934
|
+
"aria-valuemax": s.interactive ? 1 : void 0,
|
|
935
|
+
"aria-valuenow": s.interactive ? I.value : void 0,
|
|
936
|
+
"aria-valuetext": s.interactive ? R.value : void 0,
|
|
937
|
+
onKeydown: B
|
|
938
|
+
}, [w("canvas", {
|
|
1151
939
|
ref_key: "canvasRef",
|
|
1152
|
-
ref:
|
|
940
|
+
ref: u,
|
|
1153
941
|
class: "fourier-field-canvas",
|
|
1154
942
|
"aria-hidden": "true"
|
|
1155
|
-
}, null, 512)],
|
|
943
|
+
}, null, 512)], 42, je));
|
|
1156
944
|
}
|
|
1157
|
-
}), [["__scopeId", "data-v-
|
|
945
|
+
}), [["__scopeId", "data-v-4f0910ab"]]);
|
|
1158
946
|
//#endregion
|
|
1159
|
-
export {
|
|
947
|
+
export { U as DEFAULT_FOURIER_CONFIG, c as FOURIER_FIGURES, l as FOURIER_FIGURE_KEYS, Me as FourierField, d as dftFromPoints, f as makeEllipticSpectrum, p as makeHarmonicFigure, L as mintSpectrum, m as partialSumAt, h as positionsAt, z as ringsAt };
|