@frapx/core 0.2.0 → 0.4.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,11 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 - 2026-10-13
4
+
5
+ ### Added
6
+
7
+ - Shared program state for runtimes built on the host, moved here from `@frapx/fx-canvas` so `@frapx/fx-passes` can reuse it:
8
+ - Uniform helpers `normalizeUniform`, `applyUniform`, `applyProgramUniform`, `applyUniforms`, `collectUniformLocations` and `createUniformCache`, with the `NormalizedUniform` type and the uniform input types (`UniformInput`, `UniformInputMap`, `UniformRuntimeValue`, `ExplicitUniformInput`, `UniformType`, `UniformScalar`, `UniformVec2`–`UniformVec4`).
9
+ - `createTextureSet(inputs)`: named image textures with texture-unit allocation (`reserveUnit` also covers runtime-owned samplers), superseded-load handling, binding and disposal.
10
+ - `createFullscreenProgram(gl, fragment, vertex?)`: compiles a fragment shader with the matching fullscreen-quad vertex shader and exposes its uniform locations, `use()`, `draw()` and `dispose()`.
11
+ - `rgba32f` render targets (`createRenderTarget` / `createPingPong`), with the same WebGL2 + `EXT_color_buffer_float` requirement as `rgba16f`. They sample with nearest filtering unless `OES_texture_float_linear` is available. `captureFrame({ format: "rgba16f" })` also reads an `rgba32f` capture source.
12
+ - `onCaptureDraw(state, signal)` host option: draws the frame `captureFrame()` reads over several tasks (for example sample accumulation that waits for the GPU between draws). The host holds its render lock until it settles, so other frames do not interleave, and reads the result in the settling task. Resizes requested meanwhile apply after the frame is read, and a context lost (even if restored) meanwhile rejects the capture.
13
+ - `signal` capture option: an aborted signal rejects `captureFrame()` before drawing and is passed to `onCaptureDraw`.
14
+ - `waitForGpu(gl)`: resolves once the GPU has finished the submitted work by polling a fence between tasks, so long renders can yield and avoid the GPU watchdog. Resolves immediately on WebGL1.
15
+
16
+ ## 0.3.0 - 2026-10-10
17
+
18
+ ### Added
19
+
20
+ - `clock: "manual"` option on `createRuntimeHost` and `setClock()` / `setTime()` on the instance. A manual clock never schedules frames: time changes only through `setTime()` (with `delta` the difference from the previous call) and frames are drawn only by `render()`, which ignores offscreen/hidden gating. The frame state reports a neutral pointer and `reducedMotion: false`, so identical time and uniforms produce identical pixels.
21
+ - `resolution` option and `setResolution([w, h] | null)` to fix the internal render size independently of the target. The canvas is letterboxed with `object-fit: contain`, the viewport size still tracks the target, and `pixelRatio` is derived from the fit (`dpr` / `maxDpr` are ignored). Sizes beyond the GPU's viewport/renderbuffer limits fail with `UnsupportedError`.
22
+ - Creating a host with neither `target` nor `canvas` now works when `resolution` is given: a detached canvas is created and no layout observers are attached.
23
+ - `ClockMode` and `Resolution` types, and `SetupCanvasOptions.detached` / `DomSetup.detached`.
24
+ - `createRenderTarget(gl, width, height, options)` and `createPingPong(...)`: texture-backed framebuffers with an explicit `format` (`"rgba8"` or `"rgba16f"`). `rgba16f` needs WebGL2 with `EXT_color_buffer_float`; otherwise it warns and allocates `rgba8`, or throws `UnsupportedError` with `formatFallback: false`. `supportsRenderTargetFormat` / `resolveRenderTargetFormat` expose the detection, and `isWebGL2Context` is now exported.
25
+ - `captureFrame({ format })` on the host: draws a frame (bypassing pause gates) and reads it back in the same task as a PNG `Blob`, `Uint8Array` (`rgba8`) or `Float32Array` (`rgba16f`, from the new `captureSource` option), with rows top first.
26
+ - Added the MIT `LICENSE` file to the published package.
27
+
28
+ ### Changed
29
+
30
+ - An `UnsupportedError` thrown from `onInit` now sets status `"unsupported"` instead of `"error"`.
31
+ - A throwing `onDraw` no longer leaves the host stuck in its in-render state.
32
+
3
33
  ## 0.2.0 - 2026-07-12
