@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 +34 -0
- package/LICENSE +21 -0
- package/README.md +1 -1
- package/dist/index.d.ts +238 -5
- package/dist/index.js +796 -106
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/errors.ts","../src/internal/dom.ts","../src/host.ts","../src/internal/names.ts","../src/internal/textures.ts","../src/internal/webgl.ts","../src/internal/blit.ts"],"sourcesContent":["export class ShaderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class UnsupportedError extends ShaderError {}\nexport class TargetNotFoundError extends ShaderError {}\nexport class ShaderCompileError extends ShaderError {}\nexport class TextureLoadError extends ShaderError {}\nexport class DestroyedError extends ShaderError {}\n","import type { DprOption, SetupCanvasOptions } from \"../types\";\n\nexport type DomSetup = {\n target: Element;\n canvas: HTMLCanvasElement;\n createdCanvas: boolean;\n restoredPosition: string | null;\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) return null;\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): {\n width: number;\n height: number;\n viewportWidth: number;\n viewportHeight: number;\n} => {\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\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 GLContext,\n HostFrameState,\n RuntimeHostInstance,\n RuntimeHostOptions,\n ShaderStatus\n} from \"./types\";\nimport { DestroyedError, TargetNotFoundError, UnsupportedError } from \"./internal/errors\";\nimport {\n resolveDpr,\n resizeCanvasToTarget,\n setupCanvas,\n type DomSetup\n} from \"./internal/dom\";\n\nconst MAX_DELTA_SECONDS = 0.1;\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 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\n constructor(options: RuntimeHostOptions) {\n this.options = options;\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 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.hasVisibilityBlock ||\n this.inRender\n )\n return;\n this.renderInternal(this.elapsed, 0);\n }\n\n resize(): void {\n if (this.destroyed || !this.dom) return;\n\n const prevWidth = this.width;\n const prevHeight = this.height;\n const prevViewportWidth = this.viewportWidth;\n const prevViewportHeight = this.viewportHeight;\n\n this.measureSize();\n\n const sizeChanged =\n this.width !== prevWidth ||\n this.height !== prevHeight ||\n this.viewportWidth !== prevViewportWidth ||\n this.viewportHeight !== prevViewportHeight;\n\n if (sizeChanged && this.context) {\n this.options.onResize?.({\n gl: this.context,\n canvas: this.dom.canvas,\n time: this.elapsed,\n delta: 0,\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.reducedMotionActive,\n pointer: { ...this.pointer }\n });\n }\n\n if (this.options.renderMode === \"demand\" && !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 }\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 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.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 if (!this.dom || !this.context) return;\n const gl = this.context;\n\n this.inRender = true;\n this.measureSize();\n\n const state: HostFrameState = {\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.reducedMotionActive,\n pointer: { ...this.pointer }\n };\n\n this.options.onDraw(state);\n this.frame++;\n this.inRender = false;\n }\n\n private measureSize(): void {\n if (!this.dom) return;\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 private scheduleFrame(): void {\n if (this.rafId || this.options.renderMode === \"demand\") 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 });\n\n if (!this.dom) {\n this.failUnsupported(new TargetNotFoundError(\"Target or canvas not found.\"));\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 this.context = gl;\n this.currentStatus = \"loading\";\n\n try {\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.options.renderMode === \"demand\") {\n this.render();\n }\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private setupDomObservers(): void {\n if (!this.dom) return;\n\n if (this.options.autoResize ?? true) {\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n this.resizeObserver.observe(this.dom.target);\n }\n\n if (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 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;\n const y = pointerEvent.clientY - rect.top;\n this.pointer.x = x * this.pixelRatio;\n this.pointer.y = (rect.height - y) * this.pixelRatio;\n this.pointer.uvX = rect.width > 0 ? x / rect.width : 0;\n this.pointer.uvY = rect.height > 0 ? 1 - y / rect.height : 0;\n this.pointer.active = 1;\n\n if (this.options.renderMode === \"demand\") this.render();\n };\n const onPointerLeave = () => {\n this.pointer.active = 0;\n if (this.options.renderMode === \"demand\") 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.options.renderMode === \"demand\") {\n this.render();\n }\n };\n\n query.addEventListener(\"change\", onChange);\n this.removeListeners.push(() => {\n query.removeEventListener(\"change\", onChange);\n });\n }\n\n private setupContextEvents(): void {\n if (!this.dom) return;\n\n const onLost = (event: Event) => {\n event.preventDefault();\n this.contextRestoredShouldRun = this.running;\n this.cancelFrame();\n this.context = null;\n this.currentStatus = \"context-lost\";\n this.options.onContextLost?.();\n this.options.onError?.(new UnsupportedError(\"WebGL context lost.\"));\n };\n\n const onRestored = () => {\n if (!this.dom || this.destroyed) return;\n const gl = this.options.createContext(this.dom.canvas);\n if (!gl) return;\n this.context = gl;\n\n const afterRestore = async () => {\n try {\n await this.options.onContextRestored?.(gl, this.width, this.height);\n if (this.contextRestoredShouldRun) this.start();\n else 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","export const toUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name : `u_${name}`;\n\nexport const fromUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name.slice(2) : name;\n","import type { GLContext, TextureInput, TextureOptions, TextureSource } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { toUniformName } from \"./names\";\n\nexport type LoadedTexture = {\n name: string;\n uniformName: string;\n sizeUniformName: string;\n texture: WebGLTexture;\n width: number;\n height: number;\n};\n\nexport const loadTexture = async (\n gl: GLContext,\n name: string,\n input: TextureInput,\n unit: number\n): Promise<LoadedTexture> => {\n const options = normalizeTextureInput(input);\n const source = await resolveSource(options.source);\n const texture = gl.createTexture();\n\n if (!texture) {\n throw new TextureLoadError(`Failed to create texture: ${name}`);\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flipY ?? true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n\n const wrap = getWrap(gl, options.wrap ?? \"clamp\");\n const filter = getFilter(gl, options.filter ?? \"linear\");\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n return {\n name,\n uniformName: toUniformName(name),\n sizeUniformName: toUniformName(`${name}Size`),\n texture,\n width: getSourceWidth(source),\n height: getSourceHeight(source)\n };\n};\n\nconst normalizeTextureInput = (input: TextureInput): TextureOptions => {\n if (typeof input === \"string\" || isTextureSource(input)) {\n return { source: input };\n }\n\n return input;\n};\n\nconst resolveSource = async (\n source: TextureSource\n): Promise<HTMLImageElement | HTMLCanvasElement> => {\n if (typeof source !== \"string\") {\n return source;\n }\n\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = source;\n\n try {\n await image.decode();\n } catch {\n throw new TextureLoadError(`Failed to load texture: ${source}`);\n }\n\n return image;\n};\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<TextureOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n\nconst getFilter = (\n gl: GLContext,\n filter: NonNullable<TextureOptions[\"filter\"]>\n): number => (filter === \"nearest\" ? gl.NEAREST : gl.LINEAR);\n\nconst isTextureSource = (\n input: unknown\n): input is HTMLImageElement | HTMLCanvasElement =>\n typeof HTMLImageElement !== \"undefined\" &&\n (input instanceof HTMLImageElement || input instanceof HTMLCanvasElement);\n\nconst getSourceWidth = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalWidth\" in source ? source.naturalWidth : source.width;\n\nconst getSourceHeight = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalHeight\" in source ? source.naturalHeight : source.height;\n","import type { GLContext } from \"../types\";\nimport { ShaderCompileError } from \"./errors\";\n\nexport const defaultVertexShader = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const defaultVertexShader300 = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const isGLSL300 = (src: string): boolean =>\n /^\\s*#version\\s+300\\s+es\\b/.test(src);\n\nexport const createProgram = (\n gl: GLContext,\n vertexSource: string,\n fragmentSource: string\n): WebGLProgram => {\n const vertex = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n const program = gl.createProgram();\n\n if (!program) {\n throw new ShaderCompileError(\"Failed to create WebGL program.\");\n }\n\n gl.attachShader(program, vertex);\n gl.attachShader(program, fragment);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) ?? \"Unknown program link error.\";\n gl.deleteProgram(program);\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n throw new ShaderCompileError(log);\n }\n\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n return program;\n};\n\nexport const createFullscreenBuffer = (\n gl: GLContext,\n program: WebGLProgram\n): WebGLBuffer => {\n const buffer = gl.createBuffer();\n if (!buffer) {\n throw new ShaderCompileError(\"Failed to create fullscreen buffer.\");\n }\n\n const location = gl.getAttribLocation(program, \"a_position\");\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n gl.STATIC_DRAW\n );\n\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n return buffer;\n};\n\nconst compileShader = (\n gl: GLContext,\n type: number,\n source: string\n): WebGLShader => {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new ShaderCompileError(\"Failed to create WebGL shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) ?? \"Unknown shader compile error.\";\n gl.deleteShader(shader);\n throw new ShaderCompileError(log);\n }\n\n return shader;\n};\n","import type { GLContext } from \"../types\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300\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\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.\nconst isWebGL2Context = (gl: GLContext): boolean =>\n typeof (gl as WebGL2RenderingContext).createVertexArray === \"function\";\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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/errors.ts","../src/internal/webgl.ts","../src/internal/capture.ts","../src/internal/dom.ts","../src/host.ts","../src/internal/names.ts","../src/internal/textures.ts","../src/internal/textureSet.ts","../src/internal/uniforms.ts","../src/internal/fullscreenProgram.ts","../src/internal/blit.ts","../src/internal/renderTarget.ts"],"sourcesContent":["export class ShaderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class UnsupportedError extends ShaderError {}\nexport class TargetNotFoundError extends ShaderError {}\nexport class ShaderCompileError extends ShaderError {}\nexport class TextureLoadError extends ShaderError {}\nexport class DestroyedError extends ShaderError {}\n","import type { GLContext } from \"../types\";\nimport { ShaderCompileError } from \"./errors\";\n\nexport const defaultVertexShader = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const defaultVertexShader300 = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nexport const isGLSL300 = (src: string): boolean =>\n /^\\s*#version\\s+300\\s+es\\b/.test(src);\n\n// Duck-typed instead of `instanceof WebGL2RenderingContext` so this also works\n// against test mocks and other environments where the global constructor may\n// be unavailable.\nexport const isWebGL2Context = (gl: GLContext): gl is WebGL2RenderingContext =>\n typeof (gl as WebGL2RenderingContext).createVertexArray === \"function\";\n\nexport const createProgram = (\n gl: GLContext,\n vertexSource: string,\n fragmentSource: string\n): WebGLProgram => {\n const vertex = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragment = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n const program = gl.createProgram();\n\n if (!program) {\n throw new ShaderCompileError(\"Failed to create WebGL program.\");\n }\n\n gl.attachShader(program, vertex);\n gl.attachShader(program, fragment);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(program) ?? \"Unknown program link error.\";\n gl.deleteProgram(program);\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n throw new ShaderCompileError(log);\n }\n\n gl.deleteShader(vertex);\n gl.deleteShader(fragment);\n return program;\n};\n\nexport const createFullscreenBuffer = (\n gl: GLContext,\n program: WebGLProgram\n): WebGLBuffer => {\n const buffer = gl.createBuffer();\n if (!buffer) {\n throw new ShaderCompileError(\"Failed to create fullscreen buffer.\");\n }\n\n const location = gl.getAttribLocation(program, \"a_position\");\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n gl.STATIC_DRAW\n );\n\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n return buffer;\n};\n\nconst compileShader = (\n gl: GLContext,\n type: number,\n source: string\n): WebGLShader => {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new ShaderCompileError(\"Failed to create WebGL shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(shader) ?? \"Unknown shader compile error.\";\n gl.deleteShader(shader);\n throw new ShaderCompileError(log);\n }\n\n return shader;\n};\n","import type { GLContext } from \"../types\";\nimport { isWebGL2Context } from \"./webgl\";\n\n/**\n * Resolves once the GPU has finished every command submitted so far, polling\n * a fence between tasks. Waiting between heavy draws keeps each submission\n * short, so a long render never trips the browser's GPU watchdog and loses\n * the context. Resolves immediately on WebGL1.\n */\nexport const waitForGpu = (gl: GLContext): Promise<void> => {\n if (!isWebGL2Context(gl)) return Promise.resolve();\n const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\n if (!sync) return Promise.resolve();\n gl.flush();\n return new Promise((resolve) => {\n const poll = () => {\n const status = gl.clientWaitSync(sync, 0, 0);\n if (status === gl.TIMEOUT_EXPIRED) {\n setTimeout(poll, 4);\n return;\n }\n gl.deleteSync(sync);\n resolve();\n };\n poll();\n });\n};\n\n/**\n * Reads RGBA pixels from `framebuffer` (or the drawing buffer when `null`) and\n * returns them top row first. Must run in the same task as the draw when\n * reading the drawing buffer, since it is not preserved.\n */\nexport const readPixels = <T extends \"rgba8\" | \"rgba16f\">(\n gl: GLContext,\n framebuffer: WebGLFramebuffer | null,\n width: number,\n height: number,\n format: T\n): T extends \"rgba16f\" ? Float32Array : Uint8Array => {\n const length = width * height * 4;\n const data =\n format === \"rgba16f\" ? new Float32Array(length) : new Uint8Array(length);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n // RGBA/FLOAT is the read combination EXT_color_buffer_float guarantees.\n gl.readPixels(\n 0,\n 0,\n width,\n height,\n gl.RGBA,\n format === \"rgba16f\" ? gl.FLOAT : gl.UNSIGNED_BYTE,\n data\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n flipRows(data, width * 4, height);\n return data as T extends \"rgba16f\" ? Float32Array : Uint8Array;\n};\n\n/** Encodes the canvas as PNG. The snapshot is taken synchronously. */\nexport const canvasToPng = (canvas: HTMLCanvasElement): Promise<Blob> =>\n new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) resolve(blob);\n else reject(new Error(\"Failed to encode the canvas as PNG.\"));\n }, \"image/png\");\n });\n\n// WebGL reads bottom-up; captures are top row first like images.\nconst flipRows = (\n data: Uint8Array | Float32Array,\n rowLength: number,\n rows: number\n): void => {\n const temp = data.slice(0, rowLength);\n for (let top = 0, bottom = rows - 1; top < bottom; top++, bottom--) {\n const topStart = top * rowLength;\n const bottomStart = bottom * rowLength;\n temp.set(data.subarray(topStart, topStart + rowLength));\n data.copyWithin(topStart, bottomStart, bottomStart + rowLength);\n data.set(temp, bottomStart);\n }\n};\n","import type { DprOption, Resolution, SetupCanvasOptions } from \"../types\";\n\nexport type DomSetup = {\n target: Element;\n canvas: HTMLCanvasElement;\n createdCanvas: boolean;\n restoredPosition: string | null;\n /** True when the canvas was created without being attached to the document. */\n detached?: boolean;\n};\n\nexport type CanvasSize = {\n width: number;\n height: number;\n viewportWidth: number;\n viewportHeight: number;\n};\n\nexport const resolveElement = (\n target: string | Element | undefined\n): Element | null => {\n if (!target) return null;\n if (typeof target === \"string\") return document.querySelector(target);\n return target;\n};\n\nexport const setupCanvas = (options: SetupCanvasOptions): DomSetup | null => {\n const target = resolveElement(options.target);\n const canvas = options.canvas ?? document.createElement(\"canvas\");\n const measurementTarget = target ?? options.canvas;\n\n if (!measurementTarget) {\n if (!options.detached) return null;\n canvas.dataset.frapxCanvas = \"\";\n return {\n target: canvas,\n canvas,\n createdCanvas: true,\n restoredPosition: null,\n detached: true\n };\n }\n\n const createdCanvas = !options.canvas;\n const restoredPosition =\n target && getComputedStyle(target).position === \"static\"\n ? (target as HTMLElement).style.position\n : null;\n\n if (target && restoredPosition !== null) {\n (target as HTMLElement).style.position = \"relative\";\n }\n\n applyCanvasStyle(canvas, options, createdCanvas);\n\n if (options.canvasClass) {\n canvas.classList.add(options.canvasClass);\n }\n\n if (options.canvasStyle) {\n Object.assign(canvas.style, options.canvasStyle);\n }\n\n if (createdCanvas && target) {\n if ((options.layer ?? \"background\") === \"overlay\") {\n target.append(canvas);\n } else {\n target.prepend(canvas);\n }\n }\n\n return {\n target: measurementTarget,\n canvas,\n createdCanvas,\n restoredPosition\n };\n};\n\nexport const resolveDpr = (\n dpr: DprOption | undefined,\n maxDpr: number | undefined\n): number => {\n const raw =\n typeof dpr === \"function\"\n ? dpr()\n : typeof dpr === \"number\"\n ? dpr\n : typeof window === \"undefined\"\n ? 1\n : window.devicePixelRatio || 1;\n\n return Math.max(1, Math.min(raw, maxDpr ?? 2));\n};\n\nexport const resizeCanvasToTarget = (\n canvas: HTMLCanvasElement,\n target: Element,\n dpr: number\n): CanvasSize => {\n const rect = target.getBoundingClientRect();\n const viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n const viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n const width = Math.max(1, Math.round(viewportWidth * dpr));\n const height = Math.max(1, Math.round(viewportHeight * dpr));\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\n/**\n * Sizes the canvas to a fixed internal resolution. The viewport size still\n * comes from the target so `u_viewportSize` reflects the displayed size; a\n * detached canvas has no layout, so its viewport equals the resolution.\n */\nexport const resizeCanvasToResolution = (\n canvas: HTMLCanvasElement,\n target: Element | null,\n resolution: Resolution\n): CanvasSize => {\n const [width, height] = resolution;\n let viewportWidth = width;\n let viewportHeight = height;\n\n if (target) {\n const rect = target.getBoundingClientRect();\n viewportWidth = Math.max(1, rect.width || canvas.clientWidth || 1);\n viewportHeight = Math.max(1, rect.height || canvas.clientHeight || 1);\n }\n\n if (canvas.width !== width) canvas.width = width;\n if (canvas.height !== height) canvas.height = height;\n\n return { width, height, viewportWidth, viewportHeight };\n};\n\nconst applyCanvasStyle = (\n canvas: HTMLCanvasElement,\n options: SetupCanvasOptions,\n shouldPosition: boolean\n): void => {\n canvas.dataset.frapxCanvas = \"\";\n\n if (!shouldPosition) return;\n\n const layer = options.layer ?? \"background\";\n Object.assign(canvas.style, {\n position: \"absolute\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n pointerEvents: \"none\",\n zIndex: layer === \"overlay\" ? \"1\" : \"0\"\n });\n};\n","import type {\n CaptureFormat,\n CaptureOptions,\n CaptureResult,\n ClockMode,\n GLContext,\n HostFrameState,\n HostPointer,\n Resolution,\n RuntimeHostInstance,\n RuntimeHostOptions,\n ShaderStatus\n} from \"./types\";\nimport { DestroyedError, TargetNotFoundError, UnsupportedError } from \"./internal/errors\";\nimport { canvasToPng, readPixels } from \"./internal/capture\";\nimport {\n resolveDpr,\n resizeCanvasToResolution,\n resizeCanvasToTarget,\n setupCanvas,\n type DomSetup\n} from \"./internal/dom\";\n\nconst MAX_DELTA_SECONDS = 0.1;\n\n// Manual clocks report a neutral pointer so output never depends on input.\nconst IDLE_POINTER: HostPointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n\ntype Gate = \"offscreen\" | \"hidden\" | \"reducedMotion\";\n\nexport const createRuntimeHost = (\n options: RuntimeHostOptions\n): RuntimeHostInstance => {\n return new RuntimeHost(options);\n};\n\nclass RuntimeHost implements RuntimeHostInstance {\n readonly ready: Promise<void>;\n\n private readonly options: RuntimeHostOptions;\n private readyResolve: (() => void) | null = null;\n private readyReject: ((error: Error) => void) | null = null;\n private dom: DomSetup | null = null;\n private context: GLContext | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n private rafId = 0;\n private running = false;\n private inRender = false;\n private captureDrawing = false;\n private resizePending = false;\n private destroyed = false;\n private gates = new Set<Gate>();\n private reducedMotionActive = false;\n private frame = 0;\n private elapsed = 0;\n private lastTimestamp = 0;\n private pixelRatio = 1;\n private width = 1;\n private height = 1;\n private viewportWidth = 1;\n private viewportHeight = 1;\n private pointer = { x: 0, y: 0, uvX: 0, uvY: 0, active: 0 };\n private removeListeners: Array<() => void> = [];\n private currentStatus: ShaderStatus = \"idle\";\n private contextRestoredShouldRun = false;\n private clockMode: ClockMode;\n private manualDelta = 0;\n private lastManualTime: number | null = null;\n private fixedResolution: Resolution | null;\n private objectFitRestore: string | null = null;\n // Letterbox offset (CSS px) of the contained canvas content inside the target.\n private contentOffsetX = 0;\n private contentOffsetY = 0;\n\n constructor(options: RuntimeHostOptions) {\n this.options = options;\n this.clockMode = options.clock ?? \"realtime\";\n this.fixedResolution = options.resolution\n ? normalizeResolution(options.resolution)\n : null;\n this.ready = new Promise<void>((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n queueMicrotask(() => {\n void this.init();\n });\n }\n\n get canvas(): HTMLCanvasElement | null {\n return this.dom?.canvas ?? null;\n }\n\n get gl(): GLContext | null {\n return this.context;\n }\n\n get status(): ShaderStatus {\n return this.currentStatus;\n }\n\n get supported(): boolean {\n return ![\"unsupported\", \"destroyed\"].includes(this.currentStatus);\n }\n\n get clock(): ClockMode {\n return this.clockMode;\n }\n\n start(): void {\n if (this.destroyed || this.currentStatus === \"unsupported\") return;\n this.running = true;\n this.reconcile();\n }\n\n stop(): void {\n this.running = false;\n this.cancelFrame();\n if (!this.destroyed && this.currentStatus !== \"unsupported\") {\n this.currentStatus = \"paused\";\n }\n }\n\n render(): void {\n if (\n this.destroyed ||\n !this.dom ||\n !this.context ||\n this.currentStatus === \"unsupported\" ||\n this.inRender\n )\n return;\n\n if (this.isManual) {\n // The caller decides when to draw; visibility gates do not apply.\n this.renderInternal(this.elapsed, this.manualDelta);\n return;\n }\n\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n setTime(seconds: number): void {\n if (!Number.isFinite(seconds)) {\n throw new RangeError(`setTime() expects a finite number, got ${seconds}`);\n }\n if (this.destroyed) return;\n\n if (this.isManual) {\n this.manualDelta =\n this.lastManualTime === null ? 0 : seconds - this.lastManualTime;\n this.lastManualTime = seconds;\n }\n this.elapsed = seconds;\n }\n\n setClock(clock: ClockMode): void {\n if (this.destroyed || clock === this.clockMode) return;\n this.clockMode = clock;\n this.manualDelta = 0;\n this.lastManualTime = null;\n // Gates kept tracking while manual, so this resumes against current state.\n this.reconcile();\n }\n\n setResolution(resolution: Resolution | null): void {\n if (this.destroyed) return;\n\n if (resolution === null) {\n if (this.isDetached) {\n throw new TypeError(\n \"A canvas without a target needs a fixed resolution.\"\n );\n }\n this.fixedResolution = null;\n } else {\n const next = normalizeResolution(resolution);\n if (this.context) assertWithinLimits(this.context, next);\n this.fixedResolution = next;\n }\n\n this.applyObjectFit();\n this.resize();\n }\n\n async captureFrame<F extends CaptureFormat = \"png\">(\n options: CaptureOptions<F> = {}\n ): Promise<CaptureResult<F>> {\n const format: CaptureFormat = options.format ?? \"png\";\n if (format !== \"png\" && format !== \"rgba8\" && format !== \"rgba16f\") {\n throw new RangeError(`Unknown capture format: ${String(format)}`);\n }\n\n await this.ready;\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n if (!this.dom || !this.context) {\n throw new UnsupportedError(\"Cannot capture without a WebGL context.\");\n }\n if (this.inRender) {\n throw new Error(\"captureFrame() cannot be called while a frame is drawing.\");\n }\n\n // Check before drawing so a rejected capture has no side effects.\n const sourceFormat = this.options.captureSource?.()?.format;\n if (format === \"rgba16f\" && sourceFormat !== \"rgba16f\" && sourceFormat !== \"rgba32f\") {\n throw new UnsupportedError(\n \"rgba16f capture needs a float render target, such as feedback with format rgba16f.\"\n );\n }\n options.signal?.throwIfAborted();\n\n const delta = this.isManual ? this.manualDelta : 0;\n const drawContext = this.context;\n if (!this.options.onCaptureDraw) {\n this.renderInternal(this.elapsed, delta);\n return this.readCapture(format, drawContext);\n }\n\n try {\n await this.renderForCapture(this.options.onCaptureDraw, delta, options.signal);\n return this.readCapture(format, drawContext);\n } finally {\n // Resizes requested while drawing apply once the frame is read.\n if (this.resizePending) {\n this.resizePending = false;\n this.resize();\n }\n }\n }\n\n resize(): void {\n if (this.destroyed || !this.dom) return;\n // Keep the size an asynchronous capture draw started with until it is read.\n if (this.captureDrawing) {\n this.resizePending = true;\n return;\n }\n\n const prevWidth = this.width;\n const prevHeight = this.height;\n const prevViewportWidth = this.viewportWidth;\n const prevViewportHeight = this.viewportHeight;\n\n this.measureSize();\n\n const sizeChanged =\n this.width !== prevWidth ||\n this.height !== prevHeight ||\n this.viewportWidth !== prevViewportWidth ||\n this.viewportHeight !== prevViewportHeight;\n\n if (sizeChanged && this.context) {\n this.options.onResize?.(this.createFrameState(this.elapsed, 0));\n }\n\n if (this.shouldRenderOnDemand && !this.inRender) {\n this.render();\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.running = false;\n this.cancelFrame();\n this.resizeObserver?.disconnect();\n this.intersectionObserver?.disconnect();\n\n for (const remove of this.removeListeners) remove();\n this.removeListeners = [];\n\n this.context = null;\n\n if (this.dom?.createdCanvas) {\n this.dom.canvas.remove();\n } else if (this.dom && this.objectFitRestore !== null) {\n this.dom.canvas.style.objectFit = this.objectFitRestore;\n }\n\n const dom = this.dom;\n if (dom?.restoredPosition !== null && dom && this.options.target) {\n (dom.target as HTMLElement).style.position = dom.restoredPosition!;\n }\n\n this.currentStatus = \"destroyed\";\n this.readyReject?.(new DestroyedError(\"Runtime host was destroyed.\"));\n }\n\n private get isManual(): boolean {\n return this.clockMode === \"manual\";\n }\n\n private get isDetached(): boolean {\n if (this.dom) return this.dom.detached === true;\n return this.options.target === undefined && this.options.canvas === undefined;\n }\n\n // Demand mode re-renders on input changes, except under a manual clock where\n // only explicit render() calls draw.\n private get shouldRenderOnDemand(): boolean {\n return this.options.renderMode === \"demand\" && !this.isManual;\n }\n\n private get hasVisibilityBlock(): boolean {\n return this.gates.has(\"offscreen\") || this.gates.has(\"hidden\");\n }\n\n private get hasMotionBlock(): boolean {\n return (\n this.gates.has(\"reducedMotion\") && this.options.renderMode !== \"demand\"\n );\n }\n\n private setGate(gate: Gate, closed: boolean): void {\n if (closed === this.gates.has(gate)) return;\n if (closed) this.gates.add(gate);\n else this.gates.delete(gate);\n this.reconcile();\n }\n\n private reconcile(): void {\n if (\n this.destroyed ||\n this.currentStatus === \"unsupported\" ||\n this.currentStatus === \"error\" ||\n this.currentStatus === \"context-lost\"\n ) {\n return;\n }\n\n if (this.isManual) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.running) {\n if (this.hasVisibilityBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n return;\n }\n\n if (this.hasMotionBlock) {\n this.cancelFrame();\n this.currentStatus = \"paused\";\n this.renderStaticFrame();\n return;\n }\n\n this.currentStatus = \"running\";\n if (this.options.renderMode === \"demand\") this.render();\n else this.scheduleFrame();\n return;\n }\n\n if (this.options.renderMode === \"demand\") this.render();\n }\n\n private renderStaticFrame(): void {\n if (this.hasVisibilityBlock) return;\n this.renderInternal(this.elapsed, 0);\n }\n\n private renderInternal(time: number, delta: number): void {\n // An asynchronous capture draw holds the lock across tasks.\n if (!this.dom || !this.context || this.inRender) return;\n const gl = this.context;\n\n this.inRender = true;\n try {\n this.measureSize();\n this.options.onDraw(this.createFrameState(time, delta, gl));\n this.frame++;\n } finally {\n this.inRender = false;\n }\n }\n\n // Holds the render lock across an asynchronous capture draw so no other\n // frame interleaves with it.\n private async renderForCapture(\n draw: NonNullable<RuntimeHostOptions[\"onCaptureDraw\"]>,\n delta: number,\n signal: AbortSignal | undefined\n ): Promise<void> {\n if (!this.dom || !this.context) return;\n this.inRender = true;\n this.captureDrawing = true;\n try {\n this.measureSize();\n await draw(this.createFrameState(this.elapsed, delta, this.context), signal);\n this.frame++;\n } finally {\n this.inRender = false;\n this.captureDrawing = false;\n }\n }\n\n // Reads the frame just drawn, in the task that drew it: the drawing buffer\n // is not preserved. Fails if the context drawn into is gone, including when\n // it was lost and restored while an asynchronous draw was pending.\n private readCapture<F extends CaptureFormat>(\n format: CaptureFormat,\n drawContext: GLContext | null\n ): Promise<CaptureResult<F>> | CaptureResult<F> {\n if (this.destroyed) {\n throw new DestroyedError(\"Runtime host was destroyed.\");\n }\n const gl = this.context;\n if (!gl || gl !== drawContext || !this.dom) {\n throw new UnsupportedError(\"The WebGL context was lost while capturing.\");\n }\n\n if (format === \"png\") {\n return canvasToPng(this.dom.canvas) as Promise<CaptureResult<F>>;\n }\n if (format === \"rgba8\") {\n return readPixels(gl, null, this.width, this.height, \"rgba8\") as CaptureResult<F>;\n }\n const source = this.options.captureSource!()!;\n return readPixels(\n gl,\n source.framebuffer,\n source.width,\n source.height,\n \"rgba16f\"\n ) as CaptureResult<F>;\n }\n\n private createFrameState(\n time: number,\n delta: number,\n gl: GLContext = this.context!\n ): HostFrameState {\n return {\n gl,\n canvas: this.dom!.canvas,\n time,\n delta,\n frame: this.frame,\n width: this.width,\n height: this.height,\n viewportWidth: this.viewportWidth,\n viewportHeight: this.viewportHeight,\n pixelRatio: this.pixelRatio,\n reducedMotion: this.isManual ? false : this.reducedMotionActive,\n pointer: this.isManual ? { ...IDLE_POINTER } : { ...this.pointer }\n };\n }\n\n private measureSize(): void {\n if (!this.dom) return;\n\n if (this.fixedResolution) {\n const size = resizeCanvasToResolution(\n this.dom.canvas,\n this.dom.detached ? null : this.dom.target,\n this.fixedResolution\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n // Internal pixels per displayed CSS pixel under object-fit: contain.\n this.pixelRatio = Math.max(\n size.width / size.viewportWidth,\n size.height / size.viewportHeight\n );\n this.contentOffsetX =\n (size.viewportWidth - size.width / this.pixelRatio) / 2;\n this.contentOffsetY =\n (size.viewportHeight - size.height / this.pixelRatio) / 2;\n return;\n }\n\n this.contentOffsetX = 0;\n this.contentOffsetY = 0;\n this.pixelRatio = resolveDpr(this.options.dpr, this.options.maxDpr);\n const size = resizeCanvasToTarget(\n this.dom.canvas,\n this.dom.target,\n this.pixelRatio\n );\n this.width = size.width;\n this.height = size.height;\n this.viewportWidth = size.viewportWidth;\n this.viewportHeight = size.viewportHeight;\n }\n\n // Letterbox the fixed-resolution canvas instead of stretching it.\n private applyObjectFit(): void {\n if (!this.dom) return;\n const style = this.dom.canvas.style;\n if (this.fixedResolution && this.objectFitRestore === null) {\n this.objectFitRestore = style.objectFit ?? \"\";\n style.objectFit = \"contain\";\n } else if (!this.fixedResolution && this.objectFitRestore !== null) {\n style.objectFit = this.objectFitRestore;\n this.objectFitRestore = null;\n }\n }\n\n private scheduleFrame(): void {\n if (this.rafId || this.options.renderMode === \"demand\" || this.isManual)\n return;\n\n this.rafId = requestAnimationFrame((timestamp) => {\n this.rafId = 0;\n if (!this.running || this.destroyed) return;\n\n const seconds = timestamp / 1000;\n const rawDelta = this.lastTimestamp ? seconds - this.lastTimestamp : 0;\n const delta = Math.min(Math.max(rawDelta, 0), MAX_DELTA_SECONDS);\n this.lastTimestamp = seconds;\n this.elapsed += delta;\n this.renderInternal(this.elapsed, delta);\n this.scheduleFrame();\n });\n }\n\n private cancelFrame(): void {\n if (this.rafId) {\n cancelAnimationFrame(this.rafId);\n this.rafId = 0;\n }\n this.lastTimestamp = 0;\n }\n\n private async init(): Promise<void> {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n this.failUnsupported(new UnsupportedError(\"WebGL requires a browser.\"));\n return;\n }\n\n this.dom = setupCanvas({\n ...(this.options.target !== undefined && { target: this.options.target }),\n ...(this.options.canvas !== undefined && { canvas: this.options.canvas }),\n ...(this.options.layer !== undefined && { layer: this.options.layer }),\n ...(this.options.canvasClass !== undefined && { canvasClass: this.options.canvasClass }),\n ...(this.options.canvasStyle !== undefined && { canvasStyle: this.options.canvasStyle }),\n // Only a missing target/canvas may fall back to a detached canvas; a\n // target that fails to resolve must still report TargetNotFoundError.\n detached:\n this.fixedResolution !== null &&\n this.options.target === undefined &&\n this.options.canvas === undefined\n });\n\n if (!this.dom) {\n this.failUnsupported(\n new TargetNotFoundError(\n \"Target or canvas not found. Pass `resolution` to render without a target.\"\n )\n );\n return;\n }\n\n let gl: GLContext | null;\n try {\n gl = this.options.createContext(this.dom.canvas);\n } catch (error) {\n this.failUnsupported(\n error instanceof UnsupportedError\n ? error\n : new UnsupportedError(String(error))\n );\n return;\n }\n if (!gl) {\n this.failUnsupported(new UnsupportedError(\"WebGL is not supported.\"));\n return;\n }\n\n if (this.fixedResolution) {\n try {\n assertWithinLimits(gl, this.fixedResolution);\n } catch (error) {\n this.failUnsupported(\n error instanceof Error ? error : new UnsupportedError(String(error))\n );\n return;\n }\n if (this.options.dpr !== undefined || this.options.maxDpr !== undefined) {\n this.debugWarn(\"`dpr` and `maxDpr` are ignored while `resolution` is set.\");\n }\n }\n\n this.context = gl;\n this.currentStatus = \"loading\";\n\n try {\n this.applyObjectFit();\n this.setupDomObservers();\n this.setupContextEvents();\n this.measureSize();\n await this.options.onInit(gl, this.width, this.height);\n if (this.destroyed) return;\n this.currentStatus = \"ready\";\n this.readyResolve?.();\n this.options.onReady?.();\n\n if (this.running || (this.options.autoStart ?? true)) {\n this.start();\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n } catch (error) {\n if (error instanceof UnsupportedError) this.failUnsupported(error);\n else this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private setupDomObservers(): void {\n if (!this.dom) return;\n const detached = this.dom.detached === true;\n\n // A detached canvas has no layout: it can never be measured, scrolled into\n // view or pointed at, so only document-level observers apply.\n if (!detached && (this.options.autoResize ?? true)) {\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n this.resizeObserver.observe(this.dom.target);\n }\n\n if (!detached && (this.options.pauseWhenOffscreen ?? true)) {\n this.intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[0];\n this.setGate(\"offscreen\", !entry?.isIntersecting);\n });\n this.intersectionObserver.observe(this.dom.target);\n }\n\n if (this.options.pauseWhenHidden ?? true) {\n if (document.hidden) this.gates.add(\"hidden\");\n const onVisibility = () => {\n this.setGate(\"hidden\", document.hidden);\n };\n document.addEventListener(\"visibilitychange\", onVisibility);\n this.removeListeners.push(() => {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n });\n }\n\n this.setupMotionObserver();\n\n if (detached) return;\n\n const onPointerMove = (event: Event) => {\n if (!this.dom) return;\n const pointerEvent = event as PointerEvent;\n const rect = this.dom.target.getBoundingClientRect();\n const x = pointerEvent.clientX - rect.left - this.contentOffsetX;\n const y = pointerEvent.clientY - rect.top - this.contentOffsetY;\n // Displayed content size in CSS px (smaller than rect when letterboxed).\n const contentWidth = this.fixedResolution\n ? this.width / this.pixelRatio\n : rect.width;\n const contentHeight = this.fixedResolution\n ? this.height / this.pixelRatio\n : rect.height;\n this.pointer.x = x * this.pixelRatio;\n this.pointer.y = (contentHeight - y) * this.pixelRatio;\n this.pointer.uvX = contentWidth > 0 ? x / contentWidth : 0;\n this.pointer.uvY = contentHeight > 0 ? 1 - y / contentHeight : 0;\n this.pointer.active = 1;\n\n if (this.shouldRenderOnDemand) this.render();\n };\n const onPointerLeave = () => {\n this.pointer.active = 0;\n if (this.shouldRenderOnDemand) this.render();\n };\n\n this.dom.target.addEventListener(\"pointermove\", onPointerMove);\n this.dom.target.addEventListener(\"pointerenter\", onPointerMove);\n this.dom.target.addEventListener(\"pointerleave\", onPointerLeave);\n this.removeListeners.push(() => {\n this.dom?.target.removeEventListener(\"pointermove\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerenter\", onPointerMove);\n this.dom?.target.removeEventListener(\"pointerleave\", onPointerLeave);\n });\n }\n\n private setupMotionObserver(): void {\n if (typeof window.matchMedia !== \"function\") return;\n\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n this.reducedMotionActive = query.matches;\n if (this.options.respectReducedMotion && query.matches) {\n this.gates.add(\"reducedMotion\");\n }\n\n const onChange = (event: MediaQueryListEvent) => {\n this.reducedMotionActive = event.matches;\n if (this.options.respectReducedMotion) {\n this.setGate(\"reducedMotion\", event.matches);\n } else if (this.shouldRenderOnDemand) {\n this.render();\n }\n };\n\n query.addEventListener(\"change\", onChange);\n this.removeListeners.push(() => {\n query.removeEventListener(\"change\", onChange);\n });\n }\n\n private setupContextEvents(): void {\n if (!this.dom) return;\n\n const onLost = (event: Event) => {\n event.preventDefault();\n this.contextRestoredShouldRun = this.running;\n this.cancelFrame();\n this.context = null;\n this.currentStatus = \"context-lost\";\n this.options.onContextLost?.();\n this.options.onError?.(new UnsupportedError(\"WebGL context lost.\"));\n };\n\n const onRestored = () => {\n if (!this.dom || this.destroyed) return;\n const gl = this.options.createContext(this.dom.canvas);\n if (!gl) return;\n this.context = gl;\n\n const afterRestore = async () => {\n try {\n await this.options.onContextRestored?.(gl, this.width, this.height);\n if (this.contextRestoredShouldRun) this.start();\n else if (!this.isManual) this.render();\n } catch (error) {\n this.fail(error instanceof Error ? error : new Error(String(error)));\n }\n };\n void afterRestore();\n };\n\n this.dom.canvas.addEventListener(\"webglcontextlost\", onLost);\n this.dom.canvas.addEventListener(\"webglcontextrestored\", onRestored);\n this.removeListeners.push(() => {\n this.dom?.canvas.removeEventListener(\"webglcontextlost\", onLost);\n this.dom?.canvas.removeEventListener(\"webglcontextrestored\", onRestored);\n });\n }\n\n private failUnsupported(error: Error): void {\n this.currentStatus = \"unsupported\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private fail(error: Error): void {\n this.currentStatus = \"error\";\n this.debugWarn(error.message);\n this.options.onError?.(error);\n this.readyReject?.(error);\n }\n\n private debugWarn(message: string): void {\n if (this.options.debug) {\n console.warn(`[frapx/runtime] ${message}`);\n }\n }\n}\n\nconst normalizeResolution = (resolution: Resolution): Resolution => {\n const [width, height] = resolution;\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width < 1 ||\n height < 1\n ) {\n throw new RangeError(`Invalid resolution: ${width}x${height}`);\n }\n return [Math.round(width), Math.round(height)];\n};\n\nconst assertWithinLimits = (gl: GLContext, resolution: Resolution): void => {\n const [width, height] = resolution;\n const viewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS) as\n | ArrayLike<number>\n | null;\n const renderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) as\n | number\n | null;\n const limit = (axis: 0 | 1): number =>\n Math.min(\n viewportDims?.[axis] ?? Number.POSITIVE_INFINITY,\n typeof renderbufferSize === \"number\"\n ? renderbufferSize\n : Number.POSITIVE_INFINITY\n );\n\n if (width > limit(0) || height > limit(1)) {\n throw new UnsupportedError(\n `Resolution ${width}x${height} exceeds this GPU's limit of ${limit(0)}x${limit(1)}.`\n );\n }\n};\n","export const toUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name : `u_${name}`;\n\nexport const fromUniformName = (name: string): string =>\n name.startsWith(\"u_\") ? name.slice(2) : name;\n","import type { GLContext, TextureInput, TextureOptions, TextureSource } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { toUniformName } from \"./names\";\n\nexport type LoadedTexture = {\n name: string;\n uniformName: string;\n sizeUniformName: string;\n texture: WebGLTexture;\n width: number;\n height: number;\n};\n\nexport const loadTexture = async (\n gl: GLContext,\n name: string,\n input: TextureInput,\n unit: number\n): Promise<LoadedTexture> => {\n const options = normalizeTextureInput(input);\n const source = await resolveSource(options.source);\n const texture = gl.createTexture();\n\n if (!texture) {\n throw new TextureLoadError(`Failed to create texture: ${name}`);\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.flipY ?? true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n\n const wrap = getWrap(gl, options.wrap ?? \"clamp\");\n const filter = getFilter(gl, options.filter ?? \"linear\");\n\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n return {\n name,\n uniformName: toUniformName(name),\n sizeUniformName: toUniformName(`${name}Size`),\n texture,\n width: getSourceWidth(source),\n height: getSourceHeight(source)\n };\n};\n\nconst normalizeTextureInput = (input: TextureInput): TextureOptions => {\n if (typeof input === \"string\" || isTextureSource(input)) {\n return { source: input };\n }\n\n return input;\n};\n\nconst resolveSource = async (\n source: TextureSource\n): Promise<HTMLImageElement | HTMLCanvasElement> => {\n if (typeof source !== \"string\") {\n return source;\n }\n\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.src = source;\n\n try {\n await image.decode();\n } catch {\n throw new TextureLoadError(`Failed to load texture: ${source}`);\n }\n\n return image;\n};\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<TextureOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n\nconst getFilter = (\n gl: GLContext,\n filter: NonNullable<TextureOptions[\"filter\"]>\n): number => (filter === \"nearest\" ? gl.NEAREST : gl.LINEAR);\n\nconst isTextureSource = (\n input: unknown\n): input is HTMLImageElement | HTMLCanvasElement =>\n typeof HTMLImageElement !== \"undefined\" &&\n (input instanceof HTMLImageElement || input instanceof HTMLCanvasElement);\n\nconst getSourceWidth = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalWidth\" in source ? source.naturalWidth : source.width;\n\nconst getSourceHeight = (\n source: HTMLImageElement | HTMLCanvasElement\n): number =>\n \"naturalHeight\" in source ? source.naturalHeight : source.height;\n","import type { GLContext, TextureInput, TextureMap } from \"../types\";\nimport { TextureLoadError } from \"./errors\";\nimport { loadTexture, type LoadedTexture } from \"./textures\";\n\nexport type TextureSet = {\n /** The textures loaded so far, by name. */\n readonly textures: ReadonlyMap<string, LoadedTexture>;\n /** Whether `name` was given as an input, loaded or not. */\n hasInput(name: string): boolean;\n /**\n * Returns the texture unit for `name`, taking the lowest free unit on first\n * use. Runtimes reserve units for their own samplers (feedback, pass inputs)\n * here too, so they never collide with image textures.\n */\n reserveUnit(gl: GLContext, name: string): number;\n /**\n * Loads every input, then replaces the previously loaded textures. Used for\n * the initial load and after a context restore.\n */\n loadAll(gl: GLContext, isCancelled: () => boolean): Promise<void>;\n /**\n * Loads `input` as `name`. Resolves to the loaded texture, or `null` when a\n * later `set()` for the same name or `isCancelled()` superseded it (its\n * texture is deleted). On failure the unit is released if `name` is unused,\n * and the error is rethrown.\n */\n set(\n gl: GLContext,\n name: string,\n input: TextureInput,\n isCancelled: () => boolean\n ): Promise<LoadedTexture | null>;\n /**\n * Binds every loaded texture to its unit and points its sampler uniform at\n * it. Calls `onMissing` with the uniform name when the program lacks it.\n */\n bind(\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n onMissing?: (uniformName: string) => void\n ): void;\n /** Deletes every loaded texture. */\n dispose(gl: GLContext): void;\n};\n\n/**\n * Tracks named image textures and the texture units they occupy, for a\n * runtime that binds them to one or more programs.\n */\nexport const createTextureSet = (inputs: TextureMap = {}): TextureSet => {\n const textureInputs = new Map<string, TextureInput>(Object.entries(inputs));\n let textures = new Map<string, LoadedTexture>();\n const units = new Map<string, number>();\n const versions = new Map<string, number>();\n\n const reserveUnit = (gl: GLContext, name: string): number => {\n const existing = units.get(name);\n if (existing !== undefined) return existing;\n\n const maxUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number;\n const used = new Set(units.values());\n for (let unit = 0; unit < maxUnits; unit += 1) {\n if (!used.has(unit)) {\n units.set(name, unit);\n return unit;\n }\n }\n\n throw new TextureLoadError(\n `Texture unit limit exceeded while loading texture: ${name}`\n );\n };\n\n return {\n get textures() {\n return textures;\n },\n\n hasInput(name) {\n return textureInputs.has(name);\n },\n\n reserveUnit,\n\n async loadAll(gl, isCancelled) {\n const loaded = new Map<string, LoadedTexture>();\n for (const [name, input] of textureInputs) {\n if (isCancelled()) break;\n const unit = reserveUnit(gl, name);\n loaded.set(name, await loadTexture(gl, name, input, unit));\n }\n\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n textures = loaded;\n },\n\n async set(gl, name, input, isCancelled) {\n const version = (versions.get(name) ?? 0) + 1;\n versions.set(name, version);\n\n try {\n const unit = reserveUnit(gl, name);\n const loaded = await loadTexture(gl, name, input, unit);\n\n if (isCancelled() || versions.get(name) !== version) {\n gl.deleteTexture(loaded.texture);\n return null;\n }\n\n const previous = textures.get(name);\n textureInputs.set(name, input);\n textures.set(name, loaded);\n if (previous) gl.deleteTexture(previous.texture);\n return loaded;\n } catch (error) {\n if (!textures.has(name) && !textureInputs.has(name)) {\n units.delete(name);\n }\n throw error;\n }\n },\n\n bind(gl, locations, onMissing) {\n for (const texture of textures.values()) {\n const unit = units.get(texture.name);\n if (unit === undefined) continue;\n const location = locations.get(texture.uniformName);\n if (!location) {\n onMissing?.(texture.uniformName);\n continue;\n }\n\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n gl.uniform1i(location, unit);\n }\n },\n\n dispose(gl) {\n for (const texture of textures.values()) {\n gl.deleteTexture(texture.texture);\n }\n }\n };\n};\n","import type { ExplicitUniformInput, GLContext, UniformInput, UniformType } from \"../types\";\nimport { toUniformName } from \"./names\";\n\nexport type NormalizedUniform = {\n type: UniformType;\n value: number[] | Float32Array;\n};\n\nexport const normalizeUniform = (input: UniformInput): NormalizedUniform => {\n if (typeof input === \"number\") {\n return { type: \"float\", value: [input] };\n }\n\n if (input instanceof Float32Array) {\n if (input.length === 9) return { type: \"mat3\", value: input };\n if (input.length === 16) return { type: \"mat4\", value: input };\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n if (isExplicitUniform(input)) {\n return { type: input.type, value: input.value };\n }\n\n if (Array.isArray(input)) {\n if (input.length === 2) return { type: \"vec2\", value: input };\n if (input.length === 3) return { type: \"vec3\", value: input };\n if (input.length === 4) return { type: \"vec4\", value: input };\n }\n\n return { type: \"float\", value: [0] };\n};\n\nexport const applyUniform = (\n gl: GLContext,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n const value = uniform.value;\n\n switch (uniform.type) {\n case \"float\":\n gl.uniform1f(location, value[0] ?? 0);\n break;\n case \"vec2\":\n gl.uniform2f(location, value[0] ?? 0, value[1] ?? 0);\n break;\n case \"vec3\":\n gl.uniform3f(location, value[0] ?? 0, value[1] ?? 0, value[2] ?? 0);\n break;\n case \"vec4\":\n gl.uniform4f(\n location,\n value[0] ?? 0,\n value[1] ?? 0,\n value[2] ?? 0,\n value[3] ?? 0\n );\n break;\n case \"mat3\":\n gl.uniformMatrix3fv(location, false, value);\n break;\n case \"mat4\":\n gl.uniformMatrix4fv(location, false, value);\n break;\n }\n};\n\nexport const applyProgramUniform = (\n gl: GLContext,\n program: WebGLProgram,\n location: WebGLUniformLocation,\n uniform: NormalizedUniform\n): void => {\n gl.useProgram(program);\n applyUniform(gl, location, uniform);\n};\n\n/**\n * Uploads every cached uniform to the bound program. Calls `onMissing` with\n * the name of each uniform the program lacks or optimized out.\n */\nexport const applyUniforms = (\n gl: GLContext,\n locations: ReadonlyMap<string, WebGLUniformLocation>,\n cache: ReadonlyMap<string, NormalizedUniform>,\n onMissing?: (name: string) => void\n): void => {\n for (const [name, uniform] of cache) {\n const location = locations.get(name);\n if (!location) {\n onMissing?.(name);\n continue;\n }\n applyUniform(gl, location, uniform);\n }\n};\n\nexport const collectUniformLocations = (\n gl: GLContext,\n program: WebGLProgram\n): Map<string, WebGLUniformLocation> => {\n const locations = new Map<string, WebGLUniformLocation>();\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) as number;\n\n for (let index = 0; index < count; index += 1) {\n const active = gl.getActiveUniform(program, index);\n if (!active) continue;\n\n const name = active.name.replace(/\\[0\\]$/, \"\");\n const location = gl.getUniformLocation(program, name);\n if (location) {\n locations.set(name, location);\n }\n }\n\n return locations;\n};\n\nexport const createUniformCache = (\n uniforms: Record<string, UniformInput> | undefined\n): Map<string, NormalizedUniform> => {\n const cache = new Map<string, NormalizedUniform>();\n\n for (const [name, value] of Object.entries(uniforms ?? {})) {\n cache.set(toUniformName(name), normalizeUniform(value));\n }\n\n return cache;\n};\n\nconst isExplicitUniform = (input: unknown): input is ExplicitUniformInput => {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return false;\n return \"type\" in input && \"value\" in input;\n};\n","import type { GLContext } from \"../types\";\nimport { collectUniformLocations } from \"./uniforms\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isGLSL300\n} from \"./webgl\";\n\nexport type FullscreenProgram = {\n readonly program: WebGLProgram;\n /** Active uniform locations by name, array uniforms without `[0]`. */\n readonly locations: ReadonlyMap<string, WebGLUniformLocation>;\n /**\n * Binds the program, its quad buffer and `a_position`, so a draw is correct\n * whatever GL state user hooks left behind.\n */\n use(): void;\n /** Draws the fullscreen quad with the current GL state. */\n draw(): void;\n dispose(): void;\n};\n\n/**\n * Compiles `fragment` with a fullscreen-quad vertex shader (the GLSL ES 3.00\n * one when `fragment` starts with `#version 300 es`, unless `vertex` is\n * given) and leaves it bound.\n */\nexport const createFullscreenProgram = (\n gl: GLContext,\n fragment: string,\n vertex?: string\n): FullscreenProgram => {\n const defaultVertex = isGLSL300(fragment)\n ? defaultVertexShader300\n : defaultVertexShader;\n const program = createProgram(gl, vertex ?? defaultVertex, fragment);\n gl.useProgram(program);\n const buffer = createFullscreenBuffer(gl, program);\n const attribLocation = gl.getAttribLocation(program, \"a_position\");\n const locations = collectUniformLocations(gl, program);\n\n return {\n program,\n locations,\n use() {\n gl.useProgram(program);\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n if (attribLocation >= 0) {\n gl.enableVertexAttribArray(attribLocation);\n gl.vertexAttribPointer(attribLocation, 2, gl.FLOAT, false, 0, 0);\n }\n },\n draw() {\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose() {\n gl.deleteBuffer(buffer);\n gl.deleteProgram(program);\n }\n };\n};\n","import type { GLContext } from \"../types\";\nimport {\n createFullscreenBuffer,\n createProgram,\n defaultVertexShader,\n defaultVertexShader300,\n isWebGL2Context\n} from \"./webgl\";\n\nconst blitFragmentShader = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, v_uv);\n}\n`;\n\nconst blitFragmentShader300 = `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_texture;\nout vec4 fragColor;\n\nvoid main() {\n fragColor = texture(u_texture, v_uv);\n}\n`;\n\nexport type Blitter = {\n /**\n * Draws `texture` as a fullscreen quad into `target` (or the default\n * framebuffer when `target` is `null`), setting the viewport to\n * `width`/`height` first. Does not save or restore any other GL state.\n */\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void;\n /** Releases the GL resources owned by this blitter. */\n dispose(): void;\n};\n\n/**\n * Creates a reusable fullscreen-quad \"blit\" utility: draws a texture into a\n * framebuffer (or the canvas) using a minimal passthrough shader. Intended\n * for hand-rolled multi-pass/FBO pipelines; frapx's own multi-pass features\n * are built on the same primitive.\n */\nexport const createBlitter = (gl: GLContext): Blitter => {\n const program = createProgram(\n gl,\n isWebGL2Context(gl) ? defaultVertexShader300 : defaultVertexShader,\n isWebGL2Context(gl) ? blitFragmentShader300 : blitFragmentShader\n );\n const buffer = createFullscreenBuffer(gl, program);\n const textureUniform = gl.getUniformLocation(program, \"u_texture\");\n\n return {\n blit(\n texture: WebGLTexture,\n target: WebGLFramebuffer | null,\n width: number,\n height: number\n ): void {\n gl.bindFramebuffer(gl.FRAMEBUFFER, target);\n gl.viewport(0, 0, width, height);\n gl.useProgram(program);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n const location = gl.getAttribLocation(program, \"a_position\");\n if (location >= 0) {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (textureUniform) {\n gl.uniform1i(textureUniform, 0);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n },\n dispose(): void {\n gl.deleteProgram(program);\n gl.deleteBuffer(buffer);\n }\n };\n};\n","import type {\n GLContext,\n PingPong,\n RenderTarget,\n RenderTargetFormat,\n RenderTargetOptions\n} from \"../types\";\nimport { ShaderCompileError, UnsupportedError } from \"./errors\";\nimport { isWebGL2Context } from \"./webgl\";\n\nconst DEFAULT_CLEAR_COLOR = [0, 0, 0, 0] as const;\n\n/**\n * Whether `format` can be allocated as a color attachment on `gl`. `rgba8` is\n * always available; `rgba16f` and `rgba32f` need WebGL2 and\n * `EXT_color_buffer_float`.\n * Enables the extension as a side effect when present.\n */\nexport const supportsRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat\n): boolean => {\n if (format === \"rgba8\") return true;\n return isWebGL2Context(gl) && gl.getExtension(\"EXT_color_buffer_float\") !== null;\n};\n\n/**\n * Resolves the format a render target will actually use. When `format` is not\n * supported this warns and returns `rgba8`, or throws `UnsupportedError` when\n * `formatFallback` is `false`.\n */\nexport const resolveRenderTargetFormat = (\n gl: GLContext,\n format: RenderTargetFormat = \"rgba8\",\n formatFallback = true\n): RenderTargetFormat => {\n if (supportsRenderTargetFormat(gl, format)) return format;\n\n const reason = `${format} render targets need WebGL2 with EXT_color_buffer_float.`;\n if (!formatFallback) throw new UnsupportedError(reason);\n console.warn(`[frapx] ${reason} Falling back to rgba8.`);\n return \"rgba8\";\n};\n\n/**\n * Creates a texture-backed framebuffer to render into and sample from. The\n * storage is cleared to `clearColor` on creation and on every resize.\n */\nexport const createRenderTarget = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): RenderTarget => {\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n return new Target(gl, width, height, format, options);\n};\n\n/**\n * Creates two render targets of the same size and format for feedback-style\n * rendering: draw into `write` while sampling `read`, then `swap()`.\n */\nexport const createPingPong = (\n gl: GLContext,\n width: number,\n height: number,\n options: RenderTargetOptions = {}\n): PingPong => {\n // Resolve once so a fallback warns a single time for both targets.\n const format = resolveRenderTargetFormat(\n gl,\n options.format,\n options.formatFallback\n );\n let read: RenderTarget = new Target(gl, width, height, format, options);\n let write: RenderTarget;\n try {\n write = new Target(gl, width, height, format, options);\n } catch (error) {\n read.dispose();\n throw error;\n }\n\n return {\n get read() {\n return read;\n },\n get write() {\n return write;\n },\n format,\n swap() {\n const previous = read;\n read = write;\n write = previous;\n },\n resize(nextWidth: number, nextHeight: number) {\n read.resize(nextWidth, nextHeight);\n write.resize(nextWidth, nextHeight);\n },\n clear() {\n read.clear();\n write.clear();\n },\n dispose() {\n read.dispose();\n write.dispose();\n }\n };\n};\n\nclass Target implements RenderTarget {\n texture!: WebGLTexture;\n framebuffer!: WebGLFramebuffer;\n width: number;\n height: number;\n\n constructor(\n private readonly gl: GLContext,\n width: number,\n height: number,\n readonly format: RenderTargetFormat,\n private readonly options: RenderTargetOptions\n ) {\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n resize(width: number, height: number): void {\n if (width === this.width && height === this.height) return;\n this.release();\n this.width = width;\n this.height = height;\n this.allocate();\n }\n\n clear(): void {\n const gl = this.gl;\n const [r, g, b, a] = this.options.clearColor ?? DEFAULT_CLEAR_COLOR;\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.viewport(0, 0, this.width, this.height);\n gl.clearColor(r, g, b, a);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n dispose(): void {\n this.release();\n }\n\n private allocate(): void {\n const gl = this.gl;\n const texture = gl.createTexture();\n if (!texture) {\n throw new ShaderCompileError(\"Failed to create render target texture.\");\n }\n\n const framebuffer = gl.createFramebuffer();\n if (!framebuffer) {\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\"Failed to create render target framebuffer.\");\n }\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (this.format !== \"rgba8\" && isWebGL2Context(gl)) {\n const half = this.format === \"rgba16f\";\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n half ? gl.RGBA16F : gl.RGBA32F,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n half ? gl.HALF_FLOAT : gl.FLOAT,\n null\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n this.width,\n this.height,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n null\n );\n }\n\n const wrap = getWrap(gl, this.options.wrap ?? \"clamp\");\n // Linear filtering of 32-bit float textures is an optional extension.\n const linear =\n this.options.filter !== \"nearest\" &&\n (this.format !== \"rgba32f\" || gl.getExtension(\"OES_texture_float_linear\") !== null);\n const filter = linear ? gl.LINEAR : gl.NEAREST;\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.deleteFramebuffer(framebuffer);\n gl.deleteTexture(texture);\n throw new ShaderCompileError(\n `Render target framebuffer (${this.format}) is incomplete: ${status}`\n );\n }\n\n this.texture = texture;\n this.framebuffer = framebuffer;\n this.clear();\n }\n\n private release(): void {\n this.gl.deleteFramebuffer(this.framebuffer);\n this.gl.deleteTexture(this.texture);\n }\n}\n\nconst getWrap = (\n gl: GLContext,\n wrap: NonNullable<RenderTargetOptions[\"wrap\"]>\n): number => {\n if (wrap === \"repeat\") return gl.REPEAT;\n if (wrap === \"mirror\") return gl.MIRRORED_REPEAT;\n return gl.CLAMP_TO_EDGE;\n};\n"],"mappings":"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","names":["size","getWrap"]}
|