@frapx/core 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0 - 2026-10-30
4
+
5
+ ### Added
6
+
7
+ - `onStatusChange(status)` host option: called synchronously with the new value each time `status` changes, never for the initial `"idle"` nor before the factory returns. Every status change now goes through one place, so a change is reported exactly once; a `destroy()` from the callback stops the transition. A restored context reports only what the gates allow (no passing `"running"` when it comes back hidden).
8
+ - `time` on the instance: the time of the last frame drawn — the value `setTime()` would need to reproduce that frame. While gated it is the time the loop stopped at, and with a `timeSource` it is the last value read from the source. Lets a page read back where the picture is, for example to start audio at the same position or to render a frame counter.
9
+
10
+ ### Changed
11
+
12
+ - Debug warnings start with `[frapx/core]` instead of the pre-rename `[frapx/runtime]`.
13
+
14
+ ## 0.6.0 - 2026-10-23
15
+
16
+ ### Added
17
+
18
+ - `timeSource` host option and `setTimeSource(source | null)`: the realtime loop takes each frame's time from an external transport (`() => seconds`), such as an audio player, while the offscreen, hidden and reduced-motion gates and the pointer keep working. `time` is the source's value, never clamped; `delta` is the step from the previous frame, clamped to `[0, 0.1]`, and 0 when the source goes back or on the first frame after a pause. The reduced-motion still frame reads the source; `render()` and `captureFrame()` redraw at the last frame's time. A manual clock ignores the source but keeps it, and `renderMode: "demand"` (no frame loop) never reads it, with a `debug` warning. New `TimeSource` type.
19
+
20
+ ### Fixed
21
+
22
+ - An unawaited `ready` no longer produces an unhandled rejection when `destroy()` rejects it with `DestroyedError` (for example a React StrictMode effect cleanup) or when the environment is unsupported (`UnsupportedError`, including the no-op instance created without a browser). Awaiting `ready` or `.then(…, onError)` still observes the rejection. Setup failures and `TargetNotFoundError` still surface.
23
+
3
24
  ## 0.5.1 - 2026-10-20
4
25
 
5
26
  ### Fixed
package/dist/index.d.ts CHANGED
@@ -10,6 +10,12 @@ type RenderMode = "always" | "demand";
10
10
  * drawn only by explicit `render()` calls, so output is deterministic.
11
11
  */
12
12
  type ClockMode = "realtime" | "manual";
13
+ /**
14
+ * Returns the current time in seconds from an external transport, such as an
15
+ * audio player's position. Under the realtime clock it replaces
16
+ * requestAnimationFrame time while the gates keep working.
17
+ */
18
+ type TimeSource = () => number;
13
19
  /** Fixed internal render size in pixels: `[width, height]`. */
14
20
  type Resolution = readonly [number, number];
15
21
  type DprOption = "auto" | number | (() => number);
@@ -144,6 +150,8 @@ type RuntimeHostOptions = {
144
150
  renderMode?: RenderMode;
145
151
  /** Defaults to `"realtime"`. See {@link ClockMode}. */
146
152
  clock?: ClockMode;
153
+ /** Takes realtime loop frames' time from this source; unread in demand mode. See {@link TimeSource}. */
154
+ timeSource?: TimeSource;
147
155
  /**
148
156
  * Fixes the internal render size instead of following the target's size.
149
157
  * Required when neither `target` nor `canvas` is given.
@@ -172,6 +180,13 @@ type RuntimeHostOptions = {
172
180
  onContextRestored?: (gl: GLContext, width: number, height: number) => Promise<void> | void;
173
181
  onReady?: () => void;
174
182
  onError?: (error: Error) => void;
183
+ /**
184
+ * Called synchronously each time `status` changes value, with the new
185
+ * value. Not called for the initial `"idle"`, and never before the factory
186
+ * returns: initialization starts on a microtask after creation. The
187
+ * callback may call `destroy()`; the transition stops there.
188
+ */
189
+ onStatusChange?: (status: ShaderStatus) => void;
175
190
  };