4
34
 
5
35
  ### Changed
6
36
 
7
37
  - **Breaking: package renamed from `@frapx/runtime` to `@frapx/core`.** No API changes — only the npm package name and import path change. `@frapx/runtime` is deprecated on npm and will not receive further updates.
8
38
 
39
+ ### Added
40
+
41
+ - _Correction (noted after release):_ this version also shipped the `onResize` host option (called only when the measured size actually changes) and the `createBlitter(gl)` fullscreen-quad blit utility, which the entry above omitted.
42
+
9
43
  ## 0.1.0 - 2026-06-27
10
44
 
11
45
  Initial release. Shared WebGL runtime extracted from `@frapx/fx-canvas`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kramhash
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -8,4 +8,4 @@ If you are building a WebGL experience, you most likely want [`@frapx/fx-canvas`
8
8
 
9
9
  ## License
10
10
 
11
- MIT
11
+ MIT © 2026 kramhash. See [LICENSE](./LICENSE).
package/dist/index.d.ts CHANGED
@@ -4,6 +4,14 @@ export { glsl, glslUtils } from './glsl.js';
4
4
  type GLContext = WebGLRenderingContext | WebGL2RenderingContext;
5
5
  type ShaderLayer = "background" | "overlay";
6
6
  type RenderMode = "always" | "demand";
7
+ /**
8
+ * `"realtime"` advances time from requestAnimationFrame. `"manual"` never
9
+ * renders on its own: time only changes through `setTime()` and frames are
10
+ * drawn only by explicit `render()` calls, so output is deterministic.
11
+ */
12
+ type ClockMode = "realtime" | "manual";
13
+ /** Fixed internal render size in pixels: `[width, height]`. */
14
+ type Resolution = readonly [number, number];
7
15
  type DprOption = "auto" | number | (() => number);
8
16
  type ShaderStatus = "idle" | "loading" | "ready" | "running" | "paused" | "error" | "unsupported" | "context-lost" | "destroyed";
9
17
  type TextureSource = string | HTMLImageElement | HTMLCanvasElement;
@@ -15,6 +23,78 @@ type TextureOptions = {
15
23
  };
16
24
  type TextureInput = TextureSource | TextureOptions;
17
25
  type TextureMap = Record<string, TextureInput>;
26
+ type UniformScalar = number;
27
+ type UniformVec2 = [number, number] | readonly [number, number];
28
+ type UniformVec3 = [number, number, number] | readonly [number, number, number];
29
+ type UniformVec4 = [number, number, number, number] | readonly [number, number, number, number];
30
+ type UniformType = "float" | "vec2" | "vec3" | "vec4" | "mat3" | "mat4";
31
+ type ExplicitUniformInput = {
32
+ type: UniformType;
33
+ value: number[] | Float32Array;
34
+ };
35
+ type UniformInput = UniformScalar | UniformVec2 | UniformVec3 | UniformVec4 | Float32Array | ExplicitUniformInput;
36
+ type UniformInputMap = Record<string, UniformInput>;
37
+ type UniformRuntimeValue<T> = T extends ExplicitUniformInput ? ExplicitUniformInput : T extends Float32Array ? Float32Array : T extends readonly [number, number] ? UniformVec2 : T extends readonly [number, number, number] ? UniformVec3 : T extends readonly [number, number, number, number] ? UniformVec4 : T extends number ? number : UniformInput;
38
+ /**
39
+ * Storage format of a render target. `rgba16f` (half float) and `rgba32f`
40
+ * (float) need WebGL2 with `EXT_color_buffer_float`. `rgba32f` is sampled with
41
+ * nearest filtering unless `OES_texture_float_linear` is available.
42
+ */
43
+ type RenderTargetFormat = "rgba8" | "rgba16f" | "rgba32f";
44
+ type RenderTargetOptions = {
45
+ /** Defaults to `"rgba8"`. */
46
+ format?: RenderTargetFormat;
47
+ /**
48
+ * When the requested format is unsupported, `true` (default) warns and
49
+ * allocates `rgba8` instead; `false` throws `UnsupportedError`.
50
+ */
51
+ formatFallback?: boolean;
52
+ filter?: "nearest" | "linear";
53
+ wrap?: "clamp" | "repeat" | "mirror";
54
+ /** Color the storage is cleared to on creation, resize and `clear()`. */
55
+ clearColor?: readonly [number, number, number, number];
56
+ };
57
+ type RenderTarget = {
58
+ readonly texture: WebGLTexture;
59
+ readonly framebuffer: WebGLFramebuffer;
60
+ readonly width: number;
61
+ readonly height: number;
62
+ /** The format actually allocated, after any fallback. */
63
+ readonly format: RenderTargetFormat;
64
+ /** Reallocates (and clears) the storage when the size changes. */
65
+ resize(width: number, height: number): void;
66
+ /** Clears the storage to `clearColor`. Leaves the default framebuffer bound. */
67
+ clear(): void;
68
+ dispose(): void;
69
+ };
70
+ type PingPong = {
71
+ /** The target holding the last completed frame. */
72
+ readonly read: RenderTarget;
73
+ /** The target to draw the next frame into. */
74
+ readonly write: RenderTarget;
75
+ /** The format actually allocated, after any fallback. */
76
+ readonly format: RenderTargetFormat;
77
+ /** Exchanges `read` and `write`; call after drawing into `write`. */
78
+ swap(): void;
79
+ resize(width: number, height: number): void;
80
+ clear(): void;
81
+ dispose(): void;
82
+ };
83
+ /**
84
+ * `"png"` resolves to a `Blob`, `"rgba8"` to a `Uint8Array` and `"rgba16f"` to
85
+ * a `Float32Array`. Raw formats are RGBA, top row first.
86
+ */
87
+ type CaptureFormat = "png" | "rgba8" | "rgba16f";
88
+ type CaptureOptions<F extends CaptureFormat = CaptureFormat> = {
89
+ /** Defaults to `"png"`. */
90
+ format?: F;
91
+ /**
92
+ * Rejects the capture with the signal's reason when aborted before drawing,
93
+ * or between the steps of a capture that draws over several tasks.
94
+ */
95
+ signal?: AbortSignal;
96
+ };
97
+ type CaptureResult<F extends CaptureFormat> = F extends "rgba16f" ? Float32Array : F extends "rgba8" ? Uint8Array : Blob;
18
98
  type HostPointer = {
19
99
  x: number;
20
100
  y: number;
@@ -42,6 +122,11 @@ type SetupCanvasOptions = {
42
122
  layer?: ShaderLayer;
43
123
  canvasClass?: string;
44
124
  canvasStyle?: Partial<CSSStyleDeclaration>;
125
+ /**
126
+ * When neither `target` nor `canvas` is given, create a canvas that is not
127
+ * attached to the document instead of failing.
128
+ */
129
+ detached?: boolean;
45
130
  };
46
131
  type RuntimeHostOptions = {
47
132
  target?: string | Element;
@@ -57,12 +142,32 @@ type RuntimeHostOptions = {
57
142
  pauseWhenHidden?: boolean;
58
143
  respectReducedMotion?: boolean;
59
144
  renderMode?: RenderMode;
145
+ /** Defaults to `"realtime"`. See {@link ClockMode}. */
146
+ clock?: ClockMode;
147
+ /**
148
+ * Fixes the internal render size instead of following the target's size.
149
+ * Required when neither `target` nor `canvas` is given.
150
+ */
151
+ resolution?: Resolution;
60
152
  debug?: boolean;
61
153
  createContext: (canvas: HTMLCanvasElement) => GLContext | null;
62
154
  onInit: (gl: GLContext, width: number, height: number) => Promise<void> | void;
63
155
  onDraw: (state: HostFrameState) => void;
64
156
  /** Called whenever the observed size actually changes (not every frame). */
65
157
  onResize?: (state: HostFrameState) => void;
158
+ /**
159
+ * Returns the render target that holds the last drawn frame at full
160
+ * precision, if any. `captureFrame({ format: "rgba16f" })` reads from it.
161
+ */
162
+ captureSource?: () => RenderTarget | null;
163
+ /**
164
+ * Draws the frame `captureFrame()` reads, in place of `onDraw`, when drawing
165
+ * it takes more than one task (such as accumulating samples while waiting
166
+ * for the GPU). The host holds its render lock until the promise settles and
167
+ * reads the result in the task that settled it, so the final draw into the
168
+ * canvas must happen in that task. Receives the capture's abort signal.
169
+ */
170
+ onCaptureDraw?: (state: HostFrameState, signal: AbortSignal | undefined) => Promise<void>;
66
171
  onContextLost?: () => void;
67
172
  onContextRestored?: (gl: GLContext, width: number, height: number) => Promise<void> | void;
68
173
  onReady?: () => void;
@@ -74,15 +179,43 @@ type RuntimeHostInstance = {
74
179
  readonly status: ShaderStatus;
75
180
  readonly supported: boolean;
76
181
  readonly ready: Promise<void>;
182
+ readonly clock: ClockMode;
77
183
  start(): void;
78
184
  stop(): void;
79
185
  render(): void;
80
186
  resize(): void;
81
187
  destroy(): void;
188
+ /**
189
+ * Sets the clock to `seconds`. In manual mode `u_delta` becomes the
190
+ * difference from the previous `setTime()` value (0 the first time). In
191
+ * realtime mode this seeks the running clock. Does not render by itself.
192
+ */
193
+ setTime(seconds: number): void;
194
+ /** Switches between realtime and manual clocks after creation. */
195
+ setClock(clock: ClockMode): void;
196
+ /**
197
+ * Fixes the internal render size, or follows the target's size again when
198
+ * `null`. Throws `UnsupportedError` when the size exceeds the GPU limits.
199
+ */
200
+ setResolution(resolution: Resolution | null): void;
201
+ /**
202
+ * Draws a frame and reads it back in the same task, so it does not depend on
203
+ * `preserveDrawingBuffer`. Draws even while paused or hidden; waits for
204
+ * `ready` first. `"rgba16f"` needs a float `captureSource`.
205
+ */
206
+ captureFrame<F extends CaptureFormat = "png">(options?: CaptureOptions<F>): Promise<CaptureResult<F>>;
82
207
  };
83
208
 
84
209
  declare const createRuntimeHost: (options: RuntimeHostOptions) => RuntimeHostInstance;
85
210
 
211
+ /**
212
+ * Resolves once the GPU has finished every command submitted so far, polling
213
+ * a fence between tasks. Waiting between heavy draws keeps each submission
214
+ * short, so a long render never trips the browser's GPU watchdog and loses
215
+ * the context. Resolves immediately on WebGL1.
216
+ */
217
+ declare const waitForGpu: (gl: GLContext) => Promise<void>;
218
+
86
219
  declare class ShaderError extends Error {
87
220
  constructor(message: string);
88
221
  }
@@ -105,16 +238,19 @@ type DomSetup = {
105
238
  canvas: HTMLCanvasElement;
106
239
  createdCanvas: boolean;
107
240
  restoredPosition: string | null;
241
+ /** True when the canvas was created without being attached to the document. */
242
+ detached?: boolean;
108
243
  };
109
- declare const resolveElement: (target: string | Element | undefined) => Element | null;
110
- declare const setupCanvas: (options: SetupCanvasOptions) => DomSetup | null;
111
- declare const resolveDpr: (dpr: DprOption | undefined, maxDpr: number | undefined) => number;
112
- declare const resizeCanvasToTarget: (canvas: HTMLCanvasElement, target: Element, dpr: number) => {
244
+ type CanvasSize = {
113
245
  width: number;
114
246
  height: number;
115
247
  viewportWidth: number;
116
248
  viewportHeight: number;
117
249
  };
250
+ declare const resolveElement: (target: string | Element | undefined) => Element | null;
251
+ declare const setupCanvas: (options: SetupCanvasOptions) => DomSetup | null;
252
+ declare const resolveDpr: (dpr: DprOption | undefined, maxDpr: number | undefined) => number;
253
+ declare const resizeCanvasToTarget: (canvas: HTMLCanvasElement, target: Element, dpr: number) => CanvasSize;
118
254
 
119
255
  type LoadedTexture = {
120
256
  name: string;
@@ -126,9 +262,82 @@ type LoadedTexture = {
126
262
  };
127
263
  declare const loadTexture: (gl: GLContext, name: string, input: TextureInput, unit: number) => Promise<LoadedTexture>;
128
264
 
265
+ type TextureSet = {
266
+ /** The textures loaded so far, by name. */
267
+ readonly textures: ReadonlyMap<string, LoadedTexture>;
268
+ /** Whether `name` was given as an input, loaded or not. */
269
+ hasInput(name: string): boolean;
270
+ /**
271
+ * Returns the texture unit for `name`, taking the lowest free unit on first
272
+ * use. Runtimes reserve units for their own samplers (feedback, pass inputs)
273
+ * here too, so they never collide with image textures.
274
+ */
275
+ reserveUnit(gl: GLContext, name: string): number;
276
+ /**
277
+ * Loads every input, then replaces the previously loaded textures. Used for
278
+ * the initial load and after a context restore.
279
+ */
280
+ loadAll(gl: GLContext, isCancelled: () => boolean): Promise<void>;
281
+ /**
282
+ * Loads `input` as `name`. Resolves to the loaded texture, or `null` when a
283
+ * later `set()` for the same name or `isCancelled()` superseded it (its
284
+ * texture is deleted). On failure the unit is released if `name` is unused,
285
+ * and the error is rethrown.
286
+ */
287
+ set(gl: GLContext, name: string, input: TextureInput, isCancelled: () => boolean): Promise<LoadedTexture | null>;
288
+ /**
289
+ * Binds every loaded texture to its unit and points its sampler uniform at
290
+ * it. Calls `onMissing` with the uniform name when the program lacks it.
291
+ */
292
+ bind(gl: GLContext, locations: ReadonlyMap<string, WebGLUniformLocation>, onMissing?: (uniformName: string) => void): void;
293
+ /** Deletes every loaded texture. */
294
+ dispose(gl: GLContext): void;
295
+ };
296
+ /**
297
+ * Tracks named image textures and the texture units they occupy, for a
298
+ * runtime that binds them to one or more programs.
299
+ */
300
+ declare const createTextureSet: (inputs?: TextureMap) => TextureSet;
301
+
302
+ type NormalizedUniform = {
303
+ type: UniformType;
304
+ value: number[] | Float32Array;
305
+ };
306
+ declare const normalizeUniform: (input: UniformInput) => NormalizedUniform;
307
+ declare const applyUniform: (gl: GLContext, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
308
+ declare const applyProgramUniform: (gl: GLContext, program: WebGLProgram, location: WebGLUniformLocation, uniform: NormalizedUniform) => void;
309
+ /**
310
+ * Uploads every cached uniform to the bound program. Calls `onMissing` with
311
+ * the name of each uniform the program lacks or optimized out.
312
+ */
313
+ declare const applyUniforms: (gl: GLContext, locations: ReadonlyMap<string, WebGLUniformLocation>, cache: ReadonlyMap<string, NormalizedUniform>, onMissing?: (name: string) => void) => void;
314
+ declare const collectUniformLocations: (gl: GLContext, program: WebGLProgram) => Map<string, WebGLUniformLocation>;
315
+ declare const createUniformCache: (uniforms: Record<string, UniformInput> | undefined) => Map<string, NormalizedUniform>;
316
+
317
+ type FullscreenProgram = {
318
+ readonly program: WebGLProgram;
319
+ /** Active uniform locations by name, array uniforms without `[0]`. */
320
+ readonly locations: ReadonlyMap<string, WebGLUniformLocation>;
321
+ /**
322
+ * Binds the program, its quad buffer and `a_position`, so a draw is correct
323
+ * whatever GL state user hooks left behind.
324
+ */
325
+ use(): void;
326
+ /** Draws the fullscreen quad with the current GL state. */
327
+ draw(): void;
328
+ dispose(): void;
329
+ };
330
+ /**
331
+ * Compiles `fragment` with a fullscreen-quad vertex shader (the GLSL ES 3.00
332
+ * one when `fragment` starts with `#version 300 es`, unless `vertex` is
333
+ * given) and leaves it bound.
334
+ */
335
+ declare const createFullscreenProgram: (gl: GLContext, fragment: string, vertex?: string) => FullscreenProgram;
336
+
129
337
  declare 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";
130
338
  declare 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";
131
339
  declare const isGLSL300: (src: string) => boolean;
340
+ declare const isWebGL2Context: (gl: GLContext) => gl is WebGL2RenderingContext;
132
341
  declare const createProgram: (gl: GLContext, vertexSource: string, fragmentSource: string) => WebGLProgram;
133
342
  declare const createFullscreenBuffer: (gl: GLContext, program: WebGLProgram) => WebGLBuffer;
134
343
 
@@ -150,4 +359,28 @@ type Blitter = {
150
359
  */
151
360
  declare const createBlitter: (gl: GLContext) => Blitter;
152
361
 
153
- export { type Blitter, DestroyedError, type DomSetup, type DprOption, type GLContext, type HostFrameState, type HostPointer, type LoadedTexture, type RenderMode, type RuntimeHostInstance, type RuntimeHostOptions, type SetupCanvasOptions, ShaderCompileError, ShaderError, type ShaderLayer, type ShaderStatus, TargetNotFoundError, type TextureInput, TextureLoadError, type TextureMap, type TextureOptions, type TextureSource, UnsupportedError, createBlitter, createFullscreenBuffer, createProgram, createRuntimeHost, defaultVertexShader, defaultVertexShader300, fromUniformName, isGLSL300, loadTexture, resizeCanvasToTarget, resolveDpr, resolveElement, setupCanvas, toUniformName };
362
+ /**
363
+ * Whether `format` can be allocated as a color attachment on `gl`. `rgba8` is
364
+ * always available; `rgba16f` and `rgba32f` need WebGL2 and
365
+ * `EXT_color_buffer_float`.
366
+ * Enables the extension as a side effect when present.
367
+ */
368
+ declare const supportsRenderTargetFormat: (gl: GLContext, format: RenderTargetFormat) => boolean;
369
+ /**
370
+ * Resolves the format a render target will actually use. When `format` is not
371
+ * supported this warns and returns `rgba8`, or throws `UnsupportedError` when
372
+ * `formatFallback` is `false`.
373
+ */
374
+ declare const resolveRenderTargetFormat: (gl: GLContext, format?: RenderTargetFormat, formatFallback?: boolean) => RenderTargetFormat;
375
+ /**
376
+ * Creates a texture-backed framebuffer to render into and sample from. The
377
+ * storage is cleared to `clearColor` on creation and on every resize.
378
+ */
379
+ declare const createRenderTarget: (gl: GLContext, width: number, height: number, options?: RenderTargetOptions) => RenderTarget;
380
+ /**
381
+ * Creates two render targets of the same size and format for feedback-style
382
+ * rendering: draw into `write` while sampling `read`, then `swap()`.
383
+ */
384
+ declare const createPingPong: (gl: GLContext, width: number, height: number, options?: RenderTargetOptions) => PingPong;
385
+
386
+ export { type Blitter, type CaptureFormat, type CaptureOptions, type CaptureResult, type ClockMode, DestroyedError, type DomSetup, type DprOption, type ExplicitUniformInput, type FullscreenProgram, type GLContext, type HostFrameState, type HostPointer, type LoadedTexture, type NormalizedUniform, type PingPong, type RenderMode, type RenderTarget, type RenderTargetFormat, type RenderTargetOptions, type Resolution, type RuntimeHostInstance, type RuntimeHostOptions, type SetupCanvasOptions, ShaderCompileError, ShaderError, type ShaderLayer, type ShaderStatus, TargetNotFoundError, type TextureInput, TextureLoadError, type TextureMap, type TextureOptions, type TextureSet, type TextureSource, type UniformInput, type UniformInputMap, type UniformRuntimeValue, type UniformScalar, type UniformType, type UniformVec2, type UniformVec3, type UniformVec4, UnsupportedError, applyProgramUniform, applyUniform, applyUniforms, collectUniformLocations, createBlitter, createFullscreenBuffer, createFullscreenProgram, createPingPong, createProgram, createRenderTarget, createRuntimeHost, createTextureSet, createUniformCache, defaultVertexShader, defaultVertexShader300, fromUniformName, isGLSL300, isWebGL2Context, loadTexture, normalizeUniform, resizeCanvasToTarget, resolveDpr, resolveElement, resolveRenderTargetFormat, setupCanvas, supportsRenderTargetFormat, toUniformName, waitForGpu };