@frapx/core 0.4.0 → 0.5.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1 - 2026-10-20
4
+
5
+ ### Fixed
6
+
7
+ - The host's `onResize` now also fires when a frame is the first to see a new size. Browsers run animation frames before resize observations, so in a running realtime loop the frame took the new size and the resize observer then found nothing changed: `onResize` almost never fired while playing. It runs before that frame's draw.
8
+
9
+ ## 0.5.0 - 2026-10-15
10
+
11
+ ### Added
12
+
13
+ - `ShaderCompileError` carries `stage` (`"vertex"`, `"fragment"`, `"link"` or `null`) and `lines`: each error the driver's info log locates, with its line number, message, that source line and two lines of context either side (`ShaderErrorLine`). The message is still the raw log.
14
+ - `parseShaderLog(log, source)` for runtimes that compile their own shaders.
15
+ - `keyframes(tracks, { ease })`: a dependency-free `UniformSource` that interpolates float and vec2–vec4 keyframes per component, with `"linear"`, `"smooth"`, `"step"` or custom eases.
16
+ - `createUniformBindings()`: ordered `UniformSource`s merged into normalized uniforms for a time, for runtimes that implement `bindUniforms()`.
17
+
18
+ ### Fixed
19
+
20
+ - `createProgram()` no longer leaks the compiled vertex shader when the fragment shader fails to compile.
21
+ - After a WebGL context is restored, an instance that was not running (stopped, or on a manual clock) returns to its previous status instead of staying `"context-lost"`, and a stopped realtime instance redraws.
22
+
3
23
  ## 0.4.0 - 2026-10-13
4
24
 
5
25
  ### Added
package/README.md CHANGED
@@ -2,9 +2,20 @@
2
2
 
3
3
  Shared WebGL runtime host for `@frapx` packages.
4
4
 
5
- This package provides the core WebGL lifecycle engine (canvas setup, context management, animation loop, a11y gates) shared between `@frapx/fx-canvas` and future frapx packages. It is a low-level building block and its API may change between minor versions while `@frapx/core` remains at `0.x`.
5
+ This package is the lifecycle engine (canvas setup, context management and restore, animation loop and clocks, a11y gates, frame capture) shared by `@frapx/fx-canvas`, `@frapx/fx-passes` and `@frapx/fx-particles`. It is a low-level building block and its API may change between minor versions while `@frapx/core` remains at `0.x`.
6
6
 
