@wave3d/core 0.1.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/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/config/model.d.ts +240 -0
- package/dist/config/model.js +496 -0
- package/dist/config/model.js.map +1 -0
- package/dist/core-loader.d.ts +10 -0
- package/dist/core-loader.js +12 -0
- package/dist/core-loader.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/presets.d.ts +8 -0
- package/dist/presets.js +544 -0
- package/dist/presets.js.map +1 -0
- package/dist/renderer/WaveGeometry.d.ts +31 -0
- package/dist/renderer/WaveGeometry.js +92 -0
- package/dist/renderer/WaveGeometry.js.map +1 -0
- package/dist/renderer/WaveRenderer.d.ts +232 -0
- package/dist/renderer/WaveRenderer.js +1118 -0
- package/dist/renderer/WaveRenderer.js.map +1 -0
- package/dist/renderer/heroPalette.d.ts +10 -0
- package/dist/renderer/heroPalette.js +34 -0
- package/dist/renderer/heroPalette.js.map +1 -0
- package/dist/renderer/index.d.ts +4 -0
- package/dist/renderer/index.js +4 -0
- package/dist/renderer/palette.d.ts +67 -0
- package/dist/renderer/palette.js +535 -0
- package/dist/renderer/palette.js.map +1 -0
- package/dist/renderer/shaders.js +545 -0
- package/dist/renderer/shaders.js.map +1 -0
- package/dist/shell/createWave.d.ts +58 -0
- package/dist/shell/createWave.js +161 -0
- package/dist/shell/createWave.js.map +1 -0
- package/dist/shell/poster.js +64 -0
- package/dist/shell/poster.js.map +1 -0
- package/dist/shell/probe.js +34 -0
- package/dist/shell/probe.js.map +1 -0
- package/dist/standalone/wave3d.standalone.js +13507 -0
- package/dist/standalone.d.ts +13 -0
- package/dist/standalone.js +17 -0
- package/dist/standalone.js.map +1 -0
- package/dist/studio/StudioWaveRenderer.d.ts +187 -0
- package/dist/studio/StudioWaveRenderer.js +905 -0
- package/dist/studio/StudioWaveRenderer.js.map +1 -0
- package/dist/studio/index.d.ts +3 -0
- package/dist/studio/index.js +3 -0
- package/dist/studio/randomize.d.ts +28 -0
- package/dist/studio/randomize.js +264 -0
- package/dist/studio/randomize.js.map +1 -0
- package/dist/util/base64.js +14 -0
- package/dist/util/base64.js.map +1 -0
- package/dist/util/math.js +18 -0
- package/dist/util/math.js.map +1 -0
- package/package.json +76 -0
- package/skills/wave3d/SKILL.md +158 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { clamp01 } from "../util/math.js";
|
|
2
|
+
import { createDefaultMeshPoints } from "../config/model.js";
|
|
3
|
+
import * as THREE from "three";
|
|
4
|
+
//#region src/renderer/palette.ts
|
|
5
|
+
/**
|
|
6
|
+
* Bakes the gradient stops into a 2D palette texture, sampled in the shader as
|
|
7
|
+
* `texture2D(u_paletteTexture, vec2(uv.x, uv.y))`. The texture is a real image, so
|
|
8
|
+
* colour can vary independently along BOTH axes:
|
|
9
|
+
* - X (uv.x, along the length): the gradient stops.
|
|
10
|
+
* - Y (uv.y, across the width): an "edge tint" blended toward both long edges
|
|
11
|
+
*/
|
|
12
|
+
const TEX_W = 256;
|
|
13
|
+
const TEX_H = 64;
|
|
14
|
+
function smoothstep(value) {
|
|
15
|
+
return value * value * (3 - 2 * value);
|
|
16
|
+
}
|
|
17
|
+
/** "#rrggbb" → "rgba(r,g,b,a)" for canvas fills with alpha. */
|
|
18
|
+
function hexToRgba(hex, alpha) {
|
|
19
|
+
const srgb = new THREE.Color(hex).clone().convertLinearToSRGB();
|
|
20
|
+
return `rgba(${Math.round(srgb.r * 255)}, ${Math.round(srgb.g * 255)}, ${Math.round(srgb.b * 255)}, ${alpha})`;
|
|
21
|
+
}
|
|
22
|
+
/** Draw the palette into a 2D canvas. */
|
|
23
|
+
function buildPaletteCanvas(opts) {
|
|
24
|
+
const canvas = document.createElement("canvas");
|
|
25
|
+
canvas.width = TEX_W;
|
|
26
|
+
canvas.height = TEX_H;
|
|
27
|
+
const ctx = canvas.getContext("2d");
|
|
28
|
+
if (!ctx) return canvas;
|
|
29
|
+
const stops = [...opts.stops].sort((a, b) => a.pos - b.pos);
|
|
30
|
+
const grad = ctx.createLinearGradient(0, 0, TEX_W, 0);
|
|
31
|
+
if (stops.length === 0) grad.addColorStop(0, "#ffffff");
|
|
32
|
+
else for (const s of stops) grad.addColorStop(clamp01(s.pos), s.color);
|
|
33
|
+
ctx.fillStyle = grad;
|
|
34
|
+
ctx.fillRect(0, 0, TEX_W, TEX_H);
|
|
35
|
+
const a = clamp01(opts.edgeAmount);
|
|
36
|
+
if (a > .001) {
|
|
37
|
+
const eg = ctx.createLinearGradient(0, 0, 0, TEX_H);
|
|
38
|
+
eg.addColorStop(0, hexToRgba(opts.edgeColor, a));
|
|
39
|
+
eg.addColorStop(.5, hexToRgba(opts.edgeColor, 0));
|
|
40
|
+
eg.addColorStop(1, hexToRgba(opts.edgeColor, a));
|
|
41
|
+
ctx.fillStyle = eg;
|
|
42
|
+
ctx.fillRect(0, 0, TEX_W, TEX_H);
|
|
43
|
+
}
|
|
44
|
+
return canvas;
|
|
45
|
+
}
|
|
46
|
+
/** A small string that changes whenever the texture would need rebuilding. */
|
|
47
|
+
function paletteSignature(opts) {
|
|
48
|
+
return `${opts.stops.map((x) => `${x.color}@${x.pos.toFixed(3)}`).join(",")}|${opts.edgeColor}|${opts.edgeAmount.toFixed(3)}`;
|
|
49
|
+
}
|
|
50
|
+
/** Sampling config shared by every palette-texture source (canvas, image, LUT, video):
|
|
51
|
+
* sRGB (the GPU linearizes on sample), linear filtering, clamped edges, no mipmaps. */
|
|
52
|
+
function configurePaletteTexture(tex) {
|
|
53
|
+
tex.colorSpace = THREE.SRGBColorSpace;
|
|
54
|
+
tex.minFilter = THREE.LinearFilter;
|
|
55
|
+
tex.magFilter = THREE.LinearFilter;
|
|
56
|
+
tex.wrapS = THREE.ClampToEdgeWrapping;
|
|
57
|
+
tex.wrapT = THREE.ClampToEdgeWrapping;
|
|
58
|
+
tex.generateMipmaps = false;
|
|
59
|
+
return tex;
|
|
60
|
+
}
|
|
61
|
+
/** Wrap a canvas as a sampling-ready CanvasTexture. */
|
|
62
|
+
function canvasToTexture(canvas) {
|
|
63
|
+
return configurePaletteTexture(new THREE.CanvasTexture(canvas));
|
|
64
|
+
}
|
|
65
|
+
/** Build a ready-to-use CanvasTexture from gradient stops + edge tint. */
|
|
66
|
+
function buildPaletteTexture(opts) {
|
|
67
|
+
return canvasToTexture(buildPaletteCanvas(opts));
|
|
68
|
+
}
|
|
69
|
+
/** Draw an export-ready linear, radial, or conic background gradient. */
|
|
70
|
+
function buildBackgroundGradientCanvas(opts) {
|
|
71
|
+
const canvas = document.createElement("canvas");
|
|
72
|
+
canvas.width = Math.max(1, Math.round(opts.width));
|
|
73
|
+
canvas.height = Math.max(1, Math.round(opts.height));
|
|
74
|
+
const ctx = canvas.getContext("2d");
|
|
75
|
+
if (!ctx) return canvas;
|
|
76
|
+
const { width, height } = canvas;
|
|
77
|
+
const cx = width / 2;
|
|
78
|
+
const cy = height / 2;
|
|
79
|
+
const angle = opts.angle * Math.PI / 180;
|
|
80
|
+
let gradient;
|
|
81
|
+
if (opts.type === "radial") gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, Math.hypot(cx, cy));
|
|
82
|
+
else if (opts.type === "conic") gradient = ctx.createConicGradient(angle, cx, cy);
|
|
83
|
+
else {
|
|
84
|
+
const radius = Math.abs(Math.sin(angle)) * cx + Math.abs(Math.cos(angle)) * cy;
|
|
85
|
+
const dx = Math.sin(angle) * radius;
|
|
86
|
+
const dy = -Math.cos(angle) * radius;
|
|
87
|
+
gradient = ctx.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy);
|
|
88
|
+
}
|
|
89
|
+
const stops = [...opts.stops].sort((a, b) => a.pos - b.pos);
|
|
90
|
+
if (stops.length === 0) gradient.addColorStop(0, "#ffffff");
|
|
91
|
+
else for (const stop of stops) gradient.addColorStop(clamp01(stop.pos), stop.color);
|
|
92
|
+
ctx.fillStyle = gradient;
|
|
93
|
+
ctx.fillRect(0, 0, width, height);
|
|
94
|
+
return canvas;
|
|
95
|
+
}
|
|
96
|
+
/** Linear (0–1) → sRGB byte (0–255). */
|
|
97
|
+
function linearToSrgbByte(linear) {
|
|
98
|
+
const c = clamp01(linear);
|
|
99
|
+
const srgb = c <= .0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - .055;
|
|
100
|
+
return Math.round(clamp01(srgb) * 255);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The single source of truth for mesh-gradient rendering — shared by the background
|
|
104
|
+
* (buildBackgroundMeshCanvas) and the on-canvas MeshGradientEditor preview, and mirroring the
|
|
105
|
+
* wave's meshGradient shader. An inverse-distance-weighted blend of coloured points, computed in
|
|
106
|
+
* LINEAR RGB with y measured UP (point.y = 1 is the top). Returns an ImageData to putImageData
|
|
107
|
+
* onto any 2D context.
|
|
108
|
+
*/
|
|
109
|
+
function renderMeshGradient(points, softness, width, height) {
|
|
110
|
+
const w = Math.max(1, Math.round(width));
|
|
111
|
+
const h = Math.max(1, Math.round(height));
|
|
112
|
+
const image = new ImageData(w, h);
|
|
113
|
+
const data = image.data;
|
|
114
|
+
const pts = points.length >= 2 ? points : createDefaultMeshPoints();
|
|
115
|
+
const colors = pts.map((p) => new THREE.Color(p.color));
|
|
116
|
+
const exponent = 4.8 + -3.4499999999999997 * clamp01(softness);
|
|
117
|
+
for (let py = 0; py < h; py++) {
|
|
118
|
+
const y = 1 - py / Math.max(1, h - 1);
|
|
119
|
+
for (let px = 0; px < w; px++) {
|
|
120
|
+
const x = px / Math.max(1, w - 1);
|
|
121
|
+
let r = 0;
|
|
122
|
+
let g = 0;
|
|
123
|
+
let b = 0;
|
|
124
|
+
let weightSum = 0;
|
|
125
|
+
for (let i = 0; i < pts.length; i++) {
|
|
126
|
+
const influence = Math.max(pts[i].influence, .05);
|
|
127
|
+
const distance = Math.hypot(x - pts[i].x, y - pts[i].y) / influence;
|
|
128
|
+
const weight = 1 / (Math.pow(Math.max(distance, .012), exponent) + .002);
|
|
129
|
+
r += colors[i].r * weight;
|
|
130
|
+
g += colors[i].g * weight;
|
|
131
|
+
b += colors[i].b * weight;
|
|
132
|
+
weightSum += weight;
|
|
133
|
+
}
|
|
134
|
+
const iw = Math.max(weightSum, 1e-4);
|
|
135
|
+
const off = (py * w + px) * 4;
|
|
136
|
+
data[off] = linearToSrgbByte(r / iw);
|
|
137
|
+
data[off + 1] = linearToSrgbByte(g / iw);
|
|
138
|
+
data[off + 2] = linearToSrgbByte(b / iw);
|
|
139
|
+
data[off + 3] = 255;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return image;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Draw a mesh-gradient background. Mesh gradients are low-frequency, so we render at a small
|
|
146
|
+
* internal size (capped ~320 px) via renderMeshGradient and scale up smoothly.
|
|
147
|
+
*/
|
|
148
|
+
function buildBackgroundMeshCanvas(points, softness, width, height) {
|
|
149
|
+
const canvas = document.createElement("canvas");
|
|
150
|
+
canvas.width = Math.max(1, Math.round(width));
|
|
151
|
+
canvas.height = Math.max(1, Math.round(height));
|
|
152
|
+
const ctx = canvas.getContext("2d");
|
|
153
|
+
if (!ctx) return canvas;
|
|
154
|
+
const scale = Math.min(1, 320 / Math.max(canvas.width, canvas.height));
|
|
155
|
+
const lw = Math.max(2, Math.round(canvas.width * scale));
|
|
156
|
+
const lh = Math.max(2, Math.round(canvas.height * scale));
|
|
157
|
+
const buf = document.createElement("canvas");
|
|
158
|
+
buf.width = lw;
|
|
159
|
+
buf.height = lh;
|
|
160
|
+
const bctx = buf.getContext("2d");
|
|
161
|
+
if (!bctx) return canvas;
|
|
162
|
+
bctx.putImageData(renderMeshGradient(points, softness, lw, lh), 0, 0);
|
|
163
|
+
ctx.imageSmoothingEnabled = true;
|
|
164
|
+
ctx.imageSmoothingQuality = "high";
|
|
165
|
+
ctx.drawImage(buf, 0, 0, lw, lh, 0, 0, canvas.width, canvas.height);
|
|
166
|
+
return canvas;
|
|
167
|
+
}
|
|
168
|
+
/** Fit a built-in canvas or uploaded image into a background-sized canvas. */
|
|
169
|
+
function buildBackgroundImageCanvas(source, sourceWidth, sourceHeight, width, height, fit, matte, zoom = 1, positionX = 0, positionY = 0) {
|
|
170
|
+
const canvas = document.createElement("canvas");
|
|
171
|
+
canvas.width = Math.max(1, Math.round(width));
|
|
172
|
+
canvas.height = Math.max(1, Math.round(height));
|
|
173
|
+
drawBackgroundMediaFrame(canvas, source, sourceWidth, sourceHeight, fit, matte, zoom, positionX, positionY);
|
|
174
|
+
return canvas;
|
|
175
|
+
}
|
|
176
|
+
/** Draw one image or video frame into an existing fitted background canvas. */
|
|
177
|
+
function drawBackgroundMediaFrame(canvas, source, sourceWidth, sourceHeight, fit, matte, zoom = 1, positionX = 0, positionY = 0) {
|
|
178
|
+
const ctx = canvas.getContext("2d");
|
|
179
|
+
if (!ctx) return;
|
|
180
|
+
ctx.fillStyle = matte;
|
|
181
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
182
|
+
const safeZoom = Math.max(.1, zoom);
|
|
183
|
+
const baseWidth = fit === "stretch" ? canvas.width : sourceWidth * (fit === "contain" ? Math.min(canvas.width / sourceWidth, canvas.height / sourceHeight) : Math.max(canvas.width / sourceWidth, canvas.height / sourceHeight));
|
|
184
|
+
const baseHeight = fit === "stretch" ? canvas.height : sourceHeight * (fit === "contain" ? Math.min(canvas.width / sourceWidth, canvas.height / sourceHeight) : Math.max(canvas.width / sourceWidth, canvas.height / sourceHeight));
|
|
185
|
+
const drawWidth = baseWidth * safeZoom;
|
|
186
|
+
const drawHeight = baseHeight * safeZoom;
|
|
187
|
+
const offsetX = positionX / 100 * canvas.width;
|
|
188
|
+
const offsetY = positionY / 100 * canvas.height;
|
|
189
|
+
ctx.drawImage(source, (canvas.width - drawWidth) / 2 + offsetX, (canvas.height - drawHeight) / 2 + offsetY, drawWidth, drawHeight);
|
|
190
|
+
}
|
|
191
|
+
const mk = (pairs) => pairs.map(([color, pos]) => ({
|
|
192
|
+
color,
|
|
193
|
+
pos
|
|
194
|
+
}));
|
|
195
|
+
function valueNoise2D(seed) {
|
|
196
|
+
const hash = (x, y) => {
|
|
197
|
+
let h = x * 374761393 + y * 668265263 + seed * 1442695041 | 0;
|
|
198
|
+
h = Math.imul(h ^ h >>> 13, 1274126177);
|
|
199
|
+
return ((h ^ h >>> 16) >>> 0) / 4294967295;
|
|
200
|
+
};
|
|
201
|
+
return (x, y) => {
|
|
202
|
+
const xi = Math.floor(x);
|
|
203
|
+
const yi = Math.floor(y);
|
|
204
|
+
const u = smoothstep(x - xi);
|
|
205
|
+
const v = smoothstep(y - yi);
|
|
206
|
+
const a = hash(xi, yi);
|
|
207
|
+
const b = hash(xi + 1, yi);
|
|
208
|
+
const c = hash(xi, yi + 1);
|
|
209
|
+
const d = hash(xi + 1, yi + 1);
|
|
210
|
+
return a * (1 - u) * (1 - v) + b * u * (1 - v) + c * (1 - u) * v + d * u * v;
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function fbm(n, x, y, oct) {
|
|
214
|
+
let s = 0;
|
|
215
|
+
let amp = .5;
|
|
216
|
+
let f = 1;
|
|
217
|
+
let tot = 0;
|
|
218
|
+
for (let i = 0; i < oct; i++) {
|
|
219
|
+
s += amp * n(x * f, y * f);
|
|
220
|
+
tot += amp;
|
|
221
|
+
f *= 2;
|
|
222
|
+
amp *= .5;
|
|
223
|
+
}
|
|
224
|
+
return s / tot;
|
|
225
|
+
}
|
|
226
|
+
const nebulaCache = /* @__PURE__ */ new Map();
|
|
227
|
+
function buildNebulaCanvas(resolution = 220) {
|
|
228
|
+
const N = Math.max(64, Math.min(1280, Math.round(resolution)));
|
|
229
|
+
const cached = nebulaCache.get(N);
|
|
230
|
+
if (cached) return cached;
|
|
231
|
+
const cv = document.createElement("canvas");
|
|
232
|
+
cv.width = N;
|
|
233
|
+
cv.height = N;
|
|
234
|
+
const ctx = cv.getContext("2d");
|
|
235
|
+
if (!ctx) return cv;
|
|
236
|
+
const img = ctx.createImageData(N, N);
|
|
237
|
+
const field = valueNoise2D(11);
|
|
238
|
+
const warp = valueNoise2D(91);
|
|
239
|
+
const bloomN = valueNoise2D(47);
|
|
240
|
+
const COLORS = [
|
|
241
|
+
[0, [
|
|
242
|
+
34,
|
|
243
|
+
26,
|
|
244
|
+
92
|
|
245
|
+
]],
|
|
246
|
+
[.24, [
|
|
247
|
+
104,
|
|
248
|
+
48,
|
|
249
|
+
196
|
|
250
|
+
]],
|
|
251
|
+
[.46, [
|
|
252
|
+
226,
|
|
253
|
+
70,
|
|
254
|
+
158
|
|
255
|
+
]],
|
|
256
|
+
[.64, [
|
|
257
|
+
255,
|
|
258
|
+
122,
|
|
259
|
+
92
|
|
260
|
+
]],
|
|
261
|
+
[.82, [
|
|
262
|
+
255,
|
|
263
|
+
202,
|
|
264
|
+
110
|
|
265
|
+
]],
|
|
266
|
+
[1, [
|
|
267
|
+
70,
|
|
268
|
+
196,
|
|
269
|
+
188
|
|
270
|
+
]]
|
|
271
|
+
];
|
|
272
|
+
const ramp = (t) => {
|
|
273
|
+
t = clamp01(t);
|
|
274
|
+
for (let i = 1; i < COLORS.length; i++) if (t <= COLORS[i][0]) {
|
|
275
|
+
const [p0, c0] = COLORS[i - 1];
|
|
276
|
+
const [p1, c1] = COLORS[i];
|
|
277
|
+
const k = (t - p0) / (p1 - p0);
|
|
278
|
+
return [
|
|
279
|
+
c0[0] + (c1[0] - c0[0]) * k,
|
|
280
|
+
c0[1] + (c1[1] - c0[1]) * k,
|
|
281
|
+
c0[2] + (c1[2] - c0[2]) * k
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
return COLORS[COLORS.length - 1][1];
|
|
285
|
+
};
|
|
286
|
+
const S = 3;
|
|
287
|
+
for (let y = 0; y < N; y++) for (let x = 0; x < N; x++) {
|
|
288
|
+
const u = x / N * S;
|
|
289
|
+
const v = y / N * S;
|
|
290
|
+
const wx = u + .7 * warp(u * .7 + 5, v * .7);
|
|
291
|
+
const wy = v + .7 * warp(u * .7, v * .7 + 9);
|
|
292
|
+
let [r, g, b] = ramp(fbm(field, wx, wy, 4));
|
|
293
|
+
const bloom = Math.max(0, fbm(bloomN, wx * 1.6 + 3, wy * 1.6, 3) - .55) * 1.7;
|
|
294
|
+
r = r * (1 - bloom) + 70 * bloom;
|
|
295
|
+
g = g * (1 - bloom) + 210 * bloom;
|
|
296
|
+
b = b * (1 - bloom) + 200 * bloom;
|
|
297
|
+
const i = (y * N + x) * 4;
|
|
298
|
+
img.data[i] = r;
|
|
299
|
+
img.data[i + 1] = g;
|
|
300
|
+
img.data[i + 2] = b;
|
|
301
|
+
img.data[i + 3] = 255;
|
|
302
|
+
}
|
|
303
|
+
ctx.putImageData(img, 0, 0);
|
|
304
|
+
nebulaCache.set(N, cv);
|
|
305
|
+
return cv;
|
|
306
|
+
}
|
|
307
|
+
const imageMapCache = /* @__PURE__ */ new Map();
|
|
308
|
+
function cachedImageMap(id, width, height, paint) {
|
|
309
|
+
const cacheKey = `${id}|${width}x${height}`;
|
|
310
|
+
const cached = imageMapCache.get(cacheKey);
|
|
311
|
+
if (cached) return cached;
|
|
312
|
+
const canvas = document.createElement("canvas");
|
|
313
|
+
canvas.width = width;
|
|
314
|
+
canvas.height = height;
|
|
315
|
+
const ctx = canvas.getContext("2d");
|
|
316
|
+
if (ctx) paint(ctx, width, height);
|
|
317
|
+
imageMapCache.set(cacheKey, canvas);
|
|
318
|
+
return canvas;
|
|
319
|
+
}
|
|
320
|
+
function buildVaporwaveCanvas(resolution = 240) {
|
|
321
|
+
const width = Math.max(120, Math.min(2048, Math.round(resolution)));
|
|
322
|
+
return cachedImageMap("vaporwave", width, Math.round(width * 2 / 3), (ctx, canvasWidth, canvasHeight) => {
|
|
323
|
+
const unit = canvasWidth / 240;
|
|
324
|
+
const sky = ctx.createLinearGradient(0, 0, 0, canvasHeight);
|
|
325
|
+
sky.addColorStop(0, "#120638");
|
|
326
|
+
sky.addColorStop(.56, "#8e2de2");
|
|
327
|
+
sky.addColorStop(1, "#ff2fa8");
|
|
328
|
+
ctx.fillStyle = sky;
|
|
329
|
+
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
|
330
|
+
const sunY = canvasHeight * .48;
|
|
331
|
+
const sunRadius = canvasHeight * .28;
|
|
332
|
+
const sun = ctx.createLinearGradient(0, sunY - sunRadius, 0, sunY + sunRadius);
|
|
333
|
+
sun.addColorStop(0, "#fff66d");
|
|
334
|
+
sun.addColorStop(1, "#ff5cbe");
|
|
335
|
+
ctx.fillStyle = sun;
|
|
336
|
+
ctx.beginPath();
|
|
337
|
+
ctx.arc(canvasWidth / 2, sunY, sunRadius, 0, Math.PI * 2);
|
|
338
|
+
ctx.fill();
|
|
339
|
+
ctx.fillStyle = "#3b126c";
|
|
340
|
+
for (let y = sunY + 3 * unit; y < sunY + sunRadius; y += 9 * unit) ctx.fillRect(canvasWidth / 2 - sunRadius, y, sunRadius * 2, 4 * unit);
|
|
341
|
+
const horizon = canvasHeight * .72;
|
|
342
|
+
ctx.fillStyle = "#09051f";
|
|
343
|
+
ctx.fillRect(0, horizon, canvasWidth, canvasHeight - horizon);
|
|
344
|
+
ctx.strokeStyle = "#19e3ff";
|
|
345
|
+
ctx.lineWidth = Math.max(1, unit);
|
|
346
|
+
ctx.globalAlpha = .72;
|
|
347
|
+
for (let x = -canvasWidth; x <= canvasWidth * 2; x += canvasWidth / 12) {
|
|
348
|
+
ctx.beginPath();
|
|
349
|
+
ctx.moveTo(canvasWidth / 2, horizon);
|
|
350
|
+
ctx.lineTo(x, canvasHeight);
|
|
351
|
+
ctx.stroke();
|
|
352
|
+
}
|
|
353
|
+
for (let row = 0; row < 7; row++) {
|
|
354
|
+
const t = row / 6;
|
|
355
|
+
const y = horizon + (canvasHeight - horizon) * t * t;
|
|
356
|
+
ctx.beginPath();
|
|
357
|
+
ctx.moveTo(0, y);
|
|
358
|
+
ctx.lineTo(canvasWidth, y);
|
|
359
|
+
ctx.stroke();
|
|
360
|
+
}
|
|
361
|
+
ctx.globalAlpha = 1;
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function buildKaleidoscopeCanvas(resolution = 220) {
|
|
365
|
+
const size = Math.max(110, Math.min(2048, Math.round(resolution)));
|
|
366
|
+
return cachedImageMap("kaleidoscope", size, size, (ctx, width, height) => {
|
|
367
|
+
const unit = width / 220;
|
|
368
|
+
const colors = [
|
|
369
|
+
"#00e5ff",
|
|
370
|
+
"#6c3bff",
|
|
371
|
+
"#ff2ca8",
|
|
372
|
+
"#ff7a00",
|
|
373
|
+
"#ffe600",
|
|
374
|
+
"#16f7a6"
|
|
375
|
+
];
|
|
376
|
+
const cx = width / 2;
|
|
377
|
+
const cy = height / 2;
|
|
378
|
+
const radius = Math.hypot(width, height);
|
|
379
|
+
const slices = 24;
|
|
380
|
+
for (let i = 0; i < slices; i++) {
|
|
381
|
+
const a0 = i / slices * Math.PI * 2;
|
|
382
|
+
const a1 = (i + 1) / slices * Math.PI * 2;
|
|
383
|
+
ctx.fillStyle = colors[i * 5 % colors.length];
|
|
384
|
+
ctx.beginPath();
|
|
385
|
+
ctx.moveTo(cx, cy);
|
|
386
|
+
ctx.lineTo(cx + Math.cos(a0) * radius, cy + Math.sin(a0) * radius);
|
|
387
|
+
ctx.lineTo(cx + Math.cos(a1) * radius, cy + Math.sin(a1) * radius);
|
|
388
|
+
ctx.closePath();
|
|
389
|
+
ctx.fill();
|
|
390
|
+
}
|
|
391
|
+
for (let ring = 1; ring <= 4; ring++) {
|
|
392
|
+
ctx.strokeStyle = ring % 2 ? "rgba(255,255,255,.55)" : "rgba(8,5,35,.6)";
|
|
393
|
+
ctx.lineWidth = 5 * unit;
|
|
394
|
+
ctx.beginPath();
|
|
395
|
+
ctx.arc(cx, cy, ring * 25 * unit, 0, Math.PI * 2);
|
|
396
|
+
ctx.stroke();
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
/** Named palette maps. "gradient" kinds are stop presets; "image" kinds are true 2-D maps. */
|
|
401
|
+
const PALETTE_MAPS = {
|
|
402
|
+
palestine: {
|
|
403
|
+
label: "Palestine",
|
|
404
|
+
kind: "gradient",
|
|
405
|
+
stops: mk([
|
|
406
|
+
["#000000", 0],
|
|
407
|
+
["#f7f7f2", .34],
|
|
408
|
+
["#149954", .67],
|
|
409
|
+
["#e4312b", 1]
|
|
410
|
+
]),
|
|
411
|
+
edgeColor: "#e4312b",
|
|
412
|
+
edgeAmount: .22
|
|
413
|
+
},
|
|
414
|
+
grandLine: {
|
|
415
|
+
label: "Grand Line",
|
|
416
|
+
kind: "gradient",
|
|
417
|
+
stops: mk([
|
|
418
|
+
["#071b33", 0],
|
|
419
|
+
["#087ea4", .22],
|
|
420
|
+
["#45d4c5", .4],
|
|
421
|
+
["#f4d35e", .58],
|
|
422
|
+
["#f2b84b", .72],
|
|
423
|
+
["#d62828", .86],
|
|
424
|
+
["#18130f", 1]
|
|
425
|
+
]),
|
|
426
|
+
edgeColor: "#061426",
|
|
427
|
+
edgeAmount: .28
|
|
428
|
+
},
|
|
429
|
+
vaporwave: {
|
|
430
|
+
label: "Vaporwave Sunset",
|
|
431
|
+
kind: "image",
|
|
432
|
+
build: buildVaporwaveCanvas
|
|
433
|
+
},
|
|
434
|
+
kaleidoscope: {
|
|
435
|
+
label: "Kaleidoscope",
|
|
436
|
+
kind: "image",
|
|
437
|
+
build: buildKaleidoscopeCanvas
|
|
438
|
+
},
|
|
439
|
+
nebula: {
|
|
440
|
+
label: "Nebula (2D)",
|
|
441
|
+
kind: "image",
|
|
442
|
+
build: buildNebulaCanvas
|
|
443
|
+
},
|
|
444
|
+
sunset: {
|
|
445
|
+
label: "Sunset",
|
|
446
|
+
kind: "gradient",
|
|
447
|
+
stops: mk([
|
|
448
|
+
["#3b1c6b", 0],
|
|
449
|
+
["#8b2fa0", .3],
|
|
450
|
+
["#e0457a", .56],
|
|
451
|
+
["#ff7a3d", .8],
|
|
452
|
+
["#ffd166", 1]
|
|
453
|
+
]),
|
|
454
|
+
edgeColor: "#2a1a6b",
|
|
455
|
+
edgeAmount: .3
|
|
456
|
+
},
|
|
457
|
+
aurora: {
|
|
458
|
+
label: "Aurora",
|
|
459
|
+
kind: "gradient",
|
|
460
|
+
stops: mk([
|
|
461
|
+
["#0b3d4f", 0],
|
|
462
|
+
["#1fb89e", .3],
|
|
463
|
+
["#5ee0a0", .52],
|
|
464
|
+
["#4d8ef0", .76],
|
|
465
|
+
["#9b5de5", 1]
|
|
466
|
+
]),
|
|
467
|
+
edgeColor: "#0a2540",
|
|
468
|
+
edgeAmount: .35
|
|
469
|
+
},
|
|
470
|
+
ocean: {
|
|
471
|
+
label: "Ocean",
|
|
472
|
+
kind: "gradient",
|
|
473
|
+
stops: mk([
|
|
474
|
+
["#0a1f4d", 0],
|
|
475
|
+
["#1f6fb8", .36],
|
|
476
|
+
["#2bd0d0", .66],
|
|
477
|
+
["#a8f0e2", 1]
|
|
478
|
+
]),
|
|
479
|
+
edgeColor: "#061233",
|
|
480
|
+
edgeAmount: .4
|
|
481
|
+
},
|
|
482
|
+
ember: {
|
|
483
|
+
label: "Ember",
|
|
484
|
+
kind: "gradient",
|
|
485
|
+
stops: mk([
|
|
486
|
+
["#2a0707", 0],
|
|
487
|
+
["#a81e1e", .34],
|
|
488
|
+
["#ff5a2e", .64],
|
|
489
|
+
["#ffd24a", 1]
|
|
490
|
+
]),
|
|
491
|
+
edgeColor: "#150404",
|
|
492
|
+
edgeAmount: .28
|
|
493
|
+
},
|
|
494
|
+
iris: {
|
|
495
|
+
label: "Iris",
|
|
496
|
+
kind: "gradient",
|
|
497
|
+
stops: mk([
|
|
498
|
+
["#2e1065", 0],
|
|
499
|
+
["#7c3aed", .34],
|
|
500
|
+
["#db2777", .64],
|
|
501
|
+
["#f5b8f0", 1]
|
|
502
|
+
]),
|
|
503
|
+
edgeColor: "#1a0840",
|
|
504
|
+
edgeAmount: .35
|
|
505
|
+
},
|
|
506
|
+
mono: {
|
|
507
|
+
label: "Mono",
|
|
508
|
+
kind: "gradient",
|
|
509
|
+
stops: mk([
|
|
510
|
+
["#16161e", 0],
|
|
511
|
+
["#6b7280", .4],
|
|
512
|
+
["#c2c8d2", .72],
|
|
513
|
+
["#f6f8fb", 1]
|
|
514
|
+
]),
|
|
515
|
+
edgeColor: "#0a0a12",
|
|
516
|
+
edgeAmount: .2
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
/** The canvas for a named map (its 2-D image, or its stops+edge gradient). */
|
|
520
|
+
function paletteMapCanvas(def, resolution) {
|
|
521
|
+
if (def.build) return def.build(resolution);
|
|
522
|
+
return buildPaletteCanvas({
|
|
523
|
+
stops: def.stops ?? [],
|
|
524
|
+
edgeColor: def.edgeColor ?? "#8e9dff",
|
|
525
|
+
edgeAmount: def.edgeAmount ?? 0
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
/** Load an arbitrary image (URL or object-URL) as a palette texture — "bring your own map". */
|
|
529
|
+
function loadPaletteImage(url) {
|
|
530
|
+
return configurePaletteTexture(new THREE.TextureLoader().load(url));
|
|
531
|
+
}
|
|
532
|
+
//#endregion
|
|
533
|
+
export { PALETTE_MAPS, buildBackgroundGradientCanvas, buildBackgroundImageCanvas, buildBackgroundMeshCanvas, buildPaletteCanvas, buildPaletteTexture, canvasToTexture, configurePaletteTexture, drawBackgroundMediaFrame, loadPaletteImage, paletteMapCanvas, paletteSignature, renderMeshGradient };
|
|
534
|
+
|
|
535
|
+
//# sourceMappingURL=palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette.js","names":[],"sources":["../../src/renderer/palette.ts"],"sourcesContent":["import * as THREE from \"three\";\nimport { clamp01 } from \"../util/math\";\nimport { createDefaultMeshPoints } from \"../config/model\";\nimport type {\n BackgroundImageFit,\n BasicGradientType,\n ColorStop,\n MeshGradientPoint,\n} from \"../config/model\";\n\n/**\n * Bakes the gradient stops into a 2D palette texture, sampled in the shader as\n * `texture2D(u_paletteTexture, vec2(uv.x, uv.y))`. The texture is a real image, so\n * colour can vary independently along BOTH axes:\n * - X (uv.x, along the length): the gradient stops.\n * - Y (uv.y, across the width): an \"edge tint\" blended toward both long edges\n */\n\nconst TEX_W = 256; // resolution along the gradient (length)\nconst TEX_H = 64; // resolution across the width\n\nfunction smoothstep(value: number): number {\n return value * value * (3 - 2 * value);\n}\n\n/** \"#rrggbb\" → \"rgba(r,g,b,a)\" for canvas fills with alpha. */\nfunction hexToRgba(hex: string, alpha: number): string {\n const c = new THREE.Color(hex); // parses many formats; .r/.g/.b are linear…\n // …but we want the original sRGB bytes for the canvas, so re-encode.\n const srgb = c.clone().convertLinearToSRGB();\n const r = Math.round(srgb.r * 255);\n const g = Math.round(srgb.g * 255);\n const b = Math.round(srgb.b * 255);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nexport interface PaletteTextureOptions {\n stops: ColorStop[];\n /** Cross-width edge tint colour (e.g. periwinkle). */\n edgeColor: string;\n /** 0 = flat 1-D gradient (no 2nd axis); higher = stronger cool edges. */\n edgeAmount: number;\n}\n\n/** Draw the palette into a 2D canvas. */\nexport function buildPaletteCanvas(opts: PaletteTextureOptions): HTMLCanvasElement {\n const canvas = document.createElement(\"canvas\");\n canvas.width = TEX_W;\n canvas.height = TEX_H;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return canvas;\n\n // X axis: the main gradient (stops sorted by position).\n const stops = [...opts.stops].sort((a, b) => a.pos - b.pos);\n const grad = ctx.createLinearGradient(0, 0, TEX_W, 0);\n if (stops.length === 0) {\n grad.addColorStop(0, \"#ffffff\");\n } else {\n for (const s of stops) grad.addColorStop(clamp01(s.pos), s.color);\n }\n ctx.fillStyle = grad;\n ctx.fillRect(0, 0, TEX_W, TEX_H);\n\n // Y axis: blend the edge colour toward both long edges (V-shaped alpha), 0 in the\n // middle — a genuine second dimension of colour.\n const a = clamp01(opts.edgeAmount);\n if (a > 0.001) {\n const eg = ctx.createLinearGradient(0, 0, 0, TEX_H);\n eg.addColorStop(0, hexToRgba(opts.edgeColor, a));\n eg.addColorStop(0.5, hexToRgba(opts.edgeColor, 0));\n eg.addColorStop(1, hexToRgba(opts.edgeColor, a));\n ctx.fillStyle = eg;\n ctx.fillRect(0, 0, TEX_W, TEX_H);\n }\n\n return canvas;\n}\n\n/** A small string that changes whenever the texture would need rebuilding. */\nexport function paletteSignature(opts: PaletteTextureOptions): string {\n const s = opts.stops.map((x) => `${x.color}@${x.pos.toFixed(3)}`).join(\",\");\n return `${s}|${opts.edgeColor}|${opts.edgeAmount.toFixed(3)}`;\n}\n\n/** Sampling config shared by every palette-texture source (canvas, image, LUT, video):\n * sRGB (the GPU linearizes on sample), linear filtering, clamped edges, no mipmaps. */\nexport function configurePaletteTexture<T extends THREE.Texture>(tex: T): T {\n tex.colorSpace = THREE.SRGBColorSpace;\n tex.minFilter = THREE.LinearFilter;\n tex.magFilter = THREE.LinearFilter;\n tex.wrapS = THREE.ClampToEdgeWrapping;\n tex.wrapT = THREE.ClampToEdgeWrapping;\n tex.generateMipmaps = false;\n return tex;\n}\n\n/** Wrap a canvas as a sampling-ready CanvasTexture. */\nexport function canvasToTexture(canvas: HTMLCanvasElement): THREE.CanvasTexture {\n return configurePaletteTexture(new THREE.CanvasTexture(canvas));\n}\n\n/** Build a ready-to-use CanvasTexture from gradient stops + edge tint. */\nexport function buildPaletteTexture(opts: PaletteTextureOptions): THREE.CanvasTexture {\n return canvasToTexture(buildPaletteCanvas(opts));\n}\n\nexport interface BackgroundGradientOptions {\n stops: ColorStop[];\n type: BasicGradientType;\n angle: number;\n width: number;\n height: number;\n}\n\n/** Draw an export-ready linear, radial, or conic background gradient. */\nexport function buildBackgroundGradientCanvas(opts: BackgroundGradientOptions): HTMLCanvasElement {\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.max(1, Math.round(opts.width));\n canvas.height = Math.max(1, Math.round(opts.height));\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return canvas;\n\n const { width, height } = canvas;\n const cx = width / 2;\n const cy = height / 2;\n const angle = (opts.angle * Math.PI) / 180;\n let gradient: CanvasGradient;\n if (opts.type === \"radial\") {\n gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, Math.hypot(cx, cy));\n } else if (opts.type === \"conic\") {\n gradient = ctx.createConicGradient(angle, cx, cy);\n } else {\n const radius = Math.abs(Math.sin(angle)) * cx + Math.abs(Math.cos(angle)) * cy;\n const dx = Math.sin(angle) * radius;\n const dy = -Math.cos(angle) * radius;\n gradient = ctx.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy);\n }\n\n const stops = [...opts.stops].sort((a, b) => a.pos - b.pos);\n if (stops.length === 0) gradient.addColorStop(0, \"#ffffff\");\n else for (const stop of stops) gradient.addColorStop(clamp01(stop.pos), stop.color);\n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, width, height);\n return canvas;\n}\n\n/** Linear (0–1) → sRGB byte (0–255). */\nfunction linearToSrgbByte(linear: number): number {\n const c = clamp01(linear);\n const srgb = c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n return Math.round(clamp01(srgb) * 255);\n}\n\n/**\n * The single source of truth for mesh-gradient rendering — shared by the background\n * (buildBackgroundMeshCanvas) and the on-canvas MeshGradientEditor preview, and mirroring the\n * wave's meshGradient shader. An inverse-distance-weighted blend of coloured points, computed in\n * LINEAR RGB with y measured UP (point.y = 1 is the top). Returns an ImageData to putImageData\n * onto any 2D context.\n */\nexport function renderMeshGradient(\n points: MeshGradientPoint[],\n softness: number,\n width: number,\n height: number,\n): ImageData {\n const w = Math.max(1, Math.round(width));\n const h = Math.max(1, Math.round(height));\n const image = new ImageData(w, h);\n const data = image.data;\n const pts = points.length >= 2 ? points : createDefaultMeshPoints();\n const colors = pts.map((p) => new THREE.Color(p.color)); // .r/.g/.b are LINEAR\n const exponent = 4.8 + (1.35 - 4.8) * clamp01(softness);\n for (let py = 0; py < h; py++) {\n const y = 1 - py / Math.max(1, h - 1);\n for (let px = 0; px < w; px++) {\n const x = px / Math.max(1, w - 1);\n let r = 0;\n let g = 0;\n let b = 0;\n let weightSum = 0;\n for (let i = 0; i < pts.length; i++) {\n const influence = Math.max(pts[i].influence, 0.05);\n const distance = Math.hypot(x - pts[i].x, y - pts[i].y) / influence;\n const weight = 1 / (Math.pow(Math.max(distance, 0.012), exponent) + 0.002);\n r += colors[i].r * weight;\n g += colors[i].g * weight;\n b += colors[i].b * weight;\n weightSum += weight;\n }\n const iw = Math.max(weightSum, 0.0001);\n const off = (py * w + px) * 4;\n data[off] = linearToSrgbByte(r / iw);\n data[off + 1] = linearToSrgbByte(g / iw);\n data[off + 2] = linearToSrgbByte(b / iw);\n data[off + 3] = 255;\n }\n }\n return image;\n}\n\n/**\n * Draw a mesh-gradient background. Mesh gradients are low-frequency, so we render at a small\n * internal size (capped ~320 px) via renderMeshGradient and scale up smoothly.\n */\nexport function buildBackgroundMeshCanvas(\n points: MeshGradientPoint[],\n softness: number,\n width: number,\n height: number,\n): HTMLCanvasElement {\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.max(1, Math.round(width));\n canvas.height = Math.max(1, Math.round(height));\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return canvas;\n\n const scale = Math.min(1, 320 / Math.max(canvas.width, canvas.height));\n const lw = Math.max(2, Math.round(canvas.width * scale));\n const lh = Math.max(2, Math.round(canvas.height * scale));\n const buf = document.createElement(\"canvas\");\n buf.width = lw;\n buf.height = lh;\n const bctx = buf.getContext(\"2d\");\n if (!bctx) return canvas;\n bctx.putImageData(renderMeshGradient(points, softness, lw, lh), 0, 0);\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = \"high\";\n ctx.drawImage(buf, 0, 0, lw, lh, 0, 0, canvas.width, canvas.height);\n return canvas;\n}\n\n/** Fit a built-in canvas or uploaded image into a background-sized canvas. */\nexport function buildBackgroundImageCanvas(\n source: CanvasImageSource,\n sourceWidth: number,\n sourceHeight: number,\n width: number,\n height: number,\n fit: BackgroundImageFit,\n matte: string,\n zoom = 1,\n positionX = 0,\n positionY = 0,\n): HTMLCanvasElement {\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.max(1, Math.round(width));\n canvas.height = Math.max(1, Math.round(height));\n drawBackgroundMediaFrame(\n canvas,\n source,\n sourceWidth,\n sourceHeight,\n fit,\n matte,\n zoom,\n positionX,\n positionY,\n );\n return canvas;\n}\n\n/** Draw one image or video frame into an existing fitted background canvas. */\nexport function drawBackgroundMediaFrame(\n canvas: HTMLCanvasElement,\n source: CanvasImageSource,\n sourceWidth: number,\n sourceHeight: number,\n fit: BackgroundImageFit,\n matte: string,\n zoom = 1,\n positionX = 0,\n positionY = 0,\n): void {\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n ctx.fillStyle = matte;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n const safeZoom = Math.max(0.1, zoom);\n const baseWidth =\n fit === \"stretch\"\n ? canvas.width\n : sourceWidth *\n (fit === \"contain\"\n ? Math.min(canvas.width / sourceWidth, canvas.height / sourceHeight)\n : Math.max(canvas.width / sourceWidth, canvas.height / sourceHeight));\n const baseHeight =\n fit === \"stretch\"\n ? canvas.height\n : sourceHeight *\n (fit === \"contain\"\n ? Math.min(canvas.width / sourceWidth, canvas.height / sourceHeight)\n : Math.max(canvas.width / sourceWidth, canvas.height / sourceHeight));\n const drawWidth = baseWidth * safeZoom;\n const drawHeight = baseHeight * safeZoom;\n const offsetX = (positionX / 100) * canvas.width;\n const offsetY = (positionY / 100) * canvas.height;\n ctx.drawImage(\n source,\n (canvas.width - drawWidth) / 2 + offsetX,\n (canvas.height - drawHeight) / 2 + offsetY,\n drawWidth,\n drawHeight,\n );\n}\n\n// ---- Built-in palette maps (pick via config.paletteSource) ----\n\nexport interface PaletteMapDef {\n label: string;\n /** \"gradient\" = a color-stop preset (1-D ramp + edge tint, reproducible with stops);\n * \"image\" = a true 2-D texture (build()) that the stops can't reproduce. */\n kind: \"gradient\" | \"image\";\n stops?: ColorStop[];\n edgeColor?: string;\n edgeAmount?: number;\n build?: (resolution?: number) => HTMLCanvasElement;\n}\n\nconst mk = (pairs: Array<[string, number]>): ColorStop[] =>\n pairs.map(([color, pos]) => ({ color, pos }));\n\n// ---- A genuine 2-D image map (procedural nebula): organic colour patches that vary in\n// BOTH axes via domain-warped value noise — the kind of thing flat stops can't make. ----\n\nfunction valueNoise2D(seed: number): (x: number, y: number) => number {\n const hash = (x: number, y: number): number => {\n let h = (x * 374761393 + y * 668265263 + seed * 1442695041) | 0;\n h = Math.imul(h ^ (h >>> 13), 1274126177);\n return ((h ^ (h >>> 16)) >>> 0) / 4294967295;\n };\n return (x, y) => {\n const xi = Math.floor(x);\n const yi = Math.floor(y);\n const u = smoothstep(x - xi);\n const v = smoothstep(y - yi);\n const a = hash(xi, yi);\n const b = hash(xi + 1, yi);\n const c = hash(xi, yi + 1);\n const d = hash(xi + 1, yi + 1);\n return a * (1 - u) * (1 - v) + b * u * (1 - v) + c * (1 - u) * v + d * u * v;\n };\n}\n\nfunction fbm(n: (x: number, y: number) => number, x: number, y: number, oct: number): number {\n let s = 0;\n let amp = 0.5;\n let f = 1;\n let tot = 0;\n for (let i = 0; i < oct; i++) {\n s += amp * n(x * f, y * f);\n tot += amp;\n f *= 2;\n amp *= 0.5;\n }\n return s / tot;\n}\n\nconst nebulaCache = new Map<number, HTMLCanvasElement>();\nfunction buildNebulaCanvas(resolution = 220): HTMLCanvasElement {\n const N = Math.max(64, Math.min(1280, Math.round(resolution)));\n const cached = nebulaCache.get(N);\n if (cached) return cached;\n const cv = document.createElement(\"canvas\");\n cv.width = N;\n cv.height = N;\n const ctx = cv.getContext(\"2d\");\n if (!ctx) return cv;\n const img = ctx.createImageData(N, N);\n const field = valueNoise2D(11);\n const warp = valueNoise2D(91);\n const bloomN = valueNoise2D(47);\n const COLORS: Array<[number, [number, number, number]]> = [\n [0.0, [34, 26, 92]], // deep indigo\n [0.24, [104, 48, 196]], // violet\n [0.46, [226, 70, 158]], // magenta\n [0.64, [255, 122, 92]], // coral\n [0.82, [255, 202, 110]], // gold\n [1.0, [70, 196, 188]], // teal\n ];\n const ramp = (t: number): [number, number, number] => {\n t = clamp01(t);\n for (let i = 1; i < COLORS.length; i++) {\n if (t <= COLORS[i][0]) {\n const [p0, c0] = COLORS[i - 1];\n const [p1, c1] = COLORS[i];\n const k = (t - p0) / (p1 - p0);\n return [\n c0[0] + (c1[0] - c0[0]) * k,\n c0[1] + (c1[1] - c0[1]) * k,\n c0[2] + (c1[2] - c0[2]) * k,\n ];\n }\n }\n return COLORS[COLORS.length - 1][1];\n };\n const S = 3.0;\n for (let y = 0; y < N; y++) {\n for (let x = 0; x < N; x++) {\n const u = (x / N) * S;\n const v = (y / N) * S;\n const wx = u + 0.7 * warp(u * 0.7 + 5, v * 0.7);\n const wy = v + 0.7 * warp(u * 0.7, v * 0.7 + 9);\n const f = fbm(field, wx, wy, 4);\n let [r, g, b] = ramp(f);\n const bloom = Math.max(0, fbm(bloomN, wx * 1.6 + 3, wy * 1.6, 3) - 0.55) * 1.7;\n r = r * (1 - bloom) + 70 * bloom;\n g = g * (1 - bloom) + 210 * bloom;\n b = b * (1 - bloom) + 200 * bloom;\n const i = (y * N + x) * 4;\n img.data[i] = r;\n img.data[i + 1] = g;\n img.data[i + 2] = b;\n img.data[i + 3] = 255;\n }\n }\n ctx.putImageData(img, 0, 0);\n nebulaCache.set(N, cv);\n return cv;\n}\n\nconst imageMapCache = new Map<string, HTMLCanvasElement>();\n\nfunction cachedImageMap(\n id: string,\n width: number,\n height: number,\n paint: (ctx: CanvasRenderingContext2D, width: number, height: number) => void,\n): HTMLCanvasElement {\n const cacheKey = `${id}|${width}x${height}`;\n const cached = imageMapCache.get(cacheKey);\n if (cached) return cached;\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) paint(ctx, width, height);\n imageMapCache.set(cacheKey, canvas);\n return canvas;\n}\n\nfunction buildVaporwaveCanvas(resolution = 240): HTMLCanvasElement {\n const width = Math.max(120, Math.min(2048, Math.round(resolution)));\n const height = Math.round((width * 2) / 3);\n return cachedImageMap(\"vaporwave\", width, height, (ctx, canvasWidth, canvasHeight) => {\n const unit = canvasWidth / 240;\n const sky = ctx.createLinearGradient(0, 0, 0, canvasHeight);\n sky.addColorStop(0, \"#120638\");\n sky.addColorStop(0.56, \"#8e2de2\");\n sky.addColorStop(1, \"#ff2fa8\");\n ctx.fillStyle = sky;\n ctx.fillRect(0, 0, canvasWidth, canvasHeight);\n\n const sunY = canvasHeight * 0.48;\n const sunRadius = canvasHeight * 0.28;\n const sun = ctx.createLinearGradient(0, sunY - sunRadius, 0, sunY + sunRadius);\n sun.addColorStop(0, \"#fff66d\");\n sun.addColorStop(1, \"#ff5cbe\");\n ctx.fillStyle = sun;\n ctx.beginPath();\n ctx.arc(canvasWidth / 2, sunY, sunRadius, 0, Math.PI * 2);\n ctx.fill();\n\n ctx.fillStyle = \"#3b126c\";\n for (let y = sunY + 3 * unit; y < sunY + sunRadius; y += 9 * unit) {\n ctx.fillRect(canvasWidth / 2 - sunRadius, y, sunRadius * 2, 4 * unit);\n }\n\n const horizon = canvasHeight * 0.72;\n ctx.fillStyle = \"#09051f\";\n ctx.fillRect(0, horizon, canvasWidth, canvasHeight - horizon);\n ctx.strokeStyle = \"#19e3ff\";\n ctx.lineWidth = Math.max(1, unit);\n ctx.globalAlpha = 0.72;\n for (let x = -canvasWidth; x <= canvasWidth * 2; x += canvasWidth / 12) {\n ctx.beginPath();\n ctx.moveTo(canvasWidth / 2, horizon);\n ctx.lineTo(x, canvasHeight);\n ctx.stroke();\n }\n for (let row = 0; row < 7; row++) {\n const t = row / 6;\n const y = horizon + (canvasHeight - horizon) * t * t;\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(canvasWidth, y);\n ctx.stroke();\n }\n ctx.globalAlpha = 1;\n });\n}\n\nfunction buildKaleidoscopeCanvas(resolution = 220): HTMLCanvasElement {\n const size = Math.max(110, Math.min(2048, Math.round(resolution)));\n return cachedImageMap(\"kaleidoscope\", size, size, (ctx, width, height) => {\n const unit = width / 220;\n const colors = [\"#00e5ff\", \"#6c3bff\", \"#ff2ca8\", \"#ff7a00\", \"#ffe600\", \"#16f7a6\"];\n const cx = width / 2;\n const cy = height / 2;\n const radius = Math.hypot(width, height);\n const slices = 24;\n for (let i = 0; i < slices; i++) {\n const a0 = (i / slices) * Math.PI * 2;\n const a1 = ((i + 1) / slices) * Math.PI * 2;\n ctx.fillStyle = colors[(i * 5) % colors.length];\n ctx.beginPath();\n ctx.moveTo(cx, cy);\n ctx.lineTo(cx + Math.cos(a0) * radius, cy + Math.sin(a0) * radius);\n ctx.lineTo(cx + Math.cos(a1) * radius, cy + Math.sin(a1) * radius);\n ctx.closePath();\n ctx.fill();\n }\n for (let ring = 1; ring <= 4; ring++) {\n ctx.strokeStyle = ring % 2 ? \"rgba(255,255,255,.55)\" : \"rgba(8,5,35,.6)\";\n ctx.lineWidth = 5 * unit;\n ctx.beginPath();\n ctx.arc(cx, cy, ring * 25 * unit, 0, Math.PI * 2);\n ctx.stroke();\n }\n });\n}\n\n/** Named palette maps. \"gradient\" kinds are stop presets; \"image\" kinds are true 2-D maps. */\nexport const PALETTE_MAPS: Record<string, PaletteMapDef> = {\n palestine: {\n label: \"Palestine\",\n kind: \"gradient\",\n stops: mk([\n [\"#000000\", 0],\n [\"#f7f7f2\", 0.34],\n [\"#149954\", 0.67],\n [\"#e4312b\", 1],\n ]),\n edgeColor: \"#e4312b\",\n edgeAmount: 0.22,\n },\n grandLine: {\n label: \"Grand Line\",\n kind: \"gradient\",\n stops: mk([\n [\"#071b33\", 0],\n [\"#087ea4\", 0.22],\n [\"#45d4c5\", 0.4],\n [\"#f4d35e\", 0.58],\n [\"#f2b84b\", 0.72],\n [\"#d62828\", 0.86],\n [\"#18130f\", 1],\n ]),\n edgeColor: \"#061426\",\n edgeAmount: 0.28,\n },\n vaporwave: { label: \"Vaporwave Sunset\", kind: \"image\", build: buildVaporwaveCanvas },\n kaleidoscope: { label: \"Kaleidoscope\", kind: \"image\", build: buildKaleidoscopeCanvas },\n nebula: { label: \"Nebula (2D)\", kind: \"image\", build: buildNebulaCanvas },\n sunset: {\n label: \"Sunset\",\n kind: \"gradient\",\n stops: mk([\n [\"#3b1c6b\", 0],\n [\"#8b2fa0\", 0.3],\n [\"#e0457a\", 0.56],\n [\"#ff7a3d\", 0.8],\n [\"#ffd166\", 1],\n ]),\n edgeColor: \"#2a1a6b\",\n edgeAmount: 0.3,\n },\n aurora: {\n label: \"Aurora\",\n kind: \"gradient\",\n stops: mk([\n [\"#0b3d4f\", 0],\n [\"#1fb89e\", 0.3],\n [\"#5ee0a0\", 0.52],\n [\"#4d8ef0\", 0.76],\n [\"#9b5de5\", 1],\n ]),\n edgeColor: \"#0a2540\",\n edgeAmount: 0.35,\n },\n ocean: {\n label: \"Ocean\",\n kind: \"gradient\",\n stops: mk([\n [\"#0a1f4d\", 0],\n [\"#1f6fb8\", 0.36],\n [\"#2bd0d0\", 0.66],\n [\"#a8f0e2\", 1],\n ]),\n edgeColor: \"#061233\",\n edgeAmount: 0.4,\n },\n ember: {\n label: \"Ember\",\n kind: \"gradient\",\n stops: mk([\n [\"#2a0707\", 0],\n [\"#a81e1e\", 0.34],\n [\"#ff5a2e\", 0.64],\n [\"#ffd24a\", 1],\n ]),\n edgeColor: \"#150404\",\n edgeAmount: 0.28,\n },\n iris: {\n label: \"Iris\",\n kind: \"gradient\",\n stops: mk([\n [\"#2e1065\", 0],\n [\"#7c3aed\", 0.34],\n [\"#db2777\", 0.64],\n [\"#f5b8f0\", 1],\n ]),\n edgeColor: \"#1a0840\",\n edgeAmount: 0.35,\n },\n mono: {\n label: \"Mono\",\n kind: \"gradient\",\n stops: mk([\n [\"#16161e\", 0],\n [\"#6b7280\", 0.4],\n [\"#c2c8d2\", 0.72],\n [\"#f6f8fb\", 1],\n ]),\n edgeColor: \"#0a0a12\",\n edgeAmount: 0.2,\n },\n};\n\n/** The canvas for a named map (its 2-D image, or its stops+edge gradient). */\nexport function paletteMapCanvas(def: PaletteMapDef, resolution?: number): HTMLCanvasElement {\n if (def.build) return def.build(resolution);\n return buildPaletteCanvas({\n stops: def.stops ?? [],\n edgeColor: def.edgeColor ?? \"#8e9dff\",\n edgeAmount: def.edgeAmount ?? 0,\n });\n}\n\n/** Load an arbitrary image (URL or object-URL) as a palette texture — \"bring your own map\". */\nexport function loadPaletteImage(url: string): THREE.Texture {\n return configurePaletteTexture(new THREE.TextureLoader().load(url));\n}\n"],"mappings":"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"}
|