176
191
  type RuntimeHostInstance = {
177
192
  readonly canvas: HTMLCanvasElement | null;
@@ -180,6 +195,13 @@ type RuntimeHostInstance = {
180
195
  readonly supported: boolean;
181
196
  readonly ready: Promise<void>;
182
197
  readonly clock: ClockMode;
198
+ /**
199
+ * The time of the last frame drawn, before any `accumulation.loop`
200
+ * wrapping. Use it to read back where the picture is, for example to
201
+ * start audio at the same position or to render a frame counter.
202
+ */
203
+ readonly time: number;
204
+ readonly timeSource: TimeSource | null;
183
205
  start(): void;
184
206
  stop(): void;
185
207
  render(): void;
@@ -193,6 +215,12 @@ type RuntimeHostInstance = {
193
215
  setTime(seconds: number): void;
194
216
  /** Switches between realtime and manual clocks after creation. */
195
217
  setClock(clock: ClockMode): void;
218
+ /**
219
+ * Sets or removes the realtime clock's external time source. Each realtime
220
+ * frame then takes `time = source()` and `delta` from the previous frame's
221
+ * value, clamped to `[0, 0.1]`. A manual clock ignores the source but keeps it.
222
+ */
223
+ setTimeSource(source: TimeSource | null): void;
196
224
  /**
197
225
  * Fixes the internal render size, or follows the target's size again when
198
226
  * `null`. Throws `UnsupportedError` when the size exceeds the GPU limits.
@@ -462,4 +490,4 @@ declare const createRenderTarget: (gl: GLContext, width: number, height: number,
462
490
  */
463
491
  declare const createPingPong: (gl: GLContext, width: number, height: number, options?: RenderTargetOptions) => PingPong;
464
492
 
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 };
493
+ 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 TimeSource, 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
@@ -289,6 +289,7 @@ var applyCanvasStyle = (canvas, options, shouldPosition) => {
289
289
  // src/host.ts
290
290
  var MAX_DELTA_SECONDS = 0.1;
291
291
  var IDLE_POINTER = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };
292
+ var clampDelta = (delta) => Math.min(Math.max(delta, 0), MAX_DELTA_SECONDS);
292
293
  var createRuntimeHost = (options) => {
293
294
  return new RuntimeHost(options);
294
295
  };
@@ -323,12 +324,16 @@ var RuntimeHost = class {
323
324
  this.statusBeforeLoss = "idle";
324
325
  this.manualDelta = 0;
325
326
  this.lastManualTime = null;
327
+ // The source's value at the previous loop frame; null restarts u_delta at 0.
328
+ this.lastSourceTime = null;
326
329
  this.objectFitRestore = null;
327
330
  // Letterbox offset (CSS px) of the contained canvas content inside the target.
328
331
  this.contentOffsetX = 0;
329
332
  this.contentOffsetY = 0;
330
333
  this.options = options;
331
334
  this.clockMode = options.clock ?? "realtime";
335
+ this.source = options.timeSource ?? null;
336
+ this.warnIfSourceUnread();
332
337
  this.fixedResolution = options.resolution ? normalizeResolution(options.resolution) : null;
333
338
  this.ready = new Promise((resolve, reject) => {
334
339
  this.readyResolve = resolve;
@@ -353,6 +358,18 @@ var RuntimeHost = class {
353
358
  get clock() {
354
359
  return this.clockMode;
355
360
  }
361
+ /**
362
+ * The time of the last frame drawn, before any `accumulation.loop`
363
+ * wrapping: the value `setTime()` would need to reproduce that frame.
364
+ * While gated it is the time the loop stopped at, and with a time source
365
+ * it is the last value read from the source.
366
+ */
367
+ get time() {
368
+ return this.elapsed;
369
+ }
370
+ get timeSource() {
371
+ return this.source;
372
+ }
356
373
  start() {
357
374
  if (this.destroyed || this.currentStatus === "unsupported") return;
358
375
  this.running = true;
@@ -362,7 +379,7 @@ var RuntimeHost = class {
362
379
  this.running = false;
363
380
  this.cancelFrame();
364
381
  if (!this.destroyed && this.currentStatus !== "unsupported") {
365
- this.currentStatus = "paused";
382
+ this.setStatus("paused");
366
383
  }
367
384
  }
368
385
  render() {
@@ -393,6 +410,18 @@ var RuntimeHost = class {
393
410
  this.lastManualTime = null;
394
411
  this.reconcile();
395
412
  }
413
+ setTimeSource(source) {
414
+ if (this.destroyed) return;
415
+ this.source = source;
416
+ this.lastSourceTime = null;
417
+ this.warnIfSourceUnread();
418
+ }
419
+ // Only the realtime loop reads the source, and demand mode runs no loop.
420
+ warnIfSourceUnread() {
421
+ if (this.source && this.options.renderMode === "demand") {
422
+ this.debugWarn('`timeSource` is not read with renderMode "demand", which runs no frame loop. Call setTime() instead.');
423
+ }
424
+ }
396
425
  setResolution(resolution) {
397
426
  if (this.destroyed) return;
398
427
  if (resolution === null) {
@@ -478,12 +507,37 @@ var RuntimeHost = class {
478
507
  if (dom?.restoredPosition !== null && dom && this.options.target) {
479
508
  dom.target.style.position = dom.restoredPosition;
480
509
  }
481
- this.currentStatus = "destroyed";
510
+ this.setStatus("destroyed");
511
+ this.markReadyHandled();
482
512
  this.readyReject?.(new DestroyedError("Runtime host was destroyed."));
483
513
  }
484
514
  get isManual() {
485
515
  return this.clockMode === "manual";
486
516
  }
517
+ get followsSource() {
518
+ return this.source !== null && !this.isManual;
519
+ }
520
+ // A non-finite reading holds the previous time instead of throwing in a frame.
521
+ readSource() {
522
+ if (!this.followsSource) return null;
523
+ const now = this.source();
524
+ return Number.isFinite(now) ? now : null;
525
+ }
526
+ // The static frame takes the source's current time without a delta.
527
+ syncSourceTime() {
528
+ const now = this.readSource();
529
+ if (now !== null) this.elapsed = now;
530
+ }
531
+ // A loop frame under a source: time is the source's value, never clamped;
532
+ // delta is the step from the previous frame, 0 when it went back.
533
+ advanceFromSource() {
534
+ const now = this.readSource();
535
+ if (now === null) return 0;
536
+ const previous = this.lastSourceTime;
537
+ this.lastSourceTime = now;
538
+ this.elapsed = now;
539
+ return previous === null ? 0 : clampDelta(now - previous);
540
+ }
487
541
  get isDetached() {
488
542
  if (this.dom) return this.dom.detached === true;
489
543
  return this.options.target === void 0 && this.options.canvas === void 0;
@@ -505,28 +559,30 @@ var RuntimeHost = class {
505
559
  else this.gates.delete(gate);
506
560
  this.reconcile();
507
561
  }
508
- reconcile() {
509
- if (this.destroyed || this.currentStatus === "unsupported" || this.currentStatus === "error" || this.currentStatus === "context-lost") {
562
+ // `restoring` lets a restored context leave "context-lost" straight to what
563
+ // the gates allow, so the status never passes through a stale value.
564
+ reconcile(restoring = false) {
565
+ if (this.destroyed || this.currentStatus === "unsupported" || this.currentStatus === "error" || this.currentStatus === "context-lost" && !restoring) {
510
566
  return;
511
567
  }
512
568
  if (this.isManual) {
513
569
  this.cancelFrame();
514
- this.currentStatus = "paused";
570
+ this.setStatus("paused");
515
571
  return;
516
572
  }
517
573
  if (this.running) {
518
574
  if (this.hasVisibilityBlock) {
519
575
  this.cancelFrame();
520
- this.currentStatus = "paused";
576
+ this.setStatus("paused");
521
577
  return;
522
578
  }
523
579
  if (this.hasMotionBlock) {
524
580
  this.cancelFrame();
525
- this.currentStatus = "paused";
581
+ this.setStatus("paused");
526
582
  this.renderStaticFrame();
527
583
  return;
528
584
  }
529
- this.currentStatus = "running";
585
+ this.setStatus("running");
530
586
  if (this.options.renderMode === "demand") this.render();
531
587
  else this.scheduleFrame();
532
588
  return;
@@ -535,6 +591,7 @@ var RuntimeHost = class {
535
591
  }
536
592
  renderStaticFrame() {
537
593
  if (this.hasVisibilityBlock) return;
594
+ this.syncSourceTime();
538
595
  this.renderInternal(this.elapsed, 0);
539
596
  }
540
597
  renderInternal(time, delta) {
@@ -674,10 +731,14 @@ var RuntimeHost = class {
674
731
  this.rafId = 0;
675
732
  if (!this.running || this.destroyed) return;
676
733
  const seconds = timestamp / 1e3;
677
- const rawDelta = this.lastTimestamp ? seconds - this.lastTimestamp : 0;
678
- const delta = Math.min(Math.max(rawDelta, 0), MAX_DELTA_SECONDS);
734
+ let delta;
735
+ if (this.followsSource) {
736
+ delta = this.advanceFromSource();
737
+ } else {
738
+ delta = this.lastTimestamp ? clampDelta(seconds - this.lastTimestamp) : 0;
739
+ this.elapsed += delta;
740
+ }
679
741
  this.lastTimestamp = seconds;
680
- this.elapsed += delta;
681
742
  this.renderInternal(this.elapsed, delta);
682
743
  this.scheduleFrame();
683
744
  });
@@ -688,6 +749,7 @@ var RuntimeHost = class {
688
749
  this.rafId = 0;
689
750
  }
690
751
  this.lastTimestamp = 0;
752
+ this.lastSourceTime = null;
691
753
  }
692
754
  async init() {
693
755
  if (typeof window === "undefined" || typeof document === "undefined") {
@@ -739,7 +801,8 @@ var RuntimeHost = class {
739
801
  }
740
802
  }
741
803
  this.context = gl;
742
- this.currentStatus = "loading";
804
+ this.setStatus("loading");
805
+ if (this.destroyed) return;
743
806
  try {
744
807
  this.applyObjectFit();
745
808
  this.setupDomObservers();
@@ -747,7 +810,8 @@ var RuntimeHost = class {
747
810
  this.measureSize();
748
811
  await this.options.onInit(gl, this.width, this.height);
749
812
  if (this.destroyed) return;
750
- this.currentStatus = "ready";
813
+ this.setStatus("ready");
814
+ if (this.destroyed) return;
751
815
  this.readyResolve?.();
752
816
  this.options.onReady?.();
753
817
  if (this.running || (this.options.autoStart ?? true)) {
@@ -844,7 +908,8 @@ var RuntimeHost = class {
844
908
  this.statusBeforeLoss = this.currentStatus;
845
909
  this.cancelFrame();
846
910
  this.context = null;
847
- this.currentStatus = "context-lost";
911
+ this.setStatus("context-lost");
912
+ if (this.destroyed) return;
848
913
  this.options.onContextLost?.();
849
914
  this.options.onError?.(new UnsupportedError("WebGL context lost."));
850
915
  };
@@ -856,9 +921,14 @@ var RuntimeHost = class {
856
921
  const afterRestore = async () => {
857
922
  try {
858
923
  await this.options.onContextRestored?.(gl, this.width, this.height);
859
- if (this.currentStatus === "context-lost") this.currentStatus = this.statusBeforeLoss;
860
- if (this.contextRestoredShouldRun) this.start();
861
- else if (!this.isManual) this.render();
924
+ if (this.destroyed) return;
925
+ if (this.contextRestoredShouldRun) {
926
+ this.running = true;
927
+ this.reconcile(true);
928
+ return;
929
+ }
930
+ if (this.currentStatus === "context-lost") this.setStatus(this.statusBeforeLoss);
931
+ if (!this.isManual) this.render();
862
932
  } catch (error) {
863
933
  this.fail(error instanceof Error ? error : new Error(String(error)));
864
934
  }
@@ -873,20 +943,33 @@ var RuntimeHost = class {
873
943
  });
874
944
  }
875
945
  failUnsupported(error) {
876
- this.currentStatus = "unsupported";
946
+ this.setStatus("unsupported");
877
947
  this.debugWarn(error.message);
878
948
  this.options.onError?.(error);
949
+ if (error instanceof UnsupportedError) this.markReadyHandled();
879
950
  this.readyReject?.(error);
880
951
  }
881
952
  fail(error) {
882
- this.currentStatus = "error";
953
+ this.setStatus("error");
883
954
  this.debugWarn(error.message);
884
955
  this.options.onError?.(error);
885
956
  this.readyReject?.(error);
886
957
  }
958
+ // The only writer of currentStatus, so onStatusChange sees every change once.
959
+ setStatus(status) {
960
+ if (status === this.currentStatus) return;
961
+ this.currentStatus = status;
962
+ this.options.onStatusChange?.(status);
963
+ }
964
+ // Keeps an unawaited `ready` from surfacing as an unhandled rejection, e.g.
965
+ // after a StrictMode cleanup or during SSR. Callers still see the rejection.
966
+ markReadyHandled() {
967
+ this.ready.catch(() => {
968
+ });
969
+ }
887
970
  debugWarn(message) {
888
971
  if (this.options.debug) {
889
- console.warn(`[frapx/runtime] ${message}`);
972
+ console.warn(`[frapx/core] ${message}`);
890
973
  }
891
974
  }
892
975
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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"]}
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 TimeSource\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\nconst clampDelta = (delta: number): number =>\n Math.min(Math.max(delta, 0), MAX_DELTA_SECONDS);\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 source: TimeSource | null;\n // The source's value at the previous loop frame; null restarts u_delta at 0.\n private lastSourceTime: 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.source = options.timeSource ?? null;\n this.warnIfSourceUnread();\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 /**\n * The time of the last frame drawn, before any `accumulation.loop`\n * wrapping: the value `setTime()` would need to reproduce that frame.\n * While gated it is the time the loop stopped at, and with a time source\n * it is the last value read from the source.\n */\n get time(): number {\n return this.elapsed;\n }\n\n get timeSource(): TimeSource | null {\n return this.source;\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.setStatus(\"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 // Redraws at the last frame's time: refinement and reduced motion must\n // not chase a running source.\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 setTimeSource(source: TimeSource | null): void {\n if (this.destroyed) return;\n this.source = source;\n this.lastSourceTime = null;\n this.warnIfSourceUnread();\n }\n\n // Only the realtime loop reads the source, and demand mode runs no loop.\n private warnIfSourceUnread(): void {\n if (this.source && this.options.renderMode === \"demand\") {\n this.debugWarn(\"`timeSource` is not read with renderMode \\\"demand\\\", which runs no frame loop. Call setTime() instead.\");\n }\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.setStatus(\"destroyed\");\n this.markReadyHandled();\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 followsSource(): boolean {\n return this.source !== null && !this.isManual;\n }\n\n // A non-finite reading holds the previous time instead of throwing in a frame.\n private readSource(): number | null {\n if (!this.followsSource) return null;\n const now = this.source!();\n return Number.isFinite(now) ? now : null;\n }\n\n // The static frame takes the source's current time without a delta.\n private syncSourceTime(): void {\n const now = this.readSource();\n if (now !== null) this.elapsed = now;\n }\n\n // A loop frame under a source: time is the source's value, never clamped;\n // delta is the step from the previous frame, 0 when it went back.\n private advanceFromSource(): number {\n const now = this.readSource();\n if (now === null) return 0;\n const previous = this.lastSourceTime;\n this.lastSourceTime = now;\n this.elapsed = now;\n return previous === null ? 0 : clampDelta(now - previous);\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 // `restoring` lets a restored context leave \"context-lost\" straight to what\n // the gates allow, so the status never passes through a stale value.\n private reconcile(restoring = false): void {\n if (\n this.destroyed ||\n this.currentStatus === \"unsupported\" ||\n this.currentStatus === \"error\" ||\n (this.currentStatus === \"context-lost\" && !restoring)\n ) {\n return;\n }\n\n if (this.isManual) {\n this.cancelFrame();\n this.setStatus(\"paused\");\n return;\n }\n\n if (this.running) {\n if (this.hasVisibilityBlock) {\n this.cancelFrame();\n this.setStatus(\"paused\");\n return;\n }\n\n if (this.hasMotionBlock) {\n this.cancelFrame();\n this.setStatus(\"paused\");\n this.renderStaticFrame();\n return;\n }\n\n this.setStatus(\"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.syncSourceTime();\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 let delta: number;\n if (this.followsSource) {\n delta = this.advanceFromSource();\n } else {\n delta = this.lastTimestamp ? clampDelta(seconds - this.lastTimestamp) : 0;\n this.elapsed += delta;\n }\n this.lastTimestamp = seconds;\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 this.lastSourceTime = null;\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.setStatus(\"loading\");\n // onStatusChange may have destroyed the host.\n if (this.destroyed) return;\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.setStatus(\"ready\");\n if (this.destroyed) return;\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.setStatus(\"context-lost\");\n if (this.destroyed) return;\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.destroyed) return;\n if (this.contextRestoredShouldRun) {\n // Gates may have closed during the loss; report only their result.\n this.running = true;\n this.reconcile(true);\n return;\n }\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.setStatus(this.statusBeforeLoss);\n 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.setStatus(\"unsupported\");\n this.debugWarn(error.message);\n this.options.onError?.(error);\n // An unsupported environment is expected; a missing target stays loud.\n if (error instanceof UnsupportedError) this.markReadyHandled();\n this.readyReject?.(error);\n }\n\n private fail(error: Error): void {\n this.setStatus(\"error\");\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n // The only writer of currentStatus, so onStatusChange sees every change once.\n private setStatus(status: ShaderStatus): void {\n if (status === this.currentStatus) return;\n this.currentStatus = status;\n this.options.onStatusChange?.(status);\n }\n\n // Keeps an unawaited `ready` from surfacing as an unhandled rejection, e.g.\n // after a StrictMode cleanup or during SSR. Callers still see the rejection.\n private markReadyHandled(): void {\n this.ready.catch(() => {});\n }\n\n private debugWarn(message: string): void {\n if (this.options.debug) {\n console.warn(`[frapx/core] ${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,7 +1,15 @@
1
1
  {
2
2
  "name": "@frapx/core",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Shared WebGL runtime host for frapx packages.",
5
+ "keywords": [
6
+ "webgl",
7
+ "webgl2",
8
+ "shader",
9
+ "glsl",
10
+ "runtime",
11
+ "frapx"
12
+ ],
5
13
  "type": "module",
6
14
  "sideEffects": false,
7
15
  "exports": {
@@ -32,6 +40,10 @@
32
40
  "url": "git+https://github.com/kramhash/frapx.git",
33
41
  "directory": "packages/core"
34
42
  },
43
+ "homepage": "https://kramhash.github.io/frapx/packages/core/",
44
+ "bugs": {
45
+ "url": "https://github.com/kramhash/frapx/issues"
46
+ },
35
47
  "publishConfig": {
36
48
  "access": "public"
37
49
  },