7
- If you are building a WebGL experience, you most likely want [`@frapx/fx-canvas`](https://www.npmjs.com/package/@frapx/fx-canvas) instead.
7
+ If you are building a WebGL experience, you most likely want [`@frapx/fx-canvas`](https://www.npmjs.com/package/@frapx/fx-canvas) (or another `fx-*` package) instead.
8
+
9
+ ## Exports
10
+
11
+ For building a new `fx-*` runtime on the same host:
12
+
13
+ - `createRuntimeHost(options)` — the host: canvas setup, `realtime` / `manual` clocks, fixed `resolution`, offscreen / hidden / reduced-motion gates, context loss and restore, and `captureFrame()`. A runtime plugs in through `createContext`, `onInit`, `onDraw`, `onCaptureDraw`, `captureSource`, `onResize` and the context hooks.
14
+ - Programs and uniforms — `createProgram`, `createFullscreenProgram`, `createFullscreenBuffer`, `collectUniformLocations`, `applyUniform(s)`, `normalizeUniform`, `createUniformCache`, `toUniformName` / `fromUniformName`.
15
+ - Textures and targets — `loadTexture`, `createTextureSet`, `createRenderTarget`, `createPingPong`, `supportsRenderTargetFormat`, `resolveRenderTargetFormat`, `createBlitter`.
16
+ - Timelines — `createUniformBindings`, `keyframes`.
17
+ - Helpers — `waitForGpu`, `glsl`, `glslUtils`, `hexToRgb` / `hexToRgba`, `parseShaderLog`, `isWebGL2Context`, `isGLSL300`, `setupCanvas`, `resolveDpr`.
18
+ - Errors — `ShaderError`, `ShaderCompileError`, `UnsupportedError`, `TargetNotFoundError`, `TextureLoadError`, `DestroyedError`.
8
19
 
9
20
  ## License
10
21
 
package/dist/index.d.ts CHANGED
@@ -219,17 +219,111 @@ declare const waitForGpu: (gl: GLContext) => Promise<void>;
219
219
  declare class ShaderError extends Error {
220
220
  constructor(message: string);
221
221
  }
222
+ /** One line of a shader compile error, located in the source that was compiled. */
223
+ type ShaderErrorLine = {
224
+ /** 1-based line in the compiled source (after `glsl` template interpolation). */
225
+ line: number;
226
+ message: string;
227
+ /** That line of the source, or "" when the log points past the end. */
228
+ source: string;
229
+ /** Up to two lines either side, with their numbers, the error line included. */
230
+ context: ReadonlyArray<{
231
+ line: number;
232
+ source: string;
233
+ }>;
234
+ };
235
+ /** `"link"` for program link errors, which carry no line numbers. */
236
+ type ShaderStage = "vertex" | "fragment" | "link";
222
237
  declare class UnsupportedError extends ShaderError {
223
238
  }
224
239
  declare class TargetNotFoundError extends ShaderError {
225
240
  }
226
241
  declare class ShaderCompileError extends ShaderError {
242
+ /** The stage that failed, or `null` for errors not tied to compiling a shader. */
243
+ readonly stage: ShaderStage | null;
244
+ /** Errors located in the source, parsed from the driver's info log. Empty when it had none. */
245
+ readonly lines: readonly ShaderErrorLine[];
246
+ constructor(message: string, details?: {
247
+ stage?: ShaderStage;
248
+ lines?: readonly ShaderErrorLine[];
249
+ });
227
250
  }
228
251
  declare class TextureLoadError extends ShaderError {
229
252
  }
230
253
  declare class DestroyedError extends ShaderError {
231
254
  }
232
255
 
256
+ /**
257
+ * Finds the errors in a shader info log and attaches the source lines they
258
+ * point at. Lines the log does not locate are left out; the log itself stays
259
+ * the error message.
260
+ */
261
+ declare const parseShaderLog: (log: string, source: string) => ShaderErrorLine[];
262
+
263
+ type NormalizedUniform = {
264
+ type: UniformType;
265
+ value: number[] | Float32Array;
266
+ };
267
+ declare const normalizeUniform: (input: UniformInput) => NormalizedUniform;
268
+ declare const applyUniform: (gl: GLContext, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
269
+ declare const applyProgramUniform: (gl: GLContext, program: WebGLProgram, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
270
+ /**
271
+ * Uploads every cached uniform to the bound program. Calls `onMissing` with
272
+ * the name of each uniform the program lacks or optimized out.
273
+ */
274
+ declare const applyUniforms: (gl: GLContext, locations: ReadonlyMap<string, WebGLUniformLocation>, cache: ReadonlyMap<string, NormalizedUniform>, onMissing?: (name: string) => void) => void;
275
+ declare const collectUniformLocations: (gl: GLContext, program: WebGLProgram) => Map<string, WebGLUniformLocation>;
276
+ declare const createUniformCache: (uniforms: Record<string, UniformInput> | undefined) => Map<string, NormalizedUniform>;
277
+
278
+ /**
279
+ * Supplies uniform values for a time, such as a keyframe timeline. Runtimes
280
+ * call `get()` with the same time as `u_time` before drawing.
281
+ */
282
+ type UniformSource = {
283
+ get(time: number): Readonly<Record<string, UniformInput>>;
284
+ };
285
+ /** Ordered sources whose values override the runtime's own uniforms. */
286
+ type UniformBindings = {
287
+ /** Adds `source`; a later source wins for the same name. Returns its removal. */
288
+ add(source: UniformSource): () => void;
289
+ readonly size: number;
290
+ /** Merged, normalized values at `time`, keyed by uniform name (`u_` prefixed). */
291
+ evaluate(time: number): Map<string, NormalizedUniform>;
292
+ /** A stable string of the values at `time`, to notice when they change. */
293
+ signature(time: number): string;
294
+ };
295
+ declare const createUniformBindings: () => UniformBindings;
296
+ type KeyframeValue = number | readonly [number, number] | readonly [number, number, number] | readonly [number, number, number, number];
297
+ /** `[time in seconds, value]`. */
298
+ type Keyframe = readonly [number, KeyframeValue];
299
+ /**
300
+ * How a segment eases from one key to the next: `"linear"`, `"smooth"`
301
+ * (smoothstep), `"step"` (hold the earlier key), or a function of the
302
+ * segment's 0–1 progress.
303
+ */
304
+ type Ease = "linear" | "smooth" | "step" | ((t: number) => number);
305
+ type KeyframeTrack = readonly Keyframe[] | {
306
+ keys: readonly Keyframe[];
307
+ ease?: Ease;
308
+ };
309
+ type KeyframeOptions = {
310
+ /** Default ease for tracks that do not set their own. Defaults to `"linear"`. */
311
+ ease?: Ease;
312
+ };
313
+ /**
314
+ * A `UniformSource` that interpolates keyframes per component: floats and
315
+ * vec2–vec4 as tuples. Keys may come in any order; times before the first key
316
+ * or after the last hold that key's value.
317
+ *
318
+ * ```ts
319
+ * fx.bindUniforms(keyframes({
320
+ * camPos: [[0, [0, 1, 6]], [4, [3, 1.5, 2]]],
321
+ * glow: { keys: [[0, 0], [2, 1]], ease: "smooth" }
322
+ * }));
323
+ * ```
324
+ */
325
+ declare const keyframes: (tracks: Readonly<Record<string, KeyframeTrack>>, options?: KeyframeOptions) => UniformSource;
326
+
233
327
  declare const toUniformName: (name: string) => string;
234
328
  declare const fromUniformName: (name: string) => string;
235
329
 
@@ -299,21 +393,6 @@ type TextureSet = {
299
393
  */
300
394
  declare const createTextureSet: (inputs?: TextureMap) => TextureSet;
301
395
 
302
- type NormalizedUniform = {
303
- type: UniformType;
304
- value: number[] | Float32Array;
305
- };
306
- declare const normalizeUniform: (input: UniformInput) => NormalizedUniform;
307
- declare const applyUniform: (gl: GLContext, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
308
- declare const applyProgramUniform: (gl: GLContext, program: WebGLProgram, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
309
- /**
310
- * Uploads every cached uniform to the bound program. Calls `onMissing` with
311
- * the name of each uniform the program lacks or optimized out.
312
- */
313
- declare const applyUniforms: (gl: GLContext, locations: ReadonlyMap<string, WebGLUniformLocation>, cache: ReadonlyMap<string, NormalizedUniform>, onMissing?: (name: string) => void) => void;
314
- declare const collectUniformLocations: (gl: GLContext, program: WebGLProgram) => Map<string, WebGLUniformLocation>;
315
- declare const createUniformCache: (uniforms: Record<string, UniformInput> | undefined) => Map<string, NormalizedUniform>;
316
-
317
396
  type FullscreenProgram = {
318
397
  readonly program: WebGLProgram;
319
398
  /** Active uniform locations by name, array uniforms without `[0]`. */
@@ -383,4 +462,4 @@ declare const createRenderTarget: (gl: GLContext, width: number, height: number,
383
462
  */
384
463
  declare const createPingPong: (gl: GLContext, width: number, height: number, options?: RenderTargetOptions) => PingPong;
385
464
 
386
- export { type Blitter, type CaptureFormat, type CaptureOptions, type CaptureResult, type ClockMode, DestroyedError, type DomSetup, type DprOption, type ExplicitUniformInput, type FullscreenProgram, type GLContext, type HostFrameState, type HostPointer, type LoadedTexture, type NormalizedUniform, type PingPong, type RenderMode, type RenderTarget, type RenderTargetFormat, type RenderTargetOptions, type Resolution, type RuntimeHostInstance, type RuntimeHostOptions, type SetupCanvasOptions, ShaderCompileError, ShaderError, type ShaderLayer, type ShaderStatus, TargetNotFoundError, type TextureInput, TextureLoadError, type TextureMap, type TextureOptions, type TextureSet, type TextureSource, type UniformInput, type UniformInputMap, type UniformRuntimeValue, type UniformScalar, type UniformType, type UniformVec2, type UniformVec3, type UniformVec4, UnsupportedError, applyProgramUniform, applyUniform, applyUniforms, collectUniformLocations, createBlitter, createFullscreenBuffer, createFullscreenProgram, createPingPong, createProgram, createRenderTarget, createRuntimeHost, createTextureSet, createUniformCache, defaultVertexShader, defaultVertexShader300, fromUniformName, isGLSL300, isWebGL2Context, loadTexture, normalizeUniform, resizeCanvasToTarget, resolveDpr, resolveElement, resolveRenderTargetFormat, setupCanvas, supportsRenderTargetFormat, toUniformName, waitForGpu };
465
+ export { type Blitter, type CaptureFormat, type CaptureOptions, type CaptureResult, type ClockMode, DestroyedError, type DomSetup, type DprOption, type Ease, type ExplicitUniformInput, type FullscreenProgram, type GLContext, type HostFrameState, type HostPointer, type Keyframe, type KeyframeOptions, type KeyframeTrack, type KeyframeValue, type LoadedTexture, type NormalizedUniform, type PingPong, type RenderMode, type RenderTarget, type RenderTargetFormat, type RenderTargetOptions, type Resolution, type RuntimeHostInstance, type RuntimeHostOptions, type SetupCanvasOptions, ShaderCompileError, ShaderError, type ShaderErrorLine, type ShaderLayer, type ShaderStage, type ShaderStatus, TargetNotFoundError, type TextureInput, TextureLoadError, type TextureMap, type TextureOptions, type TextureSet, type TextureSource, type UniformBindings, type UniformInput, type UniformInputMap, type UniformRuntimeValue, type UniformScalar, type UniformSource, type UniformType, type UniformVec2, type UniformVec3, type UniformVec4, UnsupportedError, applyProgramUniform, applyUniform, applyUniforms, collectUniformLocations, createBlitter, createFullscreenBuffer, createFullscreenProgram, createPingPong, createProgram, createRenderTarget, createRuntimeHost, createTextureSet, createUniformBindings, createUniformCache, defaultVertexShader, defaultVertexShader300, fromUniformName, isGLSL300, isWebGL2Context, keyframes, loadTexture, normalizeUniform, parseShaderLog, resizeCanvasToTarget, resolveDpr, resolveElement, resolveRenderTargetFormat, setupCanvas, supportsRenderTargetFormat, toUniformName, waitForGpu };
package/dist/index.js CHANGED
@@ -19,12 +19,47 @@ var UnsupportedError = class extends ShaderError {
19
19
  var TargetNotFoundError = class extends ShaderError {
20
20
  };
21
21
  var ShaderCompileError = class extends ShaderError {
22
+ constructor(message, details = {}) {
23
+ super(message);
24
+ this.stage = details.stage ?? null;
25
+ this.lines = details.lines ?? [];
26
+ }
22
27
  };
23
28
  var TextureLoadError = class extends ShaderError {
24
29
  };
25
30
  var DestroyedError = class extends ShaderError {
26
31
  };
27
32
 
33
+ // src/internal/shaderLog.ts
34
+ var ANGLE_STYLE = /^\s*ERROR:\s*\d+:(\d+):\s*(.*)$/;
35
+ var NVIDIA_STYLE = /^\s*\d+\((\d+)\)\s*:\s*error\s*\w*\s*:\s*(.*)$/i;
36
+ var NOISE = /compilation terminated|^\s*''\s*:\s*$/i;
37
+ var CONTEXT_LINES = 2;
38
+ var parseShaderLog = (log, source) => {
39
+ const sourceLines = source.split(/\r?\n/);
40
+ const lineAt = (line) => sourceLines[line - 1] ?? "";
41
+ const results = [];
42
+ const seen = /* @__PURE__ */ new Set();
43
+ for (const entry of log.split(/\r?\n/)) {
44
+ const match = ANGLE_STYLE.exec(entry) ?? NVIDIA_STYLE.exec(entry);
45
+ if (!match) continue;
46
+ const line = Number(match[1]);
47
+ const message = match[2].trim();
48
+ if (!message || NOISE.test(message)) continue;
49
+ const key = `${line}:${message}`;
50
+ if (seen.has(key)) continue;
51
+ seen.add(key);
52
+ const context = [];
53
+ const first = Math.max(1, line - CONTEXT_LINES);
54
+ const last = Math.min(sourceLines.length, line + CONTEXT_LINES);
55
+ for (let current = first; current <= last; current++) {
56
+ context.push({ line: current, source: lineAt(current) });
57
+ }
58
+ results.push({ line, message, source: lineAt(line), context });
59
+ }
60
+ return results;
61
+ };
62
+
28
63
  // src/internal/webgl.ts
29
64
  var defaultVertexShader = `
30
65
  attribute vec2 a_position;
@@ -48,7 +83,13 @@ var isGLSL300 = (src) => /^\s*#version\s+300\s+es\b/.test(src);
48
83
  var isWebGL2Context = (gl) => typeof gl.createVertexArray === "function";
49
84
  var createProgram = (gl, vertexSource, fragmentSource) => {
50
85
  const vertex = compileShader(gl, gl.VERTEX_SHADER, vertexSource);
51
- const fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
86
+ let fragment;
87
+ try {
88
+ fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
89
+ } catch (error) {
90
+ gl.deleteShader(vertex);
91
+ throw error;
92
+ }
52
93
  const program = gl.createProgram();
53
94
  if (!program) {
54
95
  throw new ShaderCompileError("Failed to create WebGL program.");
@@ -61,7 +102,7 @@ var createProgram = (gl, vertexSource, fragmentSource) => {
61
102
  gl.deleteProgram(program);
62
103
  gl.deleteShader(vertex);
63
104
  gl.deleteShader(fragment);
64
- throw new ShaderCompileError(log);
105
+ throw new ShaderCompileError(log, { stage: "link" });
65
106
  }
66
107
  gl.deleteShader(vertex);
67
108
  gl.deleteShader(fragment);
@@ -95,7 +136,10 @@ var compileShader = (gl, type, source) => {
95
136
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
96
137
  const log = gl.getShaderInfoLog(shader) ?? "Unknown shader compile error.";
97
138
  gl.deleteShader(shader);
98
- throw new ShaderCompileError(log);
139
+ throw new ShaderCompileError(log, {
140
+ stage: type === gl.VERTEX_SHADER ? "vertex" : "fragment",
141
+ lines: parseShaderLog(log, source)
142
+ });
99
143
  }
100
144
  return shader;
101
145
  };
@@ -276,6 +320,7 @@ var RuntimeHost = class {
276
320
  this.removeListeners = [];
277
321
  this.currentStatus = "idle";
278
322
  this.contextRestoredShouldRun = false;
323
+ this.statusBeforeLoss = "idle";
279
324
  this.manualDelta = 0;
280
325
  this.lastManualTime = null;
281
326
  this.objectFitRestore = null;
@@ -409,15 +454,7 @@ var RuntimeHost = class {
409
454
  this.resizePending = true;
410
455
  return;
411
456
  }
412
- const prevWidth = this.width;
413
- const prevHeight = this.height;
414
- const prevViewportWidth = this.viewportWidth;
415
- const prevViewportHeight = this.viewportHeight;
416
- this.measureSize();
417
- const sizeChanged = this.width !== prevWidth || this.height !== prevHeight || this.viewportWidth !== prevViewportWidth || this.viewportHeight !== prevViewportHeight;
418
- if (sizeChanged && this.context) {
419
- this.options.onResize?.(this.createFrameState(this.elapsed, 0));
420
- }
457
+ this.syncSize();
421
458
  if (this.shouldRenderOnDemand && !this.inRender) {
422
459
  this.render();
423
460
  }
@@ -505,7 +542,7 @@ var RuntimeHost = class {
505
542
  const gl = this.context;
506
543
  this.inRender = true;
507
544
  try {
508
- this.measureSize();
545
+ this.syncSize();
509
546
  this.options.onDraw(this.createFrameState(time, delta, gl));
510
547
  this.frame++;
511
548
  } finally {
@@ -519,7 +556,7 @@ var RuntimeHost = class {
519
556
  this.inRender = true;
520
557
  this.captureDrawing = true;
521
558
  try {
522
- this.measureSize();
559
+ this.syncSize();
523
560
  await draw(this.createFrameState(this.elapsed, delta, this.context), signal);
524
561
  this.frame++;
525
562
  } finally {
@@ -569,6 +606,22 @@ var RuntimeHost = class {
569
606
  pointer: this.isManual ? { ...IDLE_POINTER } : { ...this.pointer }
570
607
  };
571
608
  }
609
+ /**
610
+ * Measures the size and calls onResize if it changed. Frames measure too:
611
+ * browsers run animation frames before resize observations, so in a running
612
+ * loop a frame is usually the first to see a new size.
613
+ */
614
+ syncSize() {
615
+ const prevWidth = this.width;
616
+ const prevHeight = this.height;
617
+ const prevViewportWidth = this.viewportWidth;
618
+ const prevViewportHeight = this.viewportHeight;
619
+ this.measureSize();
620
+ const sizeChanged = this.width !== prevWidth || this.height !== prevHeight || this.viewportWidth !== prevViewportWidth || this.viewportHeight !== prevViewportHeight;
621
+ if (sizeChanged && this.context) {
622
+ this.options.onResize?.(this.createFrameState(this.elapsed, 0));
623
+ }
624
+ }
572
625
  measureSize() {
573
626
  if (!this.dom) return;
574
627
  if (this.fixedResolution) {
@@ -788,6 +841,7 @@ var RuntimeHost = class {
788
841
  const onLost = (event) => {
789
842
  event.preventDefault();
790
843
  this.contextRestoredShouldRun = this.running;
844
+ this.statusBeforeLoss = this.currentStatus;
791
845
  this.cancelFrame();
792
846
  this.context = null;
793
847
  this.currentStatus = "context-lost";
@@ -802,6 +856,7 @@ var RuntimeHost = class {
802
856
  const afterRestore = async () => {
803
857
  try {
804
858
  await this.options.onContextRestored?.(gl, this.width, this.height);
859
+ if (this.currentStatus === "context-lost") this.currentStatus = this.statusBeforeLoss;
805
860
  if (this.contextRestoredShouldRun) this.start();
806
861
  else if (!this.isManual) this.render();
807
862
  } catch (error) {
@@ -861,6 +916,211 @@ var assertWithinLimits = (gl, resolution) => {
861
916
  var toUniformName = (name) => name.startsWith("u_") ? name : `u_${name}`;
862
917
  var fromUniformName = (name) => name.startsWith("u_") ? name.slice(2) : name;
863
918
 
919
+ // src/internal/uniforms.ts
920
+ var normalizeUniform = (input) => {
921
+ if (typeof input === "number") {
922
+ return { type: "float", value: [input] };
923
+ }
924
+ if (input instanceof Float32Array) {
925
+ if (input.length === 9) return { type: "mat3", value: input };
926
+ if (input.length === 16) return { type: "mat4", value: input };
927
+ if (input.length === 2) return { type: "vec2", value: input };
928
+ if (input.length === 3) return { type: "vec3", value: input };
929
+ if (input.length === 4) return { type: "vec4", value: input };
930
+ }
931
+ if (isExplicitUniform(input)) {
932
+ return { type: input.type, value: input.value };
933
+ }
934
+ if (Array.isArray(input)) {
935
+ if (input.length === 2) return { type: "vec2", value: input };
936
+ if (input.length === 3) return { type: "vec3", value: input };
937
+ if (input.length === 4) return { type: "vec4", value: input };
938
+ }
939
+ return { type: "float", value: [0] };
940
+ };
941
+ var applyUniform = (gl, location, uniform) => {
942
+ const value = uniform.value;
943
+ switch (uniform.type) {
944
+ case "float":
945
+ gl.uniform1f(location, value[0] ?? 0);
946
+ break;
947
+ case "vec2":
948
+ gl.uniform2f(location, value[0] ?? 0, value[1] ?? 0);
949
+ break;
950
+ case "vec3":
951
+ gl.uniform3f(location, value[0] ?? 0, value[1] ?? 0, value[2] ?? 0);
952
+ break;
953
+ case "vec4":
954
+ gl.uniform4f(
955
+ location,
956
+ value[0] ?? 0,
957
+ value[1] ?? 0,
958
+ value[2] ?? 0,
959
+ value[3] ?? 0
960
+ );
961
+ break;
962
+ case "mat3":
963
+ gl.uniformMatrix3fv(location, false, value);
964
+ break;
965
+ case "mat4":
966
+ gl.uniformMatrix4fv(location, false, value);
967
+ break;
968
+ }
969
+ };
970
+ var applyProgramUniform = (gl, program, location, uniform) => {
971
+ gl.useProgram(program);
972
+ applyUniform(gl, location, uniform);
973
+ };
974
+ var applyUniforms = (gl, locations, cache, onMissing) => {
975
+ for (const [name, uniform] of cache) {
976
+ const location = locations.get(name);
977
+ if (!location) {
978
+ onMissing?.(name);
979
+ continue;
980
+ }
981
+ applyUniform(gl, location, uniform);
982
+ }
983
+ };
984
+ var collectUniformLocations = (gl, program) => {
985
+ const locations = /* @__PURE__ */ new Map();
986
+ const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
987
+ for (let index = 0; index < count; index += 1) {
988
+ const active = gl.getActiveUniform(program, index);
989
+ if (!active) continue;
990
+ const name = active.name.replace(/\[0\]$/, "");
991
+ const location = gl.getUniformLocation(program, name);
992
+ if (location) {
993
+ locations.set(name, location);
994
+ }
995
+ }
996
+ return locations;
997
+ };
998
+ var createUniformCache = (uniforms) => {
999
+ const cache = /* @__PURE__ */ new Map();
1000
+ for (const [name, value] of Object.entries(uniforms ?? {})) {
1001
+ cache.set(toUniformName(name), normalizeUniform(value));
1002
+ }
1003
+ return cache;
1004
+ };
1005
+ var isExplicitUniform = (input) => {
1006
+ if (!input || typeof input !== "object" || Array.isArray(input)) return false;
1007
+ return "type" in input && "value" in input;
1008
+ };
1009
+
1010
+ // src/internal/bindings.ts
1011
+ var createUniformBindings = () => {
1012
+ const sources = [];
1013
+ const evaluate = (time) => {
1014
+ const merged = /* @__PURE__ */ new Map();
1015
+ for (const source of sources) {
1016
+ for (const [name, value] of Object.entries(source.get(time))) {
1017
+ merged.set(toUniformName(name), normalizeUniform(value));
1018
+ }
1019
+ }
1020
+ return merged;
1021
+ };
1022
+ return {
1023
+ add(source) {
1024
+ sources.push(source);
1025
+ let removed = false;
1026
+ return () => {
1027
+ if (removed) return;
1028
+ removed = true;
1029
+ const index = sources.indexOf(source);
1030
+ if (index >= 0) sources.splice(index, 1);
1031
+ };
1032
+ },
1033
+ get size() {
1034
+ return sources.length;
1035
+ },
1036
+ evaluate,
1037
+ signature(time) {
1038
+ if (sources.length === 0) return "";
1039
+ let text = "";
1040
+ for (const [name, uniform] of evaluate(time)) {
1041
+ text += `${name}:${uniform.type}:${Array.from(uniform.value).join(",")};`;
1042
+ }
1043
+ return text;
1044
+ }
1045
+ };
1046
+ };
1047
+ var EASES = {
1048
+ linear: (t) => t,
1049
+ smooth: (t) => t * t * (3 - 2 * t),
1050
+ step: () => 0
1051
+ };
1052
+ var toEaseFunction = (ease) => {
1053
+ if (typeof ease === "function") return ease;
1054
+ const fn = EASES[ease];
1055
+ if (!fn) throw new RangeError(`Unknown ease: ${String(ease)}`);
1056
+ return fn;
1057
+ };
1058
+ var componentsOf = (value) => typeof value === "number" ? [value] : value;
1059
+ var isKeyList = (track) => Array.isArray(track);
1060
+ var compileTrack = (name, track, fallback) => {
1061
+ const list = isKeyList(track);
1062
+ const keys = list ? track : track.keys;
1063
+ const ease = toEaseFunction((list ? void 0 : track.ease) ?? fallback);
1064
+ if (keys.length === 0) throw new TypeError(`Keyframe track ${name} has no keys.`);
1065
+ const sorted = [...keys].sort((a, b) => a[0] - b[0]);
1066
+ const scalar = typeof sorted[0][1] === "number";
1067
+ const size = componentsOf(sorted[0][1]).length;
1068
+ for (const [time, value] of sorted) {
1069
+ if (!Number.isFinite(time)) throw new TypeError(`Keyframe track ${name} has a non-finite time.`);
1070
+ const components = componentsOf(value);
1071
+ if (typeof value === "number" !== scalar || components.length !== size) {
1072
+ throw new TypeError(`Keyframe track ${name} mixes values of different sizes.`);
1073
+ }
1074
+ if (!components.every(Number.isFinite)) {
1075
+ throw new TypeError(`Keyframe track ${name} has a non-finite value.`);
1076
+ }
1077
+ }
1078
+ return {
1079
+ times: sorted.map(([time]) => time),
1080
+ values: sorted.map(([, value]) => componentsOf(value)),
1081
+ scalar,
1082
+ ease
1083
+ };
1084
+ };
1085
+ var sampleTrack = (track, time) => {
1086
+ const { times, values } = track;
1087
+ const last = times.length - 1;
1088
+ let components;
1089
+ if (time <= times[0]) {
1090
+ components = values[0];
1091
+ } else if (time >= times[last]) {
1092
+ components = values[last];
1093
+ } else {
1094
+ let low = 0;
1095
+ let high = last;
1096
+ while (high - low > 1) {
1097
+ const middle = low + high >> 1;
1098
+ if (times[middle] <= time) low = middle;
1099
+ else high = middle;
1100
+ }
1101
+ const span = times[high] - times[low];
1102
+ const t = span > 0 ? track.ease((time - times[low]) / span) : 0;
1103
+ const from = values[low];
1104
+ const to = values[high];
1105
+ components = from.map((value, index) => value + (to[index] - value) * t);
1106
+ }
1107
+ return track.scalar ? components[0] : Array.from(components);
1108
+ };
1109
+ var keyframes = (tracks, options = {}) => {
1110
+ const fallback = options.ease ?? "linear";
1111
+ toEaseFunction(fallback);
1112
+ const compiled = Object.entries(tracks).map(
1113
+ ([name, track]) => [name, compileTrack(name, track, fallback)]
1114
+ );
1115
+ return {
1116
+ get(time) {
1117
+ const values = {};
1118
+ for (const [name, track] of compiled) values[name] = sampleTrack(track, time);
1119
+ return values;
1120
+ }
1121
+ };
1122
+ };
1123
+
864
1124
  // src/internal/textures.ts
865
1125
  var loadTexture = async (gl, name, input, unit) => {
866
1126
  const options = normalizeTextureInput(input);
@@ -1003,97 +1263,6 @@ var createTextureSet = (inputs = {}) => {
1003
1263
  };
1004
1264
  };
1005
1265
 
1006
- // src/internal/uniforms.ts
1007
- var normalizeUniform = (input) => {
1008
- if (typeof input === "number") {
1009
- return { type: "float", value: [input] };
1010
- }
1011
- if (input instanceof Float32Array) {
1012
- if (input.length === 9) return { type: "mat3", value: input };
1013
- if (input.length === 16) return { type: "mat4", value: input };
1014
- if (input.length === 2) return { type: "vec2", value: input };
1015
- if (input.length === 3) return { type: "vec3", value: input };
1016
- if (input.length === 4) return { type: "vec4", value: input };
1017
- }
1018
- if (isExplicitUniform(input)) {
1019
- return { type: input.type, value: input.value };
1020
- }
1021
- if (Array.isArray(input)) {
1022
- if (input.length === 2) return { type: "vec2", value: input };
1023
- if (input.length === 3) return { type: "vec3", value: input };
1024
- if (input.length === 4) return { type: "vec4", value: input };
1025
- }
1026
- return { type: "float", value: [0] };
1027
- };
1028
- var applyUniform = (gl, location, uniform) => {
1029
- const value = uniform.value;
1030
- switch (uniform.type) {
1031
- case "float":
1032
- gl.uniform1f(location, value[0] ?? 0);
1033
- break;
1034
- case "vec2":
1035
- gl.uniform2f(location, value[0] ?? 0, value[1] ?? 0);
1036
- break;
1037
- case "vec3":
1038
- gl.uniform3f(location, value[0] ?? 0, value[1] ?? 0, value[2] ?? 0);
1039
- break;
1040
- case "vec4":
1041
- gl.uniform4f(
1042
- location,
1043
- value[0] ?? 0,
1044
- value[1] ?? 0,
1045
- value[2] ?? 0,
1046
- value[3] ?? 0
1047
- );
1048
- break;
1049
- case "mat3":
1050
- gl.uniformMatrix3fv(location, false, value);
1051
- break;
1052
- case "mat4":
1053
- gl.uniformMatrix4fv(location, false, value);
1054
- break;
1055
- }
1056
- };
1057
- var applyProgramUniform = (gl, program, location, uniform) => {
1058
- gl.useProgram(program);
1059
- applyUniform(gl, location, uniform);
1060
- };
1061
- var applyUniforms = (gl, locations, cache, onMissing) => {
1062
- for (const [name, uniform] of cache) {
1063
- const location = locations.get(name);
1064
- if (!location) {
1065
- onMissing?.(name);
1066
- continue;
1067
- }
1068
- applyUniform(gl, location, uniform);
1069
- }
1070
- };
1071
- var collectUniformLocations = (gl, program) => {
1072
- const locations = /* @__PURE__ */ new Map();
1073
- const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
1074
- for (let index = 0; index < count; index += 1) {
1075
- const active = gl.getActiveUniform(program, index);
1076
- if (!active) continue;
1077
- const name = active.name.replace(/\[0\]$/, "");
1078
- const location = gl.getUniformLocation(program, name);
1079
- if (location) {
1080
- locations.set(name, location);
1081
- }
1082
- }
1083
- return locations;
1084
- };
1085
- var createUniformCache = (uniforms) => {
1086
- const cache = /* @__PURE__ */ new Map();
1087
- for (const [name, value] of Object.entries(uniforms ?? {})) {
1088
- cache.set(toUniformName(name), normalizeUniform(value));
1089
- }
1090
- return cache;
1091
- };
1092
- var isExplicitUniform = (input) => {
1093
- if (!input || typeof input !== "object" || Array.isArray(input)) return false;
1094
- return "type" in input && "value" in input;
1095
- };
1096
-
1097
1266
  // src/internal/fullscreenProgram.ts
1098
1267
  var createFullscreenProgram = (gl, fragment, vertex) => {
1099
1268
  const defaultVertex = isGLSL300(fragment) ? defaultVertexShader300 : defaultVertexShader;
@@ -1361,6 +1530,7 @@ export {
1361
1530
  createRenderTarget,
1362
1531
  createRuntimeHost,
1363
1532
  createTextureSet,
1533
+ createUniformBindings,
1364
1534
  createUniformCache,
1365
1535
  defaultVertexShader,
1366
1536
  defaultVertexShader300,
@@ -1371,8 +1541,10 @@ export {
1371
1541
  hexToRgba,
1372
1542
  isGLSL300,
1373
1543
  isWebGL2Context,
1544
+ keyframes,
1374
1545
  loadTexture,
1375
1546
  normalizeUniform,
1547
+ parseShaderLog,
1376
1548
  resizeCanvasToTarget,
1377
1549
  resolveDpr,
1378
1550
  resolveElement,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/errors.ts","../src/internal/webgl.ts","../src/internal/capture.ts","../src/internal/dom.ts","../src/host.ts","../src/internal/names.ts","../src/internal/textures.ts","../src/internal/textureSet.ts","../src/internal/uniforms.ts","../src/internal/fullscreenProgram.ts","../src/internal/blit.ts","../src/internal/renderTarget.ts"],"sourcesContent":["export class ShaderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class UnsupportedError extends ShaderError {}\nexport class TargetNotFoundError extends ShaderError {}\nexport class ShaderCompileError extends ShaderError {}\nexport class TextureLoadError extends ShaderError {}\nexport class DestroyedError extends ShaderError {}\n","import type { GLContext } from \"../types\";\nimport { ShaderCompileError } from \"./errors\";\n\nexport const defaultVertexShader = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const defaultVertexShader300 = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const isGLSL300 = (src: string): boolean =>\n /^\\s*#version\\s+300\\s+es\\b/.test(src);\n\n// Duck-typed instead of `instanceof WebGL2RenderingContext` so this also works\n// against test mocks and other environments where the global constructor may\n// be unavailable.\nexport const isWebGL2Context = (gl: GLContext): gl is WebGL2RenderingContext =>\n typeof (gl as WebGL2RenderingContext).createVertexArray === \"function\";\n\nexport const createProgram = (\n gl: GLContext,\n vertexSource: string,\n fragmentSource: string\n): WebGLProgram => {\n const vertex = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n const program = gl.createProgram();\n\n if (!program) {\n throw new ShaderCompileError(\"Failed to create WebGL program.\");\n }\n\n gl.attachShader(program, vertex);\n gl.attachShader(program, fragment);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) ?? \"Unknown program link error.\";\n gl.deleteProgram(program);\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n throw new ShaderCompileError(log);\n }\n\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n return program;\n};\n\nexport const createFullscreenBuffer = (\n gl: GLContext,\n program: WebGLProgram\n): WebGLBuffer => {\n const buffer = gl.createBuffer();\n if (!buffer) {\n throw new ShaderCompileError(\"Failed to create fullscreen buffer.\");\n }\n\n const location = gl.getAttribLocation(program, \"a_position\");\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n gl.STATIC_DRAW\n );\n\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n return buffer;\n};\n\nconst compileShader = (\n gl: GLContext,\n type: number,\n source: string\n): WebGLShader => {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new ShaderCompileError(\"Failed to create WebGL shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) ?? \"Unknown shader compile error.\";\n gl.deleteShader(shader);\n throw new ShaderCompileError(log);\n }\n\n return shader;\n};\n","import type { GLContext } from \"../types\";\nimport { isWebGL2Context } from \"./webgl\";\n\n/**\n * Resolves once the GPU has finished every command submitted so far, polling\n * a fence between tasks. Waiting between heavy draws keeps each submission\n * short, so a long render never trips the browser's GPU watchdog and loses\n * the context. Resolves immediately on WebGL1.\n */\nexport const waitForGpu = (gl: GLContext): Promise<void> => {\n if (!isWebGL2Context(gl)) return Promise.resolve();\n const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\n if (!sync) return Promise.resolve();\n gl.flush();\n return new Promise((resolve) => {\n const poll = () => {\n const status = gl.clientWaitSync(sync, 0, 0);\n if (status === gl.TIMEOUT_EXPIRED) {\n setTimeout(poll, 4);\n return;\n }\n gl.deleteSync(sync);\n resolve();\n };\n poll();\n });\n};\n\n/**\n * Reads RGBA pixels from `framebuffer` (or the drawing buffer when `null`) and\n * returns them top row first. Must run in the same task as the draw when\n * reading the drawing buffer, since it is not preserved.\n */\nexport const readPixels = <T extends \"rgba8\" | \"rgba16f\">(\n gl: GLContext,\n framebuffer: WebGLFramebuffer | null,\n width: number,\n height: number,\n format: T\n): T extends \"rgba16f\" ? Float32Array : Uint8Array => {\n const length = width * height * 4;\n const data =\n format === \"rgba16f\" ? new Float32Array(length) : new Uint8Array(length);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n // RGBA/FLOAT is the read combination EXT_color_buffer_float guarantees.\n gl.readPixels(\n 0,\n 0,\n width,\n height,\n gl.RGBA,\n format === \"rgba16f\" ? gl.FLOAT : gl.UNSIGNED_BYTE,\n data\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n flipRows(data, width * 4, height);\n return data as T extends \"rgba16f\" ? Float32Array : Uint8Array;\n};\n\n/** Encodes the canvas as PNG. The snapshot is taken synchronously. */\nexport const canvasToPng = (canvas: HTMLCanvasElement): Promise<Blob> =>\n new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"Failed to encode the canvas as PNG.\"));\n }, \"image/png\");\n });\n\n// WebGL reads bottom-up; captures are top row first like images.\nconst flipRows = (\n data: Uint8Array | Float32Array,\n rowLength: number,\n rows: number\n): void => {\n const temp = data.slice(0, rowLength);\n for (let top = 0, bottom = rows - 1; top < bottom; top++, bottom--) {\n const topStart = top * rowLength;\n const bottomStart = bottom * rowLength;\n temp.set(data.subarray(topStart, topStart + rowLength));\n data.copyWithin(topStart, bottomStart, bottomStart + rowLength);\n data.set(temp, bottomStart);\n }\n};\n","import type { DprOption, Resolution, SetupCanvasOptions } from \"../types\";\n\nexport type DomSetup = {\n target: Element;\n canvas: HTMLCanvasElement;\n createdCanvas: boolean;\n restoredPosition: string | null;\n /** True when the canvas was created without being attached to the document. */\n detached?: boolean;\n};\n\nexport type CanvasSize = {\n width: number;\n height: number;\n viewportWidth: number;\n viewportHeight: number;\n};\n\nexport const resolveElement = (\n target: string | Element | undefined\n): Element | null => {\n if (!target) return null;\n if (typeof target === \"string\") return document.querySelector(target);\n return target;\n};\n\nexport const setupCanvas = (options: SetupCanvasOptions): DomSetup | null => {\n const target = resolveElement(options.target);\n const canvas = options.canvas ?? document.createElement(\"canvas\");\n const measurementTarget = target ?? options.canvas;\n\n if (!measurementTarget) {\n if (!options.detached) return null;\n canvas.dataset.frapxCanvas = \"\";\n return {\n target: canvas,\n canvas,\n createdCanvas: true,\n restoredPosition: null,\n detached: true\n };\n }\n\n const createdCanvas = !options.canvas;\n const restoredPosition =\n target && getComputedStyle(target).position === \"static\"\n ? (target as HTMLElement).style.position\n : null;\n\n if (target && restoredPosition !== null) {\n (target as HTMLElement).style.position = \"relative\";\n }\n\n applyCanvasStyle(canvas, options, createdCanvas);\n\n if (options.canvasClass) {\n canvas.classList.add(options.canvasClass);\n }\n\n if (options.canvasStyle) {\n Object.assign(canvas.style, options.canvasStyle);\n }\n\n if (createdCanvas && target) {\n if ((options.layer ?? \"background\") === \"overlay\") {\n target.append(canvas);\n } else {\n target.prepend(canvas);\n }\n }\n\n return {\n target: measurementTarget,\n canvas,\n createdCanvas,\n restoredPosition\n };\n};\n\nexport const resolveDpr = (\n dpr: DprOption | undefined,\n maxDpr: number | undefined\n): number => {\n const raw =\n typeof dpr === \"function\"\n ? dpr()\n : typeof dpr === \"number\"\n ? dpr\n : typeof window === \"undefined\"\n ? 1\n : window.devicePixelRatio || 1;\n\n return Math.max(1, Math.min(raw, maxDpr ?? 2));\n};\n\nexport const resizeCanvasToTarget = (\n canvas: HTMLCanvasElement,\n target: Element,\n dpr: number\n): CanvasSize => {\n const rect = target.getBoundingClientRect();\n const viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n const viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n const width = Math.max(1, Math.round(viewportWidth * dpr));\n const height = Math.max(1, Math.round(viewportHeight * dpr));\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\n/**\n * Sizes the canvas to a fixed internal resolution. The viewport size still\n * comes from the target so `u_viewportSize` reflects the displayed size; a\n * detached canvas has no layout, so its viewport equals the resolution.\n */\nexport const resizeCanvasToResolution = (\n canvas: HTMLCanvasElement,\n target: Element | null,\n resolution: Resolution\n): CanvasSize => {\n const [width, height] = resolution;\n let viewportWidth = width;\n let viewportHeight = height;\n\n if (target) {\n const rect = target.getBoundingClientRect();\n viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n }\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\nconst applyCanvasStyle = (\n canvas: HTMLCanvasElement,\n options: SetupCanvasOptions,\n shouldPosition: boolean\n): void => {\n canvas.dataset.frapxCanvas = \"\";\n\n if (!shouldPosition) return;\n\n const layer = options.layer ?? \"background\";\n Object.assign(canvas.style, {\n position: \"absolute\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n pointerEvents: \"none\",\n zIndex: layer === \"overlay\" ? \"1\" : \"0\"\n });\n};\n","import type {\n CaptureFormat,\n CaptureOptions,\n CaptureResult,\n ClockMode,\n GLContext,\n HostFrameState,\n HostPointer,\n Resolution,\n RuntimeHostInstance,\n RuntimeHostOptions,\n ShaderStatus\n} from \"./types\";\nimport { DestroyedError, TargetNotFoundError, UnsupportedError } from \"./internal/errors\";\nimport { canvasToPng, readPixels } from \"./internal/capture\";\nimport {\n resolveDpr,\n resizeCanvasToResolution,\n resizeCanvasToTarget,\n setupCanvas,\n type DomSetup\n} from \"./internal/dom\";\n\nconst MAX_DELTA_SECONDS = 0.1;\n\n// Manual clocks report a neutral pointer so output never depends on input.\nconst IDLE_POINTER: HostPointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n\ntype Gate = \"offscreen\" | \"hidden\" | \"reducedMotion\";\n\nexport const createRuntimeHost = (\n options: RuntimeHostOptions\n): RuntimeHostInstance => {\n return new RuntimeHost(options);\n};\n\nclass RuntimeHost implements RuntimeHostInstance {\n readonly ready: Promise<void>;\n\n private readonly options: RuntimeHostOptions;\n private readyResolve: (() => void) | null = null;\n private readyReject: ((error: Error) => void) | null = null;\n private dom: DomSetup | null = null;\n private context: GLContext | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n private rafId = 0;\n private running = false;\n private inRender = false;\n private captureDrawing = false;\n private resizePending = false;\n private destroyed = false;\n private gates = new Set<Gate>();\n private reducedMotionActive = false;\n private frame = 0;\n private elapsed = 0;\n private lastTimestamp = 0;\n private pixelRatio = 1;\n private width = 1;\n private height = 1;\n private viewportWidth = 1;\n private viewportHeight = 1;\n private pointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n private removeListeners: Array<() => void> = [];\n private currentStatus: ShaderStatus = \"idle\";\n private contextRestoredShouldRun = false;\n private clockMode: ClockMode;\n private manualDelta = 0;\n private lastManualTime: number | null = null;\n private fixedResolution: Resolution | null;\n private objectFitRestore: string | null = null;\n // Letterbox offset (CSS px) of the contained canvas content inside the target.\n private contentOffsetX = 0;\n private contentOffsetY = 0;\n\n constructor(options: RuntimeHostOptions) {\n this.options = options;\n this.clockMode = options.clock ?? \"realtime\";\n this.fixedResolution = options.resolution\n ? normalizeResolution(options.resolution)\n : null;\n this.ready = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n queueMicrotask(() => {\n void this.init();\n });\n }\n\n get canvas(): HTMLCanvasElement | null {\n return this.dom?.canvas ?? null;\n }\n\n get gl(): GLContext | null {\n return this.context;\n }\n\n get status(): ShaderStatus {\n return this.currentStatus;\n }\n\n get supported(): boolean {\n return ![\"unsupported\", \"destroyed\"].includes(this.currentStatus);\n }\n\n get clock(): ClockMode {\n return this.clockMode;\n }\n\n start(): void {\n if (this.destroyed || this.currentStatus === \"unsupported\") return;\n this.running = true;\n this.reconcile();\n }\n\n stop(): void {\n this.running = false;\n this.cancelFrame();\n if (!this.destroyed && this.currentStatus !== \"unsupported\") {\n this.currentStatus = \"paused\";\n }\n }\n\n render(): void {\n if (\n this.destroyed ||\n !this.dom ||\n !this.context ||\n this.currentStatus === \"unsupported\" ||\n this.inRender\n )\n return;\n\n if (this.isManual) {\n // The caller decides when to draw; visibility gates do not apply.\n this.renderInternal(this.elapsed, this.manualDelta);\n return;\n }\n\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n setTime(seconds: number): void {\n if (!Number.isFinite(seconds)) {\n throw new RangeError(`setTime() expects a finite number, got ${seconds}`);\n }\n if (this.destroyed) return;\n\n if (this.isManual) {\n this.manualDelta =\n this.lastManualTime === null ? 0 : seconds - this.lastManualTime;\n this.lastManualTime = seconds;\n }\n this.elapsed = seconds;\n }\n\n setClock(clock: ClockMode): void {\n if (this.destroyed || clock === this.clockMode) return;\n this.clockMode = clock;\n this.manualDelta = 0;\n this.lastManualTime = null;\n // Gates kept tracking while manual, so this resumes against current state.\n this.reconcile();\n }\n\n setResolution(resolution: Resolution | null): void {\n if (this.destroyed) return;\n\n if (resolution === null) {\n if (this.isDetached) {\n throw new TypeError(\n \"A canvas without a target needs a fixed resolution.\"\n );\n }\n this.fixedResolution = null;\n } else {\n const next = normalizeResolution(resolution);\n if (this.context) assertWithinLimits(this.context, next);\n this.fixedResolution = next;\n }\n\n this.applyObjectFit();\n this.resize();\n }\n\n async captureFrame<F extends CaptureFormat = \"png\">(\n options: CaptureOptions<F> = {}\n ): Promise<CaptureResult<F>> {\n const format: CaptureFormat = options.format ?? \"png\";\n if (format !== \"png\" && format !== \"rgba8\" && format !== \"rgba16f\") {\n throw new RangeError(`Unknown capture format: ${String(format)}`);\n }\n\n await this.ready;\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n if (!this.dom || !this.context) {\n throw new UnsupportedError(\"Cannot capture without a WebGL context.\");\n }\n if (this.inRender) {\n throw new Error(\"captureFrame() cannot be called while a frame is drawing.\");\n }\n\n // Check before drawing so a rejected capture has no side effects.\n const sourceFormat = this.options.captureSource?.()?.format;\n if (format === \"rgba16f\" && sourceFormat !== \"rgba16f\" && sourceFormat !== \"rgba32f\") {\n throw new UnsupportedError(\n \"rgba16f capture needs a float render target, such as feedback with format rgba16f.\"\n );\n }\n options.signal?.throwIfAborted();\n\n const delta = this.isManual ? this.manualDelta : 0;\n const drawContext = this.context;\n if (!this.options.onCaptureDraw) {\n this.renderInternal(this.elapsed, delta);\n return this.readCapture(format, drawContext);\n }\n\n try {\n await this.renderForCapture(this.options.onCaptureDraw, delta, options.signal);\n return this.readCapture(format, drawContext);\n } finally {\n // Resizes requested while drawing apply once the frame is read.\n if (this.resizePending) {\n this.resizePending = false;\n this.resize();\n }\n }\n }\n\n resize(): void {\n if (this.destroyed || !this.dom) return;\n // Keep the size an asynchronous capture draw started with until it is read.\n if (this.captureDrawing) {\n this.resizePending = true;\n return;\n }\n\n const prevWidth = this.width;\n const prevHeight = this.height;\n const prevViewportWidth = this.viewportWidth;\n const prevViewportHeight = this.viewportHeight;\n\n this.measureSize();\n\n const sizeChanged =\n this.width !== prevWidth ||\n this.height !== prevHeight ||\n this.viewportWidth !== prevViewportWidth ||\n this.viewportHeight !== prevViewportHeight;\n\n if (sizeChanged && this.context) {\n this.options.onResize?.(this.createFrameState(this.elapsed, 0));\n }\n\n if (this.shouldRenderOnDemand && !this.inRender) {\n this.render();\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.running = false;\n this.cancelFrame();\n this.resizeObserver?.disconnect();\n this.intersectionObserver?.disconnect();\n\n for (const remove of this.removeListeners) remove();\n this.removeListeners = [];\n\n this.context = null;\n\n if (this.dom?.createdCanvas) {\n this.dom.canvas.remove();\n } else if (this.dom && this.objectFitRestore !== null) {\n this.dom.canvas.style.objectFit = this.objectFitRestore;\n }\n\n const dom = this.dom;\n if (dom?.restoredPosition !== null && dom && this.options.target) {\n (dom.target as HTMLElement).style.position = dom.restoredPosition!;\n }\n\n this.currentStatus = \"destroyed\";\n this.readyReject?.(new DestroyedError(\"Runtime host was destroyed.\"));\n }\n\n private get isManual(): boolean {\n return this.clockMode === \"manual\";\n }\n\n private get isDetached(): boolean {\n if (this.dom) return this.dom.detached === true;\n return this.options.target === undefined && this.options.canvas === undefined;\n }\n\n // Demand mode re-renders on input changes, except under a manual clock where\n // only explicit render() calls draw.\n private get shouldRenderOnDemand(): boolean {\n return this.options.renderMode === \"demand\" && !this.isManual;\n }\n\n private get hasVisibilityBlock(): boolean {\n return this.gates.has(\"offscreen\") || this.gates.has(\"hidden\");\n }\n\n private get hasMotionBlock(): boolean {\n return (\n this.gates.has(\"reducedMotion\") && this.options.renderMode !== \"demand\"\n );\n }\n\n private setGate(gate: Gate, closed: boolean): void {\n if (closed === this.gates.has(gate)) return;\n if (closed) this.gates.add(gate);\n else this.gates.delete(gate);\n this.reconcile();\n }\n\n private reconcile(): void {\n if (\n this.destroyed ||\n this.currentStatus === \"unsupported\" ||\n this.currentStatus === \"error\" ||\n this.currentStatus === \"context-lost\"\n ) {\n return;\n }\n\n if (this.isManual) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.running) {\n if (this.hasVisibilityBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.hasMotionBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n this.renderStaticFrame();\n return;\n }\n\n this.currentStatus = \"running\";\n if (this.options.renderMode === \"demand\") this.render();\n else this.scheduleFrame();\n return;\n }\n\n if (this.options.renderMode === \"demand\") this.render();\n }\n\n private renderStaticFrame(): void {\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n private renderInternal(time: number, delta: number): void {\n // An asynchronous capture draw holds the lock across tasks.\n if (!this.dom || !this.context || this.inRender) return;\n const gl = this.context;\n\n this.inRender = true;\n try {\n this.measureSize();\n this.options.onDraw(this.createFrameState(time, delta, gl));\n this.frame++;\n } finally {\n this.inRender = false;\n }\n }\n\n // Holds the render lock across an asynchronous capture draw so no other\n // frame interleaves with it.\n private async renderForCapture(\n draw: NonNullable<RuntimeHostOptions[\"onCaptureDraw\"]>,\n delta: number,\n signal: AbortSignal | undefined\n ): Promise<void> {\n if (!this.dom || !this.context) return;\n this.inRender = true;\n this.captureDrawing = true;\n try {\n this.measureSize();\n await draw(this.createFrameState(this.elapsed, delta, this.context), signal);\n this.frame++;\n } finally {\n this.inRender = false;\n this.captureDrawing = false;\n }\n }\n\n // Reads the frame just drawn, in the task that drew it: the drawing buffer\n // is not preserved. Fails if the context drawn into is gone, including when\n // it was lost and restored while an asynchronous draw was pending.\n private readCapture<F extends CaptureFormat>(\n format: CaptureFormat,\n drawContext: GLContext | null\n ): Promise<CaptureResult<F>> | CaptureResult<F> {\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n const gl = this.context;\n if (!gl || gl !== drawContext || !this.dom) {\n throw new UnsupportedError(\"The WebGL context was lost while capturing.\");\n }\n\n if (format === \"png\") {\n return canvasToPng(this.dom.canvas) as Promise<CaptureResult<F>>;\n }\n if (format === \"rgba8\") {\n return readPixels(gl, null, this.width, this.height, \"rgba8\") as CaptureResult<F>;\n }\n const source = this.options.captureSource!()!;\n return readPixels(\n gl,\n source.framebuffer,\n source.width,\n source.height,\n \"rgba16f\"\n ) as CaptureResult<F>;\n }\n\n private createFrameState(\n time: number,\n delta: number,\n gl: GLContext = this.context!\n ): HostFrameState {\n return {\n gl,\n canvas: this.dom!.canvas,\n time,\n delta,\n frame: this.frame,\n width: this.width,\n height: this.height,\n viewportWidth: this.viewportWidth,\n viewportHeight: this.viewportHeight,\n pixelRatio: this.pixelRatio,\n reducedMotion: this.isManual ? false : this.reducedMotionActive,\n pointer: this.isManual ? { ...IDLE_POINTER } : { ...this.pointer }\n };\n }\n\n private measureSize(): void {\n if (!this.dom) return;\n\n if (this.fixedResolution) {\n const size = resizeCanvasToResolution(\n this.dom.canvas,\n this.dom.detached ? null : this.dom.target,\n this.fixedResolution\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n // Internal pixels per displayed CSS pixel under object-fit: contain.\n this.pixelRatio = Math.max(\n size.width / size.viewportWidth,\n size.height / size.viewportHeight\n );\n this.contentOffsetX =\n (size.viewportWidth - size.width / this.pixelRatio) / 2;\n this.contentOffsetY =\n (size.viewportHeight - size.height / this.pixelRatio) / 2;\n return;\n }\n\n this.contentOffsetX = 0;\n this.contentOffsetY = 0;\n this.pixelRatio = resolveDpr(this.options.dpr, this.options.maxDpr);\n const size = resizeCanvasToTarget(\n this.dom.canvas,\n this.dom.target,\n this.pixelRatio\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n }\n\n // Letterbox the fixed-resolution canvas instead of stretching it.\n private applyObjectFit(): void {\n if (!this.dom) return;\n const style = this.dom.canvas.style;\n if (this.fixedResolution && this.objectFitRestore === null) {\n this.objectFitRestore = style.objectFit ?? \"\";\n style.objectFit = \"contain\";\n } else if (!this.fixedResolution && this.objectFitRestore !== null) {\n style.objectFit = this.objectFitRestore;\n this.objectFitRestore = null;\n }\n }\n\n private scheduleFrame(): void {\n if (this.rafId || this.options.renderMode === \"demand\" || this.isManual)\n return;\n\n this.rafId = requestAnimationFrame((timestamp) => {\n this.rafId = 0;\n if (!this.running || this.destroyed) return;\n\n const seconds = timestamp / 1000;\n const rawDelta = this.lastTimestamp ? seconds - this.lastTimestamp : 0;\n const delta = Math.min(Math.max(rawDelta, 0), MAX_DELTA_SECONDS);\n this.lastTimestamp = seconds;\n this.elapsed += delta;\n this.renderInternal(this.elapsed, delta);\n this.scheduleFrame();\n });\n }\n\n private cancelFrame(): void {\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = 0;\n }\n this.lastTimestamp = 0;\n }\n\n private async init(): Promise<void> {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n this.failUnsupported(new UnsupportedError(\"WebGL requires a browser.\"));\n return;\n }\n\n this.dom = setupCanvas({\n ...(this.options.target !== undefined && { target: this.options.target }),\n ...(this.options.canvas !== undefined && { canvas: this.options.canvas }),\n ...(this.options.layer !== undefined && { layer: this.options.layer }),\n ...(this.options.canvasClass !== undefined && { canvasClass: this.options.canvasClass }),\n ...(this.options.canvasStyle !== undefined && { canvasStyle: this.options.canvasStyle }),\n // Only a missing target/canvas may fall back to a detached canvas; a\n // target that fails to resolve must still report TargetNotFoundError.\n detached:\n this.fixedResolution !== null &&\n this.options.target === undefined &&\n this.options.canvas === undefined\n });\n\n if (!this.dom) {\n this.failUnsupported(\n new TargetNotFoundError(\n \"Target or canvas not found. Pass `resolution` to render without a target.\"\n )\n );\n return;\n }\n\n let gl: GLContext | null;\n try {\n gl = this.options.createContext(this.dom.canvas);\n } catch (error) {\n this.failUnsupported(\n error instanceof UnsupportedError\n ? error\n : new UnsupportedError(String(error))\n );\n return;\n }\n if (!gl) {\n this.failUnsupported(new UnsupportedError(\"WebGL is not supported.\"));\n return;\n }\n\n if (this.fixedResolution) {\n try {\n assertWithinLimits(gl, this.fixedResolution);\n } catch (error) {\n this.failUnsupported(\n error instanceof Error ? error : new UnsupportedError(String(error))\n );\n return;\n }\n if (this.options.dpr !== undefined || this.options.maxDpr !== undefined) {\n this.debugWarn(\"`dpr` and `maxDpr` are ignored while `resolution` is set.\");\n }\n }\n\n this.context = gl;\n this.currentStatus = \"loading\";\n\n try {\n this.applyObjectFit();\n this.setupDomObservers();\n this.setupContextEvents();\n this.measureSize();\n await this.options.onInit(gl, this.width, this.height);\n if (this.destroyed) return;\n this.currentStatus = \"ready\";\n this.readyResolve?.();\n this.options.onReady?.();\n\n if (this.running || (this.options.autoStart ?? true)) {\n this.start();\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n } catch (error) {\n if (error instanceof UnsupportedError) this.failUnsupported(error);\n else this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private setupDomObservers(): void {\n if (!this.dom) return;\n const detached = this.dom.detached === true;\n\n // A detached canvas has no layout: it can never be measured, scrolled into\n // view or pointed at, so only document-level observers apply.\n if (!detached && (this.options.autoResize ?? true)) {\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n this.resizeObserver.observe(this.dom.target);\n }\n\n if (!detached && (this.options.pauseWhenOffscreen ?? true)) {\n this.intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[0];\n this.setGate(\"offscreen\", !entry?.isIntersecting);\n });\n this.intersectionObserver.observe(this.dom.target);\n }\n\n if (this.options.pauseWhenHidden ?? true) {\n if (document.hidden) this.gates.add(\"hidden\");\n const onVisibility = () => {\n this.setGate(\"hidden\", document.hidden);\n };\n document.addEventListener(\"visibilitychange\", onVisibility);\n this.removeListeners.push(() => {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n });\n }\n\n this.setupMotionObserver();\n\n if (detached) return;\n\n const onPointerMove = (event: Event) => {\n if (!this.dom) return;\n const pointerEvent = event as PointerEvent;\n const rect = this.dom.target.getBoundingClientRect();\n const x = pointerEvent.clientX - rect.left - this.contentOffsetX;\n const y = pointerEvent.clientY - rect.top - this.contentOffsetY;\n // Displayed content size in CSS px (smaller than rect when letterboxed).\n const contentWidth = this.fixedResolution\n ? this.width / this.pixelRatio\n : rect.width;\n const contentHeight = this.fixedResolution\n ? this.height / this.pixelRatio\n : rect.height;\n this.pointer.x = x * this.pixelRatio;\n this.pointer.y = (contentHeight - y) * this.pixelRatio;\n this.pointer.uvX = contentWidth > 0 ? x / contentWidth : 0;\n this.pointer.uvY = contentHeight > 0 ? 1 - y / contentHeight : 0;\n this.pointer.active = 1;\n\n if (this.shouldRenderOnDemand) this.render();\n };\n const onPointerLeave = () => {\n this.pointer.active = 0;\n if (this.shouldRenderOnDemand) this.render();\n };\n\n this.dom.target.addEventListener(\"pointermove\", onPointerMove);\n this.dom.target.addEventListener(\"pointerenter\", onPointerMove);\n this.dom.target.addEventListener(\"pointerleave\", onPointerLeave);\n this.removeListeners.push(() => {\n this.dom?.target.removeEventListener(\"pointermove\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerenter\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerleave\", onPointerLeave);\n });\n }\n\n private setupMotionObserver(): void {\n if (typeof window.matchMedia !== \"function\") return;\n\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.reducedMotionActive = query.matches;\n if (this.options.respectReducedMotion && query.matches) {\n this.gates.add(\"reducedMotion\");\n }\n\n const onChange = (event: MediaQueryListEvent) => {\n this.reducedMotionActive = event.matches;\n if (this.options.respectReducedMotion) {\n this.setGate(\"reducedMotion\", event.matches);\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n };\n\n query.addEventListener(\"change\", onChange);\n this.removeListeners.push(() => {\n query.removeEventListener(\"change\", onChange);\n });\n }\n\n private setupContextEvents(): void {\n if (!this.dom) return;\n\n const onLost = (event: Event) => {\n event.preventDefault();\n this.contextRestoredShouldRun = this.running;\n this.cancelFrame();\n this.context = null;\n this.currentStatus = \"context-lost\";\n this.options.onContextLost?.();\n this.options.onError?.(new UnsupportedError(\"WebGL context lost.\"));\n };\n\n const onRestored = () => {\n if (!this.dom || this.destroyed) return;\n const gl = this.options.createContext(this.dom.canvas);\n if (!gl) return;\n this.context = gl;\n\n const afterRestore = async () => {\n try {\n await this.options.onContextRestored?.(gl, this.width, this.height);\n if (this.contextRestoredShouldRun) this.start();\n else if (!this.isManual) this.render();\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n };\n void afterRestore();\n };\n\n this.dom.canvas.addEventListener(\"webglcontextlost\", onLost);\n this.dom.canvas.addEventListener(\"webglcontextrestored\", onRestored);\n this.removeListeners.push(() => {\n this.dom?.canvas.removeEventListener(\"webglcontextlost\", onLost);\n this.dom?.canvas.removeEventListener(\"webglcontextrestored\", onRestored);\n });\n }\n\n private failUnsupported(error: Error): void {\n this.currentStatus = \"unsupported\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private fail(error: Error): void {\n this.currentStatus = \"error\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private debugWarn(message: string): void {\n if (this.options.debug) {\n console.warn(`[frapx/runtime] ${message}`);\n }\n }\n}\n\nconst normalizeResolution = (resolution: Resolution): Resolution => {\n const [width, height] = resolution;\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width < 1 ||\n height < 1\n ) {\n throw new RangeError(`Invalid resolution: ${width}x${height}`);\n }\n return [Math.round(width), Math.round(height)];\n};\n\nconst assertWithinLimits = (gl: GLContext, resolution: Resolution): void => {\n const [width, height] = resolution;\n const viewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS) as\n | ArrayLike<number>\n | null;\n const renderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) as\n | number\n | null;\n const limit = (axis: 0 | 1): number =>\n Math.min(\n viewportDims?.[axis] ?? Number.POSITIVE_INFINITY,\n typeof renderbufferSize === \"number\"\n ? renderbufferSize\n : Number.POSITIVE_INFINITY\n );\n\n if (width > limit(0) || height > limit(1)) {\n throw new UnsupportedError(\n `Resolution ${width}x${height} exceeds this GPU's limit of ${limit(0)}x${limit(1)}.`\n );\n }\n};\n","export const toUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name : `u_${name}`;\n\nexport const fromUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name.slice(2) : name;\n","import type { GLContext, TextureInput, TextureOptions, TextureSource } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { toUniformName } from \"./names\";\n\nexport type LoadedTexture = {\n name: string;\n uniformName: string;\n sizeUniformName: string;\n texture: WebGLTexture;\n width: number;\n height: number;\n};\n\nexport const loadTexture = async (\n gl: GLContext,\n name: string,\n input: TextureInput,\n unit: number\n): Promise<LoadedTexture> => {\n const options = normalizeTextureInput(input);\n const source = await resolveSource(options.source);\n const texture = gl.createTexture();\n\n if (!texture) {\n throw new TextureLoadError(`Failed to create texture: ${name}`);\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flipY ?? true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n\n const wrap = getWrap(gl, options.wrap ?? \"clamp\");\n const filter = getFilter(gl, options.filter ?? \"linear\");\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n return {\n name,\n uniformName: toUniformName(name),\n sizeUniformName: toUniformName(`${name}Size`),\n texture,\n width: getSourceWidth(source),\n height: getSourceHeight(source)\n };\n};\n\nconst normalizeTextureInput = (input: TextureInput): TextureOptions => {\n if (typeof input === \"string\" || isTextureSource(input)) {\n return { source: input };\n }\n\n return input;\n};\n\nconst resolveSource = async (\n source: TextureSource\n): Promise<HTMLImageElement | HTMLCanvasElement> => {\n if (typeof source !== \"string\") {\n return source;\n }\n\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = source;\n\n try {\n await image.decode();\n } catch {\n throw new TextureLoadError(`Failed to load texture: ${source}`);\n }\n\n return image;\n};\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<TextureOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n\nconst getFilter = (\n gl: GLContext,\n filter: NonNullable<TextureOptions[\"filter\"]>\n): number => (filter === \"nearest\" ? gl.NEAREST : gl.LINEAR);\n\nconst isTextureSource = (\n input: unknown\n): input is HTMLImageElement | HTMLCanvasElement =>\n typeof HTMLImageElement !== \"undefined\" &&\n (input instanceof HTMLImageElement || input instanceof HTMLCanvasElement);\n\nconst getSourceWidth = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalWidth\" in source ? source.naturalWidth : source.width;\n\nconst getSourceHeight = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalHeight\" in source ? source.naturalHeight : source.height;\n","import type { GLContext, TextureInput, TextureMap } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { loadTexture, type LoadedTexture } from \"./textures\";\n\nexport type TextureSet = {\n /** The textures loaded so far, by name. */\n readonly textures: ReadonlyMap<string, LoadedTexture>;\n /** Whether `name` was given as an input, loaded or not. */\n hasInput(name: string): boolean;\n /**\n * Returns the texture unit for `name`, taking the lowest free unit on first\n * use. Runtimes reserve units for their own samplers (feedback, pass inputs)\n * here too, so they never collide with image textures.\n */\n reserveUnit(gl: GLContext, name: string): number;\n /**\n * Loads every input, then replaces the previously loaded textures. Used for\n * the initial load and after a context restore.\n */\n loadAll(gl: GLContext, isCancelled: () => boolean): Promise<void>;\n /**\n * Loads `input` as `name`. Resolves to the loaded texture, or `null` when a\n * later `set()` for the same name or `isCancelled()` superseded it (its\n * texture is deleted). On failure the unit is released if `name` is unused,\n * and the error is rethrown.\n */\n set(\n gl: GLContext,\n name: string,\n input: TextureInput,\n isCancelled: () => boolean\n ): Promise<LoadedTexture | null>;\n /**\n * Binds every loaded texture to its unit and points its sampler uniform at\n * it. Calls `onMissing` with the uniform name when the program lacks it.\n */\n bind(\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n onMissing?: (uniformName: string) => void\n ): void;\n /** Deletes every loaded texture. */\n dispose(gl: GLContext): void;\n};\n\n/**\n * Tracks named image textures and the texture units they occupy, for a\n * runtime that binds them to one or more programs.\n */\nexport const createTextureSet = (inputs: TextureMap = {}): TextureSet => {\n const textureInputs = new Map<string, TextureInput>(Object.entries(inputs));\n let textures = new Map<string, LoadedTexture>();\n const units = new Map<string, number>();\n const versions = new Map<string, number>();\n\n const reserveUnit = (gl: GLContext, name: string): number => {\n const existing = units.get(name);\n if (existing !== undefined) return existing;\n\n const maxUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number;\n const used = new Set(units.values());\n for (let unit = 0; unit < maxUnits; unit += 1) {\n if (!used.has(unit)) {\n units.set(name, unit);\n return unit;\n }\n }\n\n throw new TextureLoadError(\n `Texture unit limit exceeded while loading texture: ${name}`\n );\n };\n\n return {\n get textures() {\n return textures;\n },\n\n hasInput(name) {\n return textureInputs.has(name);\n },\n\n reserveUnit,\n\n async loadAll(gl, isCancelled) {\n const loaded = new Map<string, LoadedTexture>();\n for (const [name, input] of textureInputs) {\n if (isCancelled()) break;\n const unit = reserveUnit(gl, name);\n loaded.set(name, await loadTexture(gl, name, input, unit));\n }\n\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n textures = loaded;\n },\n\n async set(gl, name, input, isCancelled) {\n const version = (versions.get(name) ?? 0) + 1;\n versions.set(name, version);\n\n try {\n const unit = reserveUnit(gl, name);\n const loaded = await loadTexture(gl, name, input, unit);\n\n if (isCancelled() || versions.get(name) !== version) {\n gl.deleteTexture(loaded.texture);\n return null;\n }\n\n const previous = textures.get(name);\n textureInputs.set(name, input);\n textures.set(name, loaded);\n if (previous) gl.deleteTexture(previous.texture);\n return loaded;\n } catch (error) {\n if (!textures.has(name) && !textureInputs.has(name)) {\n units.delete(name);\n }\n throw error;\n }\n },\n\n bind(gl, locations, onMissing) {\n for (const texture of textures.values()) {\n const unit = units.get(texture.name);\n if (unit === undefined) continue;\n const location = locations.get(texture.uniformName);\n if (!location) {\n onMissing?.(texture.uniformName);\n continue;\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n gl.uniform1i(location, unit);\n }\n },\n\n dispose(gl) {\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n }\n };\n};\n","import type { ExplicitUniformInput, GLContext, UniformInput, UniformType } from \"../types\";\nimport { toUniformName } from \"./names\";\n\nexport type NormalizedUniform = {\n type: UniformType;\n value: number[] | Float32Array;\n};\n\nexport const normalizeUniform = (input: UniformInput): NormalizedUniform => {\n if (typeof input === \"number\") {\n return { type: \"float\", value: [input] };\n }\n\n if (input instanceof Float32Array) {\n if (input.length === 9) return { type: \"mat3\", value: input };\n if (input.length === 16) return { type: \"mat4\", value: input };\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n if (isExplicitUniform(input)) {\n return { type: input.type, value: input.value };\n }\n\n if (Array.isArray(input)) {\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n return { type: \"float\", value: [0] };\n};\n\nexport const applyUniform = (\n gl: GLContext,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n const value = uniform.value;\n\n switch (uniform.type) {\n case \"float\":\n gl.uniform1f(location, value[0] ?? 0);\n break;\n case \"vec2\":\n gl.uniform2f(location, value[0] ?? 0, value[1] ?? 0);\n break;\n case \"vec3\":\n gl.uniform3f(location, value[0] ?? 0, value[1] ?? 0, value[2] ?? 0);\n break;\n case \"vec4\":\n gl.uniform4f(\n location,\n value[0] ?? 0,\n value[1] ?? 0,\n value[2] ?? 0,\n value[3] ?? 0\n );\n break;\n case \"mat3\":\n gl.uniformMatrix3fv(location, false, value);\n break;\n case \"mat4\":\n gl.uniformMatrix4fv(location, false, value);\n break;\n }\n};\n\nexport const applyProgramUniform = (\n gl: GLContext,\n program: WebGLProgram,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n gl.useProgram(program);\n applyUniform(gl, location, uniform);\n};\n\n/**\n * Uploads every cached uniform to the bound program. Calls `onMissing` with\n * the name of each uniform the program lacks or optimized out.\n */\nexport const applyUniforms = (\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n cache: ReadonlyMap<string, NormalizedUniform>,\n onMissing?: (name: string) => void\n): void => {\n for (const [name, uniform] of cache) {\n const location = locations.get(name);\n if (!location) {\n onMissing?.(name);\n continue;\n }\n applyUniform(gl, location, uniform);\n }\n};\n\nexport const collectUniformLocations = (\n gl: GLContext,\n program: WebGLProgram\n): Map<string, WebGLUniformLocation> => {\n const locations = new Map<string, WebGLUniformLocation>();\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) as number;\n\n for (let index = 0; index < count; index += 1) {\n const active = gl.getActiveUniform(program, index);\n if (!active) continue;\n\n const name = active.name.replace(/\\[0\\]$/, \"\");\n const location = gl.getUniformLocation(program, name);\n if (location) {\n locations.set(name, location);\n }\n }\n\n return locations;\n};\n\nexport const createUniformCache = (\n uniforms: Record<string, UniformInput> | undefined\n): Map<string, NormalizedUniform> => {\n const cache = new Map<string, NormalizedUniform>();\n\n for (const [name, value] of Object.entries(uniforms ?? {})) {\n cache.set(toUniformName(name), normalizeUniform(value));\n }\n\n return cache;\n};\n\nconst isExplicitUniform = (input: unknown): input is ExplicitUniformInput => {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return false;\n return \"type\" in input && \"value\" in input;\n};\n","import type { GLContext } from \"../types\";\nimport { collectUniformLocations } from \"./uniforms\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isGLSL300\n} from \"./webgl\";\n\nexport type FullscreenProgram = {\n readonly program: WebGLProgram;\n /** Active uniform locations by name, array uniforms without `[0]`. */\n readonly locations: ReadonlyMap<string, WebGLUniformLocation>;\n /**\n * Binds the program, its quad buffer and `a_position`, so a draw is correct\n * whatever GL state user hooks left behind.\n */\n use(): void;\n /** Draws the fullscreen quad with the current GL state. */\n draw(): void;\n dispose(): void;\n};\n\n/**\n * Compiles `fragment` with a fullscreen-quad vertex shader (the GLSL ES 3.00\n * one when `fragment` starts with `#version 300 es`, unless `vertex` is\n * given) and leaves it bound.\n */\nexport const createFullscreenProgram = (\n gl: GLContext,\n fragment: string,\n vertex?: string\n): FullscreenProgram => {\n const defaultVertex = isGLSL300(fragment)\n ? defaultVertexShader300\n : defaultVertexShader;\n const program = createProgram(gl, vertex ?? defaultVertex, fragment);\n gl.useProgram(program);\n const buffer = createFullscreenBuffer(gl, program);\n const attribLocation = gl.getAttribLocation(program, \"a_position\");\n const locations = collectUniformLocations(gl, program);\n\n return {\n program,\n locations,\n use() {\n gl.useProgram(program);\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n if (attribLocation >= 0) {\n gl.enableVertexAttribArray(attribLocation);\n gl.vertexAttribPointer(attribLocation, 2, gl.FLOAT, false, 0, 0);\n }\n },\n draw() {\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose() {\n gl.deleteBuffer(buffer);\n gl.deleteProgram(program);\n }\n };\n};\n","import type { GLContext } from \"../types\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isWebGL2Context\n} from \"./webgl\";\n\nconst blitFragmentShader = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, v_uv);\n}\n`;\n\nconst blitFragmentShader300 = `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_texture;\nout vec4 fragColor;\n\nvoid main() {\n fragColor = texture(u_texture, v_uv);\n}\n`;\n\nexport type Blitter = {\n /**\n * Draws `texture` as a fullscreen quad into `target` (or the default\n * framebuffer when `target` is `null`), setting the viewport to\n * `width`/`height` first. Does not save or restore any other GL state.\n */\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void;\n /** Releases the GL resources owned by this blitter. */\n dispose(): void;\n};\n\n/**\n * Creates a reusable fullscreen-quad \"blit\" utility: draws a texture into a\n * framebuffer (or the canvas) using a minimal passthrough shader. Intended\n * for hand-rolled multi-pass/FBO pipelines; frapx's own multi-pass features\n * are built on the same primitive.\n */\nexport const createBlitter = (gl: GLContext): Blitter => {\n const program = createProgram(\n gl,\n isWebGL2Context(gl) ? defaultVertexShader300 : defaultVertexShader,\n isWebGL2Context(gl) ? blitFragmentShader300 : blitFragmentShader\n );\n const buffer = createFullscreenBuffer(gl, program);\n const textureUniform = gl.getUniformLocation(program, \"u_texture\");\n\n return {\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void {\n gl.bindFramebuffer(gl.FRAMEBUFFER, target);\n gl.viewport(0, 0, width, height);\n gl.useProgram(program);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n const location = gl.getAttribLocation(program, \"a_position\");\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (textureUniform) {\n gl.uniform1i(textureUniform, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose(): void {\n gl.deleteProgram(program);\n gl.deleteBuffer(buffer);\n }\n };\n};\n","import type {\n GLContext,\n PingPong,\n RenderTarget,\n RenderTargetFormat,\n RenderTargetOptions\n} from \"../types\";\nimport { ShaderCompileError, UnsupportedError } from \"./errors\";\nimport { isWebGL2Context } from \"./webgl\";\n\nconst DEFAULT_CLEAR_COLOR = [0, 0, 0, 0] as const;\n\n/**\n * Whether `format` can be allocated as a color attachment on `gl`. `rgba8` is\n * always available; `rgba16f` and `rgba32f` need WebGL2 and\n * `EXT_color_buffer_float`.\n * Enables the extension as a side effect when present.\n */\nexport const supportsRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat\n): boolean => {\n if (format === \"rgba8\") return true;\n return isWebGL2Context(gl) && gl.getExtension(\"EXT_color_buffer_float\") !== null;\n};\n\n/**\n * Resolves the format a render target will actually use. When `format` is not\n * supported this warns and returns `rgba8`, or throws `UnsupportedError` when\n * `formatFallback` is `false`.\n */\nexport const resolveRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat = \"rgba8\",\n formatFallback = true\n): RenderTargetFormat => {\n if (supportsRenderTargetFormat(gl, format)) return format;\n\n const reason = `${format} render targets need WebGL2 with EXT_color_buffer_float.`;\n if (!formatFallback) throw new UnsupportedError(reason);\n console.warn(`[frapx] ${reason} Falling back to rgba8.`);\n return \"rgba8\";\n};\n\n/**\n * Creates a texture-backed framebuffer to render into and sample from. The\n * storage is cleared to `clearColor` on creation and on every resize.\n */\nexport const createRenderTarget = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): RenderTarget => {\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n return new Target(gl, width, height, format, options);\n};\n\n/**\n * Creates two render targets of the same size and format for feedback-style\n * rendering: draw into `write` while sampling `read`, then `swap()`.\n */\nexport const createPingPong = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): PingPong => {\n // Resolve once so a fallback warns a single time for both targets.\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n let read: RenderTarget = new Target(gl, width, height, format, options);\n let write: RenderTarget;\n try {\n write = new Target(gl, width, height, format, options);\n } catch (error) {\n read.dispose();\n throw error;\n }\n\n return {\n get read() {\n return read;\n },\n get write() {\n return write;\n },\n format,\n swap() {\n const previous = read;\n read = write;\n write = previous;\n },\n resize(nextWidth: number, nextHeight: number) {\n read.resize(nextWidth, nextHeight);\n write.resize(nextWidth, nextHeight);\n },\n clear() {\n read.clear();\n write.clear();\n },\n dispose() {\n read.dispose();\n write.dispose();\n }\n };\n};\n\nclass Target implements RenderTarget {\n texture!: WebGLTexture;\n framebuffer!: WebGLFramebuffer;\n width: number;\n height: number;\n\n constructor(\n private readonly gl: GLContext,\n width: number,\n height: number,\n readonly format: RenderTargetFormat,\n private readonly options: RenderTargetOptions\n ) {\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n resize(width: number, height: number): void {\n if (width === this.width && height === this.height) return;\n this.release();\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n clear(): void {\n const gl = this.gl;\n const [r, g, b, a] = this.options.clearColor ?? DEFAULT_CLEAR_COLOR;\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.viewport(0, 0, this.width, this.height);\n gl.clearColor(r, g, b, a);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n dispose(): void {\n this.release();\n }\n\n private allocate(): void {\n const gl = this.gl;\n const texture = gl.createTexture();\n if (!texture) {\n throw new ShaderCompileError(\"Failed to create render target texture.\");\n }\n\n const framebuffer = gl.createFramebuffer();\n if (!framebuffer) {\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\"Failed to create render target framebuffer.\");\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (this.format !== \"rgba8\" && isWebGL2Context(gl)) {\n const half = this.format === \"rgba16f\";\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n half ? gl.RGBA16F : gl.RGBA32F,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n half ? gl.HALF_FLOAT : gl.FLOAT,\n null\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n null\n );\n }\n\n const wrap = getWrap(gl, this.options.wrap ?? \"clamp\");\n // Linear filtering of 32-bit float textures is an optional extension.\n const linear =\n this.options.filter !== \"nearest\" &&\n (this.format !== \"rgba32f\" || gl.getExtension(\"OES_texture_float_linear\") !== null);\n const filter = linear ? gl.LINEAR : gl.NEAREST;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.deleteFramebuffer(framebuffer);\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\n `Render target framebuffer (${this.format}) is incomplete: ${status}`\n );\n }\n\n this.texture = texture;\n this.framebuffer = framebuffer;\n this.clear();\n }\n\n private release(): void {\n this.gl.deleteFramebuffer(this.framebuffer);\n this.gl.deleteTexture(this.texture);\n }\n}\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<RenderTargetOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n"],"mappings":"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","names":["size","getWrap"]}
1
+ {"version":3,"sources":["../src/internal/errors.ts","../src/internal/shaderLog.ts","../src/internal/webgl.ts","../src/internal/capture.ts","../src/internal/dom.ts","../src/host.ts","../src/internal/names.ts","../src/internal/uniforms.ts","../src/internal/bindings.ts","../src/internal/textures.ts","../src/internal/textureSet.ts","../src/internal/fullscreenProgram.ts","../src/internal/blit.ts","../src/internal/renderTarget.ts"],"sourcesContent":["export class ShaderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** One line of a shader compile error, located in the source that was compiled. */\nexport type ShaderErrorLine = {\n /** 1-based line in the compiled source (after `glsl` template interpolation). */\n line: number;\n message: string;\n /** That line of the source, or \"\" when the log points past the end. */\n source: string;\n /** Up to two lines either side, with their numbers, the error line included. */\n context: ReadonlyArray<{ line: number; source: string }>;\n};\n\n/** `\"link\"` for program link errors, which carry no line numbers. */\nexport type ShaderStage = \"vertex\" | \"fragment\" | \"link\";\n\nexport class UnsupportedError extends ShaderError {}\nexport class TargetNotFoundError extends ShaderError {}\nexport class ShaderCompileError extends ShaderError {\n /** The stage that failed, or `null` for errors not tied to compiling a shader. */\n readonly stage: ShaderStage | null;\n /** Errors located in the source, parsed from the driver's info log. Empty when it had none. */\n readonly lines: readonly ShaderErrorLine[];\n\n constructor(\n message: string,\n details: { stage?: ShaderStage; lines?: readonly ShaderErrorLine[] } = {}\n ) {\n super(message);\n this.stage = details.stage ?? null;\n this.lines = details.lines ?? [];\n }\n}\nexport class TextureLoadError extends ShaderError {}\nexport class DestroyedError extends ShaderError {}\n","import type { ShaderErrorLine } from \"./errors\";\n\n// Browsers translate shaders through ANGLE: \"ERROR: 0:12: 'x' : undeclared identifier\".\nconst ANGLE_STYLE = /^\\s*ERROR:\\s*\\d+:(\\d+):\\s*(.*)$/;\n// Native NVIDIA-style drivers: \"0(12) : error C1008: undefined variable\".\nconst NVIDIA_STYLE = /^\\s*\\d+\\((\\d+)\\)\\s*:\\s*error\\s*\\w*\\s*:\\s*(.*)$/i;\n// Follow-up noise after the real error.\nconst NOISE = /compilation terminated|^\\s*''\\s*:\\s*$/i;\n\nconst CONTEXT_LINES = 2;\n\n/**\n * Finds the errors in a shader info log and attaches the source lines they\n * point at. Lines the log does not locate are left out; the log itself stays\n * the error message.\n */\nexport const parseShaderLog = (log: string, source: string): ShaderErrorLine[] => {\n const sourceLines = source.split(/\\r?\\n/);\n const lineAt = (line: number) => sourceLines[line - 1] ?? \"\";\n const results: ShaderErrorLine[] = [];\n const seen = new Set<string>();\n\n for (const entry of log.split(/\\r?\\n/)) {\n const match = ANGLE_STYLE.exec(entry) ?? NVIDIA_STYLE.exec(entry);\n if (!match) continue;\n const line = Number(match[1]);\n const message = match[2]!.trim();\n if (!message || NOISE.test(message)) continue;\n const key = `${line}:${message}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const context: Array<{ line: number; source: string }> = [];\n const first = Math.max(1, line - CONTEXT_LINES);\n const last = Math.min(sourceLines.length, line + CONTEXT_LINES);\n for (let current = first; current <= last; current++) {\n context.push({ line: current, source: lineAt(current) });\n }\n results.push({ line, message, source: lineAt(line), context });\n }\n return results;\n};\n","import type { GLContext } from \"../types\";\nimport { ShaderCompileError } from \"./errors\";\nimport { parseShaderLog } from \"./shaderLog\";\n\nexport const defaultVertexShader = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const defaultVertexShader300 = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const isGLSL300 = (src: string): boolean =>\n /^\\s*#version\\s+300\\s+es\\b/.test(src);\n\n// Duck-typed instead of `instanceof WebGL2RenderingContext` so this also works\n// against test mocks and other environments where the global constructor may\n// be unavailable.\nexport const isWebGL2Context = (gl: GLContext): gl is WebGL2RenderingContext =>\n typeof (gl as WebGL2RenderingContext).createVertexArray === \"function\";\n\nexport const createProgram = (\n gl: GLContext,\n vertexSource: string,\n fragmentSource: string\n): WebGLProgram => {\n const vertex = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n let fragment: WebGLShader;\n try {\n fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n } catch (error) {\n gl.deleteShader(vertex);\n throw error;\n }\n const program = gl.createProgram();\n\n if (!program) {\n throw new ShaderCompileError(\"Failed to create WebGL program.\");\n }\n\n gl.attachShader(program, vertex);\n gl.attachShader(program, fragment);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) ?? \"Unknown program link error.\";\n gl.deleteProgram(program);\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n throw new ShaderCompileError(log, { stage: \"link\" });\n }\n\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n return program;\n};\n\nexport const createFullscreenBuffer = (\n gl: GLContext,\n program: WebGLProgram\n): WebGLBuffer => {\n const buffer = gl.createBuffer();\n if (!buffer) {\n throw new ShaderCompileError(\"Failed to create fullscreen buffer.\");\n }\n\n const location = gl.getAttribLocation(program, \"a_position\");\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n gl.STATIC_DRAW\n );\n\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n return buffer;\n};\n\nconst compileShader = (\n gl: GLContext,\n type: number,\n source: string\n): WebGLShader => {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new ShaderCompileError(\"Failed to create WebGL shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) ?? \"Unknown shader compile error.\";\n gl.deleteShader(shader);\n throw new ShaderCompileError(log, {\n stage: type === gl.VERTEX_SHADER ? \"vertex\" : \"fragment\",\n lines: parseShaderLog(log, source)\n });\n }\n\n return shader;\n};\n","import type { GLContext } from \"../types\";\nimport { isWebGL2Context } from \"./webgl\";\n\n/**\n * Resolves once the GPU has finished every command submitted so far, polling\n * a fence between tasks. Waiting between heavy draws keeps each submission\n * short, so a long render never trips the browser's GPU watchdog and loses\n * the context. Resolves immediately on WebGL1.\n */\nexport const waitForGpu = (gl: GLContext): Promise<void> => {\n if (!isWebGL2Context(gl)) return Promise.resolve();\n const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\n if (!sync) return Promise.resolve();\n gl.flush();\n return new Promise((resolve) => {\n const poll = () => {\n const status = gl.clientWaitSync(sync, 0, 0);\n if (status === gl.TIMEOUT_EXPIRED) {\n setTimeout(poll, 4);\n return;\n }\n gl.deleteSync(sync);\n resolve();\n };\n poll();\n });\n};\n\n/**\n * Reads RGBA pixels from `framebuffer` (or the drawing buffer when `null`) and\n * returns them top row first. Must run in the same task as the draw when\n * reading the drawing buffer, since it is not preserved.\n */\nexport const readPixels = <T extends \"rgba8\" | \"rgba16f\">(\n gl: GLContext,\n framebuffer: WebGLFramebuffer | null,\n width: number,\n height: number,\n format: T\n): T extends \"rgba16f\" ? Float32Array : Uint8Array => {\n const length = width * height * 4;\n const data =\n format === \"rgba16f\" ? new Float32Array(length) : new Uint8Array(length);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n // RGBA/FLOAT is the read combination EXT_color_buffer_float guarantees.\n gl.readPixels(\n 0,\n 0,\n width,\n height,\n gl.RGBA,\n format === \"rgba16f\" ? gl.FLOAT : gl.UNSIGNED_BYTE,\n data\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n flipRows(data, width * 4, height);\n return data as T extends \"rgba16f\" ? Float32Array : Uint8Array;\n};\n\n/** Encodes the canvas as PNG. The snapshot is taken synchronously. */\nexport const canvasToPng = (canvas: HTMLCanvasElement): Promise<Blob> =>\n new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"Failed to encode the canvas as PNG.\"));\n }, \"image/png\");\n });\n\n// WebGL reads bottom-up; captures are top row first like images.\nconst flipRows = (\n data: Uint8Array | Float32Array,\n rowLength: number,\n rows: number\n): void => {\n const temp = data.slice(0, rowLength);\n for (let top = 0, bottom = rows - 1; top < bottom; top++, bottom--) {\n const topStart = top * rowLength;\n const bottomStart = bottom * rowLength;\n temp.set(data.subarray(topStart, topStart + rowLength));\n data.copyWithin(topStart, bottomStart, bottomStart + rowLength);\n data.set(temp, bottomStart);\n }\n};\n","import type { DprOption, Resolution, SetupCanvasOptions } from \"../types\";\n\nexport type DomSetup = {\n target: Element;\n canvas: HTMLCanvasElement;\n createdCanvas: boolean;\n restoredPosition: string | null;\n /** True when the canvas was created without being attached to the document. */\n detached?: boolean;\n};\n\nexport type CanvasSize = {\n width: number;\n height: number;\n viewportWidth: number;\n viewportHeight: number;\n};\n\nexport const resolveElement = (\n target: string | Element | undefined\n): Element | null => {\n if (!target) return null;\n if (typeof target === \"string\") return document.querySelector(target);\n return target;\n};\n\nexport const setupCanvas = (options: SetupCanvasOptions): DomSetup | null => {\n const target = resolveElement(options.target);\n const canvas = options.canvas ?? document.createElement(\"canvas\");\n const measurementTarget = target ?? options.canvas;\n\n if (!measurementTarget) {\n if (!options.detached) return null;\n canvas.dataset.frapxCanvas = \"\";\n return {\n target: canvas,\n canvas,\n createdCanvas: true,\n restoredPosition: null,\n detached: true\n };\n }\n\n const createdCanvas = !options.canvas;\n const restoredPosition =\n target && getComputedStyle(target).position === \"static\"\n ? (target as HTMLElement).style.position\n : null;\n\n if (target && restoredPosition !== null) {\n (target as HTMLElement).style.position = \"relative\";\n }\n\n applyCanvasStyle(canvas, options, createdCanvas);\n\n if (options.canvasClass) {\n canvas.classList.add(options.canvasClass);\n }\n\n if (options.canvasStyle) {\n Object.assign(canvas.style, options.canvasStyle);\n }\n\n if (createdCanvas && target) {\n if ((options.layer ?? \"background\") === \"overlay\") {\n target.append(canvas);\n } else {\n target.prepend(canvas);\n }\n }\n\n return {\n target: measurementTarget,\n canvas,\n createdCanvas,\n restoredPosition\n };\n};\n\nexport const resolveDpr = (\n dpr: DprOption | undefined,\n maxDpr: number | undefined\n): number => {\n const raw =\n typeof dpr === \"function\"\n ? dpr()\n : typeof dpr === \"number\"\n ? dpr\n : typeof window === \"undefined\"\n ? 1\n : window.devicePixelRatio || 1;\n\n return Math.max(1, Math.min(raw, maxDpr ?? 2));\n};\n\nexport const resizeCanvasToTarget = (\n canvas: HTMLCanvasElement,\n target: Element,\n dpr: number\n): CanvasSize => {\n const rect = target.getBoundingClientRect();\n const viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n const viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n const width = Math.max(1, Math.round(viewportWidth * dpr));\n const height = Math.max(1, Math.round(viewportHeight * dpr));\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\n/**\n * Sizes the canvas to a fixed internal resolution. The viewport size still\n * comes from the target so `u_viewportSize` reflects the displayed size; a\n * detached canvas has no layout, so its viewport equals the resolution.\n */\nexport const resizeCanvasToResolution = (\n canvas: HTMLCanvasElement,\n target: Element | null,\n resolution: Resolution\n): CanvasSize => {\n const [width, height] = resolution;\n let viewportWidth = width;\n let viewportHeight = height;\n\n if (target) {\n const rect = target.getBoundingClientRect();\n viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n }\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\nconst applyCanvasStyle = (\n canvas: HTMLCanvasElement,\n options: SetupCanvasOptions,\n shouldPosition: boolean\n): void => {\n canvas.dataset.frapxCanvas = \"\";\n\n if (!shouldPosition) return;\n\n const layer = options.layer ?? \"background\";\n Object.assign(canvas.style, {\n position: \"absolute\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n pointerEvents: \"none\",\n zIndex: layer === \"overlay\" ? \"1\" : \"0\"\n });\n};\n","import type {\n CaptureFormat,\n CaptureOptions,\n CaptureResult,\n ClockMode,\n GLContext,\n HostFrameState,\n HostPointer,\n Resolution,\n RuntimeHostInstance,\n RuntimeHostOptions,\n ShaderStatus\n} from \"./types\";\nimport { DestroyedError, TargetNotFoundError, UnsupportedError } from \"./internal/errors\";\nimport { canvasToPng, readPixels } from \"./internal/capture\";\nimport {\n resolveDpr,\n resizeCanvasToResolution,\n resizeCanvasToTarget,\n setupCanvas,\n type DomSetup\n} from \"./internal/dom\";\n\nconst MAX_DELTA_SECONDS = 0.1;\n\n// Manual clocks report a neutral pointer so output never depends on input.\nconst IDLE_POINTER: HostPointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n\ntype Gate = \"offscreen\" | \"hidden\" | \"reducedMotion\";\n\nexport const createRuntimeHost = (\n options: RuntimeHostOptions\n): RuntimeHostInstance => {\n return new RuntimeHost(options);\n};\n\nclass RuntimeHost implements RuntimeHostInstance {\n readonly ready: Promise<void>;\n\n private readonly options: RuntimeHostOptions;\n private readyResolve: (() => void) | null = null;\n private readyReject: ((error: Error) => void) | null = null;\n private dom: DomSetup | null = null;\n private context: GLContext | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n private rafId = 0;\n private running = false;\n private inRender = false;\n private captureDrawing = false;\n private resizePending = false;\n private destroyed = false;\n private gates = new Set<Gate>();\n private reducedMotionActive = false;\n private frame = 0;\n private elapsed = 0;\n private lastTimestamp = 0;\n private pixelRatio = 1;\n private width = 1;\n private height = 1;\n private viewportWidth = 1;\n private viewportHeight = 1;\n private pointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n private removeListeners: Array<() => void> = [];\n private currentStatus: ShaderStatus = \"idle\";\n private contextRestoredShouldRun = false;\n private statusBeforeLoss: ShaderStatus = \"idle\";\n private clockMode: ClockMode;\n private manualDelta = 0;\n private lastManualTime: number | null = null;\n private fixedResolution: Resolution | null;\n private objectFitRestore: string | null = null;\n // Letterbox offset (CSS px) of the contained canvas content inside the target.\n private contentOffsetX = 0;\n private contentOffsetY = 0;\n\n constructor(options: RuntimeHostOptions) {\n this.options = options;\n this.clockMode = options.clock ?? \"realtime\";\n this.fixedResolution = options.resolution\n ? normalizeResolution(options.resolution)\n : null;\n this.ready = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n queueMicrotask(() => {\n void this.init();\n });\n }\n\n get canvas(): HTMLCanvasElement | null {\n return this.dom?.canvas ?? null;\n }\n\n get gl(): GLContext | null {\n return this.context;\n }\n\n get status(): ShaderStatus {\n return this.currentStatus;\n }\n\n get supported(): boolean {\n return ![\"unsupported\", \"destroyed\"].includes(this.currentStatus);\n }\n\n get clock(): ClockMode {\n return this.clockMode;\n }\n\n start(): void {\n if (this.destroyed || this.currentStatus === \"unsupported\") return;\n this.running = true;\n this.reconcile();\n }\n\n stop(): void {\n this.running = false;\n this.cancelFrame();\n if (!this.destroyed && this.currentStatus !== \"unsupported\") {\n this.currentStatus = \"paused\";\n }\n }\n\n render(): void {\n if (\n this.destroyed ||\n !this.dom ||\n !this.context ||\n this.currentStatus === \"unsupported\" ||\n this.inRender\n )\n return;\n\n if (this.isManual) {\n // The caller decides when to draw; visibility gates do not apply.\n this.renderInternal(this.elapsed, this.manualDelta);\n return;\n }\n\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n setTime(seconds: number): void {\n if (!Number.isFinite(seconds)) {\n throw new RangeError(`setTime() expects a finite number, got ${seconds}`);\n }\n if (this.destroyed) return;\n\n if (this.isManual) {\n this.manualDelta =\n this.lastManualTime === null ? 0 : seconds - this.lastManualTime;\n this.lastManualTime = seconds;\n }\n this.elapsed = seconds;\n }\n\n setClock(clock: ClockMode): void {\n if (this.destroyed || clock === this.clockMode) return;\n this.clockMode = clock;\n this.manualDelta = 0;\n this.lastManualTime = null;\n // Gates kept tracking while manual, so this resumes against current state.\n this.reconcile();\n }\n\n setResolution(resolution: Resolution | null): void {\n if (this.destroyed) return;\n\n if (resolution === null) {\n if (this.isDetached) {\n throw new TypeError(\n \"A canvas without a target needs a fixed resolution.\"\n );\n }\n this.fixedResolution = null;\n } else {\n const next = normalizeResolution(resolution);\n if (this.context) assertWithinLimits(this.context, next);\n this.fixedResolution = next;\n }\n\n this.applyObjectFit();\n this.resize();\n }\n\n async captureFrame<F extends CaptureFormat = \"png\">(\n options: CaptureOptions<F> = {}\n ): Promise<CaptureResult<F>> {\n const format: CaptureFormat = options.format ?? \"png\";\n if (format !== \"png\" && format !== \"rgba8\" && format !== \"rgba16f\") {\n throw new RangeError(`Unknown capture format: ${String(format)}`);\n }\n\n await this.ready;\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n if (!this.dom || !this.context) {\n throw new UnsupportedError(\"Cannot capture without a WebGL context.\");\n }\n if (this.inRender) {\n throw new Error(\"captureFrame() cannot be called while a frame is drawing.\");\n }\n\n // Check before drawing so a rejected capture has no side effects.\n const sourceFormat = this.options.captureSource?.()?.format;\n if (format === \"rgba16f\" && sourceFormat !== \"rgba16f\" && sourceFormat !== \"rgba32f\") {\n throw new UnsupportedError(\n \"rgba16f capture needs a float render target, such as feedback with format rgba16f.\"\n );\n }\n options.signal?.throwIfAborted();\n\n const delta = this.isManual ? this.manualDelta : 0;\n const drawContext = this.context;\n if (!this.options.onCaptureDraw) {\n this.renderInternal(this.elapsed, delta);\n return this.readCapture(format, drawContext);\n }\n\n try {\n await this.renderForCapture(this.options.onCaptureDraw, delta, options.signal);\n return this.readCapture(format, drawContext);\n } finally {\n // Resizes requested while drawing apply once the frame is read.\n if (this.resizePending) {\n this.resizePending = false;\n this.resize();\n }\n }\n }\n\n resize(): void {\n if (this.destroyed || !this.dom) return;\n // Keep the size an asynchronous capture draw started with until it is read.\n if (this.captureDrawing) {\n this.resizePending = true;\n return;\n }\n\n this.syncSize();\n\n if (this.shouldRenderOnDemand && !this.inRender) {\n this.render();\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.running = false;\n this.cancelFrame();\n this.resizeObserver?.disconnect();\n this.intersectionObserver?.disconnect();\n\n for (const remove of this.removeListeners) remove();\n this.removeListeners = [];\n\n this.context = null;\n\n if (this.dom?.createdCanvas) {\n this.dom.canvas.remove();\n } else if (this.dom && this.objectFitRestore !== null) {\n this.dom.canvas.style.objectFit = this.objectFitRestore;\n }\n\n const dom = this.dom;\n if (dom?.restoredPosition !== null && dom && this.options.target) {\n (dom.target as HTMLElement).style.position = dom.restoredPosition!;\n }\n\n this.currentStatus = \"destroyed\";\n this.readyReject?.(new DestroyedError(\"Runtime host was destroyed.\"));\n }\n\n private get isManual(): boolean {\n return this.clockMode === \"manual\";\n }\n\n private get isDetached(): boolean {\n if (this.dom) return this.dom.detached === true;\n return this.options.target === undefined && this.options.canvas === undefined;\n }\n\n // Demand mode re-renders on input changes, except under a manual clock where\n // only explicit render() calls draw.\n private get shouldRenderOnDemand(): boolean {\n return this.options.renderMode === \"demand\" && !this.isManual;\n }\n\n private get hasVisibilityBlock(): boolean {\n return this.gates.has(\"offscreen\") || this.gates.has(\"hidden\");\n }\n\n private get hasMotionBlock(): boolean {\n return (\n this.gates.has(\"reducedMotion\") && this.options.renderMode !== \"demand\"\n );\n }\n\n private setGate(gate: Gate, closed: boolean): void {\n if (closed === this.gates.has(gate)) return;\n if (closed) this.gates.add(gate);\n else this.gates.delete(gate);\n this.reconcile();\n }\n\n private reconcile(): void {\n if (\n this.destroyed ||\n this.currentStatus === \"unsupported\" ||\n this.currentStatus === \"error\" ||\n this.currentStatus === \"context-lost\"\n ) {\n return;\n }\n\n if (this.isManual) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.running) {\n if (this.hasVisibilityBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.hasMotionBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n this.renderStaticFrame();\n return;\n }\n\n this.currentStatus = \"running\";\n if (this.options.renderMode === \"demand\") this.render();\n else this.scheduleFrame();\n return;\n }\n\n if (this.options.renderMode === \"demand\") this.render();\n }\n\n private renderStaticFrame(): void {\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n private renderInternal(time: number, delta: number): void {\n // An asynchronous capture draw holds the lock across tasks.\n if (!this.dom || !this.context || this.inRender) return;\n const gl = this.context;\n\n this.inRender = true;\n try {\n this.syncSize();\n this.options.onDraw(this.createFrameState(time, delta, gl));\n this.frame++;\n } finally {\n this.inRender = false;\n }\n }\n\n // Holds the render lock across an asynchronous capture draw so no other\n // frame interleaves with it.\n private async renderForCapture(\n draw: NonNullable<RuntimeHostOptions[\"onCaptureDraw\"]>,\n delta: number,\n signal: AbortSignal | undefined\n ): Promise<void> {\n if (!this.dom || !this.context) return;\n this.inRender = true;\n this.captureDrawing = true;\n try {\n this.syncSize();\n await draw(this.createFrameState(this.elapsed, delta, this.context), signal);\n this.frame++;\n } finally {\n this.inRender = false;\n this.captureDrawing = false;\n }\n }\n\n // Reads the frame just drawn, in the task that drew it: the drawing buffer\n // is not preserved. Fails if the context drawn into is gone, including when\n // it was lost and restored while an asynchronous draw was pending.\n private readCapture<F extends CaptureFormat>(\n format: CaptureFormat,\n drawContext: GLContext | null\n ): Promise<CaptureResult<F>> | CaptureResult<F> {\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n const gl = this.context;\n if (!gl || gl !== drawContext || !this.dom) {\n throw new UnsupportedError(\"The WebGL context was lost while capturing.\");\n }\n\n if (format === \"png\") {\n return canvasToPng(this.dom.canvas) as Promise<CaptureResult<F>>;\n }\n if (format === \"rgba8\") {\n return readPixels(gl, null, this.width, this.height, \"rgba8\") as CaptureResult<F>;\n }\n const source = this.options.captureSource!()!;\n return readPixels(\n gl,\n source.framebuffer,\n source.width,\n source.height,\n \"rgba16f\"\n ) as CaptureResult<F>;\n }\n\n private createFrameState(\n time: number,\n delta: number,\n gl: GLContext = this.context!\n ): HostFrameState {\n return {\n gl,\n canvas: this.dom!.canvas,\n time,\n delta,\n frame: this.frame,\n width: this.width,\n height: this.height,\n viewportWidth: this.viewportWidth,\n viewportHeight: this.viewportHeight,\n pixelRatio: this.pixelRatio,\n reducedMotion: this.isManual ? false : this.reducedMotionActive,\n pointer: this.isManual ? { ...IDLE_POINTER } : { ...this.pointer }\n };\n }\n\n /**\n * Measures the size and calls onResize if it changed. Frames measure too:\n * browsers run animation frames before resize observations, so in a running\n * loop a frame is usually the first to see a new size.\n */\n private syncSize(): void {\n const prevWidth = this.width;\n const prevHeight = this.height;\n const prevViewportWidth = this.viewportWidth;\n const prevViewportHeight = this.viewportHeight;\n\n this.measureSize();\n\n const sizeChanged =\n this.width !== prevWidth ||\n this.height !== prevHeight ||\n this.viewportWidth !== prevViewportWidth ||\n this.viewportHeight !== prevViewportHeight;\n\n if (sizeChanged && this.context) {\n this.options.onResize?.(this.createFrameState(this.elapsed, 0));\n }\n }\n\n private measureSize(): void {\n if (!this.dom) return;\n\n if (this.fixedResolution) {\n const size = resizeCanvasToResolution(\n this.dom.canvas,\n this.dom.detached ? null : this.dom.target,\n this.fixedResolution\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n // Internal pixels per displayed CSS pixel under object-fit: contain.\n this.pixelRatio = Math.max(\n size.width / size.viewportWidth,\n size.height / size.viewportHeight\n );\n this.contentOffsetX =\n (size.viewportWidth - size.width / this.pixelRatio) / 2;\n this.contentOffsetY =\n (size.viewportHeight - size.height / this.pixelRatio) / 2;\n return;\n }\n\n this.contentOffsetX = 0;\n this.contentOffsetY = 0;\n this.pixelRatio = resolveDpr(this.options.dpr, this.options.maxDpr);\n const size = resizeCanvasToTarget(\n this.dom.canvas,\n this.dom.target,\n this.pixelRatio\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n }\n\n // Letterbox the fixed-resolution canvas instead of stretching it.\n private applyObjectFit(): void {\n if (!this.dom) return;\n const style = this.dom.canvas.style;\n if (this.fixedResolution && this.objectFitRestore === null) {\n this.objectFitRestore = style.objectFit ?? \"\";\n style.objectFit = \"contain\";\n } else if (!this.fixedResolution && this.objectFitRestore !== null) {\n style.objectFit = this.objectFitRestore;\n this.objectFitRestore = null;\n }\n }\n\n private scheduleFrame(): void {\n if (this.rafId || this.options.renderMode === \"demand\" || this.isManual)\n return;\n\n this.rafId = requestAnimationFrame((timestamp) => {\n this.rafId = 0;\n if (!this.running || this.destroyed) return;\n\n const seconds = timestamp / 1000;\n const rawDelta = this.lastTimestamp ? seconds - this.lastTimestamp : 0;\n const delta = Math.min(Math.max(rawDelta, 0), MAX_DELTA_SECONDS);\n this.lastTimestamp = seconds;\n this.elapsed += delta;\n this.renderInternal(this.elapsed, delta);\n this.scheduleFrame();\n });\n }\n\n private cancelFrame(): void {\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = 0;\n }\n this.lastTimestamp = 0;\n }\n\n private async init(): Promise<void> {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n this.failUnsupported(new UnsupportedError(\"WebGL requires a browser.\"));\n return;\n }\n\n this.dom = setupCanvas({\n ...(this.options.target !== undefined && { target: this.options.target }),\n ...(this.options.canvas !== undefined && { canvas: this.options.canvas }),\n ...(this.options.layer !== undefined && { layer: this.options.layer }),\n ...(this.options.canvasClass !== undefined && { canvasClass: this.options.canvasClass }),\n ...(this.options.canvasStyle !== undefined && { canvasStyle: this.options.canvasStyle }),\n // Only a missing target/canvas may fall back to a detached canvas; a\n // target that fails to resolve must still report TargetNotFoundError.\n detached:\n this.fixedResolution !== null &&\n this.options.target === undefined &&\n this.options.canvas === undefined\n });\n\n if (!this.dom) {\n this.failUnsupported(\n new TargetNotFoundError(\n \"Target or canvas not found. Pass `resolution` to render without a target.\"\n )\n );\n return;\n }\n\n let gl: GLContext | null;\n try {\n gl = this.options.createContext(this.dom.canvas);\n } catch (error) {\n this.failUnsupported(\n error instanceof UnsupportedError\n ? error\n : new UnsupportedError(String(error))\n );\n return;\n }\n if (!gl) {\n this.failUnsupported(new UnsupportedError(\"WebGL is not supported.\"));\n return;\n }\n\n if (this.fixedResolution) {\n try {\n assertWithinLimits(gl, this.fixedResolution);\n } catch (error) {\n this.failUnsupported(\n error instanceof Error ? error : new UnsupportedError(String(error))\n );\n return;\n }\n if (this.options.dpr !== undefined || this.options.maxDpr !== undefined) {\n this.debugWarn(\"`dpr` and `maxDpr` are ignored while `resolution` is set.\");\n }\n }\n\n this.context = gl;\n this.currentStatus = \"loading\";\n\n try {\n this.applyObjectFit();\n this.setupDomObservers();\n this.setupContextEvents();\n this.measureSize();\n await this.options.onInit(gl, this.width, this.height);\n if (this.destroyed) return;\n this.currentStatus = \"ready\";\n this.readyResolve?.();\n this.options.onReady?.();\n\n if (this.running || (this.options.autoStart ?? true)) {\n this.start();\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n } catch (error) {\n if (error instanceof UnsupportedError) this.failUnsupported(error);\n else this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private setupDomObservers(): void {\n if (!this.dom) return;\n const detached = this.dom.detached === true;\n\n // A detached canvas has no layout: it can never be measured, scrolled into\n // view or pointed at, so only document-level observers apply.\n if (!detached && (this.options.autoResize ?? true)) {\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n this.resizeObserver.observe(this.dom.target);\n }\n\n if (!detached && (this.options.pauseWhenOffscreen ?? true)) {\n this.intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[0];\n this.setGate(\"offscreen\", !entry?.isIntersecting);\n });\n this.intersectionObserver.observe(this.dom.target);\n }\n\n if (this.options.pauseWhenHidden ?? true) {\n if (document.hidden) this.gates.add(\"hidden\");\n const onVisibility = () => {\n this.setGate(\"hidden\", document.hidden);\n };\n document.addEventListener(\"visibilitychange\", onVisibility);\n this.removeListeners.push(() => {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n });\n }\n\n this.setupMotionObserver();\n\n if (detached) return;\n\n const onPointerMove = (event: Event) => {\n if (!this.dom) return;\n const pointerEvent = event as PointerEvent;\n const rect = this.dom.target.getBoundingClientRect();\n const x = pointerEvent.clientX - rect.left - this.contentOffsetX;\n const y = pointerEvent.clientY - rect.top - this.contentOffsetY;\n // Displayed content size in CSS px (smaller than rect when letterboxed).\n const contentWidth = this.fixedResolution\n ? this.width / this.pixelRatio\n : rect.width;\n const contentHeight = this.fixedResolution\n ? this.height / this.pixelRatio\n : rect.height;\n this.pointer.x = x * this.pixelRatio;\n this.pointer.y = (contentHeight - y) * this.pixelRatio;\n this.pointer.uvX = contentWidth > 0 ? x / contentWidth : 0;\n this.pointer.uvY = contentHeight > 0 ? 1 - y / contentHeight : 0;\n this.pointer.active = 1;\n\n if (this.shouldRenderOnDemand) this.render();\n };\n const onPointerLeave = () => {\n this.pointer.active = 0;\n if (this.shouldRenderOnDemand) this.render();\n };\n\n this.dom.target.addEventListener(\"pointermove\", onPointerMove);\n this.dom.target.addEventListener(\"pointerenter\", onPointerMove);\n this.dom.target.addEventListener(\"pointerleave\", onPointerLeave);\n this.removeListeners.push(() => {\n this.dom?.target.removeEventListener(\"pointermove\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerenter\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerleave\", onPointerLeave);\n });\n }\n\n private setupMotionObserver(): void {\n if (typeof window.matchMedia !== \"function\") return;\n\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.reducedMotionActive = query.matches;\n if (this.options.respectReducedMotion && query.matches) {\n this.gates.add(\"reducedMotion\");\n }\n\n const onChange = (event: MediaQueryListEvent) => {\n this.reducedMotionActive = event.matches;\n if (this.options.respectReducedMotion) {\n this.setGate(\"reducedMotion\", event.matches);\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n };\n\n query.addEventListener(\"change\", onChange);\n this.removeListeners.push(() => {\n query.removeEventListener(\"change\", onChange);\n });\n }\n\n private setupContextEvents(): void {\n if (!this.dom) return;\n\n const onLost = (event: Event) => {\n event.preventDefault();\n this.contextRestoredShouldRun = this.running;\n this.statusBeforeLoss = this.currentStatus;\n this.cancelFrame();\n this.context = null;\n this.currentStatus = \"context-lost\";\n this.options.onContextLost?.();\n this.options.onError?.(new UnsupportedError(\"WebGL context lost.\"));\n };\n\n const onRestored = () => {\n if (!this.dom || this.destroyed) return;\n const gl = this.options.createContext(this.dom.canvas);\n if (!gl) return;\n this.context = gl;\n\n const afterRestore = async () => {\n try {\n await this.options.onContextRestored?.(gl, this.width, this.height);\n // A stopped or manual-clock instance would otherwise stay\n // \"context-lost\", and render() would refuse to draw.\n if (this.currentStatus === \"context-lost\") this.currentStatus = this.statusBeforeLoss;\n if (this.contextRestoredShouldRun) this.start();\n else if (!this.isManual) this.render();\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n };\n void afterRestore();\n };\n\n this.dom.canvas.addEventListener(\"webglcontextlost\", onLost);\n this.dom.canvas.addEventListener(\"webglcontextrestored\", onRestored);\n this.removeListeners.push(() => {\n this.dom?.canvas.removeEventListener(\"webglcontextlost\", onLost);\n this.dom?.canvas.removeEventListener(\"webglcontextrestored\", onRestored);\n });\n }\n\n private failUnsupported(error: Error): void {\n this.currentStatus = \"unsupported\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private fail(error: Error): void {\n this.currentStatus = \"error\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private debugWarn(message: string): void {\n if (this.options.debug) {\n console.warn(`[frapx/runtime] ${message}`);\n }\n }\n}\n\nconst normalizeResolution = (resolution: Resolution): Resolution => {\n const [width, height] = resolution;\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width < 1 ||\n height < 1\n ) {\n throw new RangeError(`Invalid resolution: ${width}x${height}`);\n }\n return [Math.round(width), Math.round(height)];\n};\n\nconst assertWithinLimits = (gl: GLContext, resolution: Resolution): void => {\n const [width, height] = resolution;\n const viewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS) as\n | ArrayLike<number>\n | null;\n const renderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) as\n | number\n | null;\n const limit = (axis: 0 | 1): number =>\n Math.min(\n viewportDims?.[axis] ?? Number.POSITIVE_INFINITY,\n typeof renderbufferSize === \"number\"\n ? renderbufferSize\n : Number.POSITIVE_INFINITY\n );\n\n if (width > limit(0) || height > limit(1)) {\n throw new UnsupportedError(\n `Resolution ${width}x${height} exceeds this GPU's limit of ${limit(0)}x${limit(1)}.`\n );\n }\n};\n","export const toUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name : `u_${name}`;\n\nexport const fromUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name.slice(2) : name;\n","import type { ExplicitUniformInput, GLContext, UniformInput, UniformType } from \"../types\";\nimport { toUniformName } from \"./names\";\n\nexport type NormalizedUniform = {\n type: UniformType;\n value: number[] | Float32Array;\n};\n\nexport const normalizeUniform = (input: UniformInput): NormalizedUniform => {\n if (typeof input === \"number\") {\n return { type: \"float\", value: [input] };\n }\n\n if (input instanceof Float32Array) {\n if (input.length === 9) return { type: \"mat3\", value: input };\n if (input.length === 16) return { type: \"mat4\", value: input };\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n if (isExplicitUniform(input)) {\n return { type: input.type, value: input.value };\n }\n\n if (Array.isArray(input)) {\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n return { type: \"float\", value: [0] };\n};\n\nexport const applyUniform = (\n gl: GLContext,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n const value = uniform.value;\n\n switch (uniform.type) {\n case \"float\":\n gl.uniform1f(location, value[0] ?? 0);\n break;\n case \"vec2\":\n gl.uniform2f(location, value[0] ?? 0, value[1] ?? 0);\n break;\n case \"vec3\":\n gl.uniform3f(location, value[0] ?? 0, value[1] ?? 0, value[2] ?? 0);\n break;\n case \"vec4\":\n gl.uniform4f(\n location,\n value[0] ?? 0,\n value[1] ?? 0,\n value[2] ?? 0,\n value[3] ?? 0\n );\n break;\n case \"mat3\":\n gl.uniformMatrix3fv(location, false, value);\n break;\n case \"mat4\":\n gl.uniformMatrix4fv(location, false, value);\n break;\n }\n};\n\nexport const applyProgramUniform = (\n gl: GLContext,\n program: WebGLProgram,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n gl.useProgram(program);\n applyUniform(gl, location, uniform);\n};\n\n/**\n * Uploads every cached uniform to the bound program. Calls `onMissing` with\n * the name of each uniform the program lacks or optimized out.\n */\nexport const applyUniforms = (\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n cache: ReadonlyMap<string, NormalizedUniform>,\n onMissing?: (name: string) => void\n): void => {\n for (const [name, uniform] of cache) {\n const location = locations.get(name);\n if (!location) {\n onMissing?.(name);\n continue;\n }\n applyUniform(gl, location, uniform);\n }\n};\n\nexport const collectUniformLocations = (\n gl: GLContext,\n program: WebGLProgram\n): Map<string, WebGLUniformLocation> => {\n const locations = new Map<string, WebGLUniformLocation>();\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) as number;\n\n for (let index = 0; index < count; index += 1) {\n const active = gl.getActiveUniform(program, index);\n if (!active) continue;\n\n const name = active.name.replace(/\\[0\\]$/, \"\");\n const location = gl.getUniformLocation(program, name);\n if (location) {\n locations.set(name, location);\n }\n }\n\n return locations;\n};\n\nexport const createUniformCache = (\n uniforms: Record<string, UniformInput> | undefined\n): Map<string, NormalizedUniform> => {\n const cache = new Map<string, NormalizedUniform>();\n\n for (const [name, value] of Object.entries(uniforms ?? {})) {\n cache.set(toUniformName(name), normalizeUniform(value));\n }\n\n return cache;\n};\n\nconst isExplicitUniform = (input: unknown): input is ExplicitUniformInput => {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return false;\n return \"type\" in input && \"value\" in input;\n};\n","import type { UniformInput } from \"../types\";\nimport { toUniformName } from \"./names\";\nimport { normalizeUniform, type NormalizedUniform } from \"./uniforms\";\n\n/**\n * Supplies uniform values for a time, such as a keyframe timeline. Runtimes\n * call `get()` with the same time as `u_time` before drawing.\n */\nexport type UniformSource = {\n get(time: number): Readonly<Record<string, UniformInput>>;\n};\n\n/** Ordered sources whose values override the runtime's own uniforms. */\nexport type UniformBindings = {\n /** Adds `source`; a later source wins for the same name. Returns its removal. */\n add(source: UniformSource): () => void;\n readonly size: number;\n /** Merged, normalized values at `time`, keyed by uniform name (`u_` prefixed). */\n evaluate(time: number): Map<string, NormalizedUniform>;\n /** A stable string of the values at `time`, to notice when they change. */\n signature(time: number): string;\n};\n\nexport const createUniformBindings = (): UniformBindings => {\n const sources: UniformSource[] = [];\n\n const evaluate = (time: number): Map<string, NormalizedUniform> => {\n const merged = new Map<string, NormalizedUniform>();\n for (const source of sources) {\n for (const [name, value] of Object.entries(source.get(time))) {\n merged.set(toUniformName(name), normalizeUniform(value));\n }\n }\n return merged;\n };\n\n return {\n add(source) {\n sources.push(source);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n const index = sources.indexOf(source);\n if (index >= 0) sources.splice(index, 1);\n };\n },\n get size() {\n return sources.length;\n },\n evaluate,\n signature(time) {\n if (sources.length === 0) return \"\";\n let text = \"\";\n for (const [name, uniform] of evaluate(time)) {\n text += `${name}:${uniform.type}:${Array.from(uniform.value).join(\",\")};`;\n }\n return text;\n }\n };\n};\n\n// --- Keyframes -------------------------------------------------------------------\n\nexport type KeyframeValue =\n | number\n | readonly [number, number]\n | readonly [number, number, number]\n | readonly [number, number, number, number];\n\n/** `[time in seconds, value]`. */\nexport type Keyframe = readonly [number, KeyframeValue];\n\n/**\n * How a segment eases from one key to the next: `\"linear\"`, `\"smooth\"`\n * (smoothstep), `\"step\"` (hold the earlier key), or a function of the\n * segment's 0–1 progress.\n */\nexport type Ease = \"linear\" | \"smooth\" | \"step\" | ((t: number) => number);\n\nexport type KeyframeTrack = readonly Keyframe[] | { keys: readonly Keyframe[]; ease?: Ease };\n\nexport type KeyframeOptions = {\n /** Default ease for tracks that do not set their own. Defaults to `\"linear\"`. */\n ease?: Ease;\n};\n\nconst EASES: Record<Exclude<Ease, (t: number) => number>, (t: number) => number> = {\n linear: (t) => t,\n smooth: (t) => t * t * (3 - 2 * t),\n step: () => 0\n};\n\nconst toEaseFunction = (ease: Ease): ((t: number) => number) => {\n if (typeof ease === \"function\") return ease;\n const fn = EASES[ease];\n if (!fn) throw new RangeError(`Unknown ease: ${String(ease)}`);\n return fn;\n};\n\nconst componentsOf = (value: KeyframeValue): readonly number[] =>\n typeof value === \"number\" ? [value] : value;\n\ntype CompiledTrack = {\n times: number[];\n values: Array<readonly number[]>;\n scalar: boolean;\n ease: (t: number) => number;\n};\n\nconst isKeyList = (track: KeyframeTrack): track is readonly Keyframe[] => Array.isArray(track);\n\nconst compileTrack = (name: string, track: KeyframeTrack, fallback: Ease): CompiledTrack => {\n // Not `\"keys\" in track`: arrays have a keys() method.\n const list = isKeyList(track);\n const keys = list ? track : track.keys;\n const ease = toEaseFunction((list ? undefined : track.ease) ?? fallback);\n if (keys.length === 0) throw new TypeError(`Keyframe track ${name} has no keys.`);\n\n const sorted = [...keys].sort((a, b) => a[0] - b[0]);\n const scalar = typeof sorted[0]![1] === \"number\";\n const size = componentsOf(sorted[0]![1]).length;\n for (const [time, value] of sorted) {\n if (!Number.isFinite(time)) throw new TypeError(`Keyframe track ${name} has a non-finite time.`);\n const components = componentsOf(value);\n if ((typeof value === \"number\") !== scalar || components.length !== size) {\n throw new TypeError(`Keyframe track ${name} mixes values of different sizes.`);\n }\n if (!components.every(Number.isFinite)) {\n throw new TypeError(`Keyframe track ${name} has a non-finite value.`);\n }\n }\n return {\n times: sorted.map(([time]) => time),\n values: sorted.map(([, value]) => componentsOf(value)),\n scalar,\n ease\n };\n};\n\nconst sampleTrack = (track: CompiledTrack, time: number): UniformInput => {\n const { times, values } = track;\n const last = times.length - 1;\n let components: readonly number[];\n if (time <= times[0]!) {\n components = values[0]!;\n } else if (time >= times[last]!) {\n components = values[last]!;\n } else {\n // The last key at or before `time`.\n let low = 0;\n let high = last;\n while (high - low > 1) {\n const middle = (low + high) >> 1;\n if (times[middle]! <= time) low = middle;\n else high = middle;\n }\n const span = times[high]! - times[low]!;\n const t = span > 0 ? track.ease((time - times[low]!) / span) : 0;\n const from = values[low]!;\n const to = values[high]!;\n components = from.map((value, index) => value + (to[index]! - value) * t);\n }\n return track.scalar ? components[0]! : (Array.from(components) as UniformInput);\n};\n\n/**\n * A `UniformSource` that interpolates keyframes per component: floats and\n * vec2–vec4 as tuples. Keys may come in any order; times before the first key\n * or after the last hold that key's value.\n *\n * ```ts\n * fx.bindUniforms(keyframes({\n * camPos: [[0, [0, 1, 6]], [4, [3, 1.5, 2]]],\n * glow: { keys: [[0, 0], [2, 1]], ease: \"smooth\" }\n * }));\n * ```\n */\nexport const keyframes = (\n tracks: Readonly<Record<string, KeyframeTrack>>,\n options: KeyframeOptions = {}\n): UniformSource => {\n const fallback = options.ease ?? \"linear\";\n toEaseFunction(fallback);\n const compiled = Object.entries(tracks).map(\n ([name, track]) => [name, compileTrack(name, track, fallback)] as const\n );\n return {\n get(time) {\n const values: Record<string, UniformInput> = {};\n for (const [name, track] of compiled) values[name] = sampleTrack(track, time);\n return values;\n }\n };\n};\n","import type { GLContext, TextureInput, TextureOptions, TextureSource } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { toUniformName } from \"./names\";\n\nexport type LoadedTexture = {\n name: string;\n uniformName: string;\n sizeUniformName: string;\n texture: WebGLTexture;\n width: number;\n height: number;\n};\n\nexport const loadTexture = async (\n gl: GLContext,\n name: string,\n input: TextureInput,\n unit: number\n): Promise<LoadedTexture> => {\n const options = normalizeTextureInput(input);\n const source = await resolveSource(options.source);\n const texture = gl.createTexture();\n\n if (!texture) {\n throw new TextureLoadError(`Failed to create texture: ${name}`);\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flipY ?? true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n\n const wrap = getWrap(gl, options.wrap ?? \"clamp\");\n const filter = getFilter(gl, options.filter ?? \"linear\");\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n return {\n name,\n uniformName: toUniformName(name),\n sizeUniformName: toUniformName(`${name}Size`),\n texture,\n width: getSourceWidth(source),\n height: getSourceHeight(source)\n };\n};\n\nconst normalizeTextureInput = (input: TextureInput): TextureOptions => {\n if (typeof input === \"string\" || isTextureSource(input)) {\n return { source: input };\n }\n\n return input;\n};\n\nconst resolveSource = async (\n source: TextureSource\n): Promise<HTMLImageElement | HTMLCanvasElement> => {\n if (typeof source !== \"string\") {\n return source;\n }\n\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = source;\n\n try {\n await image.decode();\n } catch {\n throw new TextureLoadError(`Failed to load texture: ${source}`);\n }\n\n return image;\n};\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<TextureOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n\nconst getFilter = (\n gl: GLContext,\n filter: NonNullable<TextureOptions[\"filter\"]>\n): number => (filter === \"nearest\" ? gl.NEAREST : gl.LINEAR);\n\nconst isTextureSource = (\n input: unknown\n): input is HTMLImageElement | HTMLCanvasElement =>\n typeof HTMLImageElement !== \"undefined\" &&\n (input instanceof HTMLImageElement || input instanceof HTMLCanvasElement);\n\nconst getSourceWidth = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalWidth\" in source ? source.naturalWidth : source.width;\n\nconst getSourceHeight = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalHeight\" in source ? source.naturalHeight : source.height;\n","import type { GLContext, TextureInput, TextureMap } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { loadTexture, type LoadedTexture } from \"./textures\";\n\nexport type TextureSet = {\n /** The textures loaded so far, by name. */\n readonly textures: ReadonlyMap<string, LoadedTexture>;\n /** Whether `name` was given as an input, loaded or not. */\n hasInput(name: string): boolean;\n /**\n * Returns the texture unit for `name`, taking the lowest free unit on first\n * use. Runtimes reserve units for their own samplers (feedback, pass inputs)\n * here too, so they never collide with image textures.\n */\n reserveUnit(gl: GLContext, name: string): number;\n /**\n * Loads every input, then replaces the previously loaded textures. Used for\n * the initial load and after a context restore.\n */\n loadAll(gl: GLContext, isCancelled: () => boolean): Promise<void>;\n /**\n * Loads `input` as `name`. Resolves to the loaded texture, or `null` when a\n * later `set()` for the same name or `isCancelled()` superseded it (its\n * texture is deleted). On failure the unit is released if `name` is unused,\n * and the error is rethrown.\n */\n set(\n gl: GLContext,\n name: string,\n input: TextureInput,\n isCancelled: () => boolean\n ): Promise<LoadedTexture | null>;\n /**\n * Binds every loaded texture to its unit and points its sampler uniform at\n * it. Calls `onMissing` with the uniform name when the program lacks it.\n */\n bind(\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n onMissing?: (uniformName: string) => void\n ): void;\n /** Deletes every loaded texture. */\n dispose(gl: GLContext): void;\n};\n\n/**\n * Tracks named image textures and the texture units they occupy, for a\n * runtime that binds them to one or more programs.\n */\nexport const createTextureSet = (inputs: TextureMap = {}): TextureSet => {\n const textureInputs = new Map<string, TextureInput>(Object.entries(inputs));\n let textures = new Map<string, LoadedTexture>();\n const units = new Map<string, number>();\n const versions = new Map<string, number>();\n\n const reserveUnit = (gl: GLContext, name: string): number => {\n const existing = units.get(name);\n if (existing !== undefined) return existing;\n\n const maxUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number;\n const used = new Set(units.values());\n for (let unit = 0; unit < maxUnits; unit += 1) {\n if (!used.has(unit)) {\n units.set(name, unit);\n return unit;\n }\n }\n\n throw new TextureLoadError(\n `Texture unit limit exceeded while loading texture: ${name}`\n );\n };\n\n return {\n get textures() {\n return textures;\n },\n\n hasInput(name) {\n return textureInputs.has(name);\n },\n\n reserveUnit,\n\n async loadAll(gl, isCancelled) {\n const loaded = new Map<string, LoadedTexture>();\n for (const [name, input] of textureInputs) {\n if (isCancelled()) break;\n const unit = reserveUnit(gl, name);\n loaded.set(name, await loadTexture(gl, name, input, unit));\n }\n\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n textures = loaded;\n },\n\n async set(gl, name, input, isCancelled) {\n const version = (versions.get(name) ?? 0) + 1;\n versions.set(name, version);\n\n try {\n const unit = reserveUnit(gl, name);\n const loaded = await loadTexture(gl, name, input, unit);\n\n if (isCancelled() || versions.get(name) !== version) {\n gl.deleteTexture(loaded.texture);\n return null;\n }\n\n const previous = textures.get(name);\n textureInputs.set(name, input);\n textures.set(name, loaded);\n if (previous) gl.deleteTexture(previous.texture);\n return loaded;\n } catch (error) {\n if (!textures.has(name) && !textureInputs.has(name)) {\n units.delete(name);\n }\n throw error;\n }\n },\n\n bind(gl, locations, onMissing) {\n for (const texture of textures.values()) {\n const unit = units.get(texture.name);\n if (unit === undefined) continue;\n const location = locations.get(texture.uniformName);\n if (!location) {\n onMissing?.(texture.uniformName);\n continue;\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n gl.uniform1i(location, unit);\n }\n },\n\n dispose(gl) {\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n }\n };\n};\n","import type { GLContext } from \"../types\";\nimport { collectUniformLocations } from \"./uniforms\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isGLSL300\n} from \"./webgl\";\n\nexport type FullscreenProgram = {\n readonly program: WebGLProgram;\n /** Active uniform locations by name, array uniforms without `[0]`. */\n readonly locations: ReadonlyMap<string, WebGLUniformLocation>;\n /**\n * Binds the program, its quad buffer and `a_position`, so a draw is correct\n * whatever GL state user hooks left behind.\n */\n use(): void;\n /** Draws the fullscreen quad with the current GL state. */\n draw(): void;\n dispose(): void;\n};\n\n/**\n * Compiles `fragment` with a fullscreen-quad vertex shader (the GLSL ES 3.00\n * one when `fragment` starts with `#version 300 es`, unless `vertex` is\n * given) and leaves it bound.\n */\nexport const createFullscreenProgram = (\n gl: GLContext,\n fragment: string,\n vertex?: string\n): FullscreenProgram => {\n const defaultVertex = isGLSL300(fragment)\n ? defaultVertexShader300\n : defaultVertexShader;\n const program = createProgram(gl, vertex ?? defaultVertex, fragment);\n gl.useProgram(program);\n const buffer = createFullscreenBuffer(gl, program);\n const attribLocation = gl.getAttribLocation(program, \"a_position\");\n const locations = collectUniformLocations(gl, program);\n\n return {\n program,\n locations,\n use() {\n gl.useProgram(program);\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n if (attribLocation >= 0) {\n gl.enableVertexAttribArray(attribLocation);\n gl.vertexAttribPointer(attribLocation, 2, gl.FLOAT, false, 0, 0);\n }\n },\n draw() {\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose() {\n gl.deleteBuffer(buffer);\n gl.deleteProgram(program);\n }\n };\n};\n","import type { GLContext } from \"../types\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isWebGL2Context\n} from \"./webgl\";\n\nconst blitFragmentShader = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, v_uv);\n}\n`;\n\nconst blitFragmentShader300 = `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_texture;\nout vec4 fragColor;\n\nvoid main() {\n fragColor = texture(u_texture, v_uv);\n}\n`;\n\nexport type Blitter = {\n /**\n * Draws `texture` as a fullscreen quad into `target` (or the default\n * framebuffer when `target` is `null`), setting the viewport to\n * `width`/`height` first. Does not save or restore any other GL state.\n */\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void;\n /** Releases the GL resources owned by this blitter. */\n dispose(): void;\n};\n\n/**\n * Creates a reusable fullscreen-quad \"blit\" utility: draws a texture into a\n * framebuffer (or the canvas) using a minimal passthrough shader. Intended\n * for hand-rolled multi-pass/FBO pipelines; frapx's own multi-pass features\n * are built on the same primitive.\n */\nexport const createBlitter = (gl: GLContext): Blitter => {\n const program = createProgram(\n gl,\n isWebGL2Context(gl) ? defaultVertexShader300 : defaultVertexShader,\n isWebGL2Context(gl) ? blitFragmentShader300 : blitFragmentShader\n );\n const buffer = createFullscreenBuffer(gl, program);\n const textureUniform = gl.getUniformLocation(program, \"u_texture\");\n\n return {\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void {\n gl.bindFramebuffer(gl.FRAMEBUFFER, target);\n gl.viewport(0, 0, width, height);\n gl.useProgram(program);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n const location = gl.getAttribLocation(program, \"a_position\");\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (textureUniform) {\n gl.uniform1i(textureUniform, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose(): void {\n gl.deleteProgram(program);\n gl.deleteBuffer(buffer);\n }\n };\n};\n","import type {\n GLContext,\n PingPong,\n RenderTarget,\n RenderTargetFormat,\n RenderTargetOptions\n} from \"../types\";\nimport { ShaderCompileError, UnsupportedError } from \"./errors\";\nimport { isWebGL2Context } from \"./webgl\";\n\nconst DEFAULT_CLEAR_COLOR = [0, 0, 0, 0] as const;\n\n/**\n * Whether `format` can be allocated as a color attachment on `gl`. `rgba8` is\n * always available; `rgba16f` and `rgba32f` need WebGL2 and\n * `EXT_color_buffer_float`.\n * Enables the extension as a side effect when present.\n */\nexport const supportsRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat\n): boolean => {\n if (format === \"rgba8\") return true;\n return isWebGL2Context(gl) && gl.getExtension(\"EXT_color_buffer_float\") !== null;\n};\n\n/**\n * Resolves the format a render target will actually use. When `format` is not\n * supported this warns and returns `rgba8`, or throws `UnsupportedError` when\n * `formatFallback` is `false`.\n */\nexport const resolveRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat = \"rgba8\",\n formatFallback = true\n): RenderTargetFormat => {\n if (supportsRenderTargetFormat(gl, format)) return format;\n\n const reason = `${format} render targets need WebGL2 with EXT_color_buffer_float.`;\n if (!formatFallback) throw new UnsupportedError(reason);\n console.warn(`[frapx] ${reason} Falling back to rgba8.`);\n return \"rgba8\";\n};\n\n/**\n * Creates a texture-backed framebuffer to render into and sample from. The\n * storage is cleared to `clearColor` on creation and on every resize.\n */\nexport const createRenderTarget = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): RenderTarget => {\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n return new Target(gl, width, height, format, options);\n};\n\n/**\n * Creates two render targets of the same size and format for feedback-style\n * rendering: draw into `write` while sampling `read`, then `swap()`.\n */\nexport const createPingPong = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): PingPong => {\n // Resolve once so a fallback warns a single time for both targets.\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n let read: RenderTarget = new Target(gl, width, height, format, options);\n let write: RenderTarget;\n try {\n write = new Target(gl, width, height, format, options);\n } catch (error) {\n read.dispose();\n throw error;\n }\n\n return {\n get read() {\n return read;\n },\n get write() {\n return write;\n },\n format,\n swap() {\n const previous = read;\n read = write;\n write = previous;\n },\n resize(nextWidth: number, nextHeight: number) {\n read.resize(nextWidth, nextHeight);\n write.resize(nextWidth, nextHeight);\n },\n clear() {\n read.clear();\n write.clear();\n },\n dispose() {\n read.dispose();\n write.dispose();\n }\n };\n};\n\nclass Target implements RenderTarget {\n texture!: WebGLTexture;\n framebuffer!: WebGLFramebuffer;\n width: number;\n height: number;\n\n constructor(\n private readonly gl: GLContext,\n width: number,\n height: number,\n readonly format: RenderTargetFormat,\n private readonly options: RenderTargetOptions\n ) {\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n resize(width: number, height: number): void {\n if (width === this.width && height === this.height) return;\n this.release();\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n clear(): void {\n const gl = this.gl;\n const [r, g, b, a] = this.options.clearColor ?? DEFAULT_CLEAR_COLOR;\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.viewport(0, 0, this.width, this.height);\n gl.clearColor(r, g, b, a);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n dispose(): void {\n this.release();\n }\n\n private allocate(): void {\n const gl = this.gl;\n const texture = gl.createTexture();\n if (!texture) {\n throw new ShaderCompileError(\"Failed to create render target texture.\");\n }\n\n const framebuffer = gl.createFramebuffer();\n if (!framebuffer) {\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\"Failed to create render target framebuffer.\");\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (this.format !== \"rgba8\" && isWebGL2Context(gl)) {\n const half = this.format === \"rgba16f\";\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n half ? gl.RGBA16F : gl.RGBA32F,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n half ? gl.HALF_FLOAT : gl.FLOAT,\n null\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n null\n );\n }\n\n const wrap = getWrap(gl, this.options.wrap ?? \"clamp\");\n // Linear filtering of 32-bit float textures is an optional extension.\n const linear =\n this.options.filter !== \"nearest\" &&\n (this.format !== \"rgba32f\" || gl.getExtension(\"OES_texture_float_linear\") !== null);\n const filter = linear ? gl.LINEAR : gl.NEAREST;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.deleteFramebuffer(framebuffer);\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\n `Render target framebuffer (${this.format}) is incomplete: ${status}`\n );\n }\n\n this.texture = texture;\n this.framebuffer = framebuffer;\n this.clear();\n }\n\n private release(): void {\n this.gl.deleteFramebuffer(this.framebuffer);\n this.gl.deleteTexture(this.texture);\n }\n}\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<RenderTargetOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n"],"mappings":"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","names":["size","getWrap"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frapx/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Shared WebGL runtime host for frapx packages.",
5
5
  "type": "module",
6
6
  "sideEffects": false,