@babylonjs/lite-gl 0.1.0 → 1.0.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/README.md +10 -35
- package/apply-states.d.ts +1 -0
- package/apply-states.js +30 -0
- package/apply-states.js.map +1 -0
- package/blend.d.ts +123 -0
- package/blend.js +194 -0
- package/blend.js.map +1 -0
- package/context.d.ts +130 -0
- package/context.js +354 -0
- package/context.js.map +1 -0
- package/depth-stencil.d.ts +155 -231
- package/depth-stencil.js +399 -262
- package/depth-stencil.js.map +1 -1
- package/dynamic-texture.d.ts +59 -149
- package/dynamic-texture.js +123 -69
- package/dynamic-texture.js.map +1 -1
- package/effect-renderer.d.ts +65 -0
- package/effect-renderer.js +132 -0
- package/effect-renderer.js.map +1 -0
- package/effect.d.ts +142 -0
- package/effect.js +465 -0
- package/effect.js.map +1 -0
- package/html-texture.d.ts +44 -143
- package/html-texture.js +87 -81
- package/html-texture.js.map +1 -1
- package/index.d.ts +23 -1482
- package/index.js +42 -263
- package/index.js.map +1 -1
- package/mesh.d.ts +210 -307
- package/mesh.js +436 -311
- package/mesh.js.map +1 -1
- package/package.json +5 -29
- package/render-loop.d.ts +8 -0
- package/render-loop.js +62 -0
- package/render-loop.js.map +1 -0
- package/render-target.d.ts +190 -290
- package/render-target.js +459 -328
- package/render-target.js.map +1 -1
- package/scissor.d.ts +30 -72
- package/scissor.js +47 -33
- package/scissor.js.map +1 -1
- package/shader.d.ts +22 -0
- package/shader.js +65 -0
- package/shader.js.map +1 -0
- package/sprites.d.ts +182 -263
- package/sprites.js +426 -10
- package/sprites.js.map +1 -1
- package/state.d.ts +126 -0
- package/state.js +153 -0
- package/state.js.map +1 -0
- package/texture.d.ts +142 -0
- package/texture.js +433 -0
- package/texture.js.map +1 -0
- package/effect-BxxwfB_O.js +0 -737
- package/effect-BxxwfB_O.js.map +0 -1
- package/sprites--1oyVtJ3.js +0 -437
- package/sprites--1oyVtJ3.js.map +0 -1
- package/state--j_ncWIi.js +0 -155
- package/state--j_ncWIi.js.map +0 -1
- package/texture-DaMd1gGm.js +0 -329
- package/texture-DaMd1gGm.js.map +0 -1
package/render-target.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-target.js","sources":["../src/render-target.ts"],"sourcesContent":["/**\n * Sub-entry: render-to-texture (offscreen framebuffer) support.\n *\n * Dynamic-importable via `import { ... } from \"@babylonjs/lite-gl/render-target\"`\n * so consumers that only render fullscreen effects to the canvas don't pull the\n * FBO code into their bundles.\n *\n * This is the lite-gl equivalent of Babylon's `RenderTargetWrapper` +\n * `ThinEngine.createRenderTargetTexture` / `bindFramebuffer` /\n * `restoreDefaultFramebuffer` / `_readTexturePixelsSync`. A render target owns a\n * color {@link GLTexture} (or attaches a caller-supplied one) plus an optional\n * depth and/or stencil renderbuffer, all wrapped in a single\n * `WebGLFramebuffer`.\n *\n * The default {@link createRenderTarget} makes an **RGBA8** color target and\n * ships none of the HDR sized-format knowledge; {@link createFloatRenderTarget}\n * is the separate opt-in for float / half-float color attachments (it alone\n * carries the `RGBA16F` / `RGBA32F` table, so RGBA8 consumers tree-shake it\n * away).\n *\n * The full color/depth/stencil GPU set is rebuilt automatically on\n * `webglcontextrestored` — the render target registers itself with the engine's\n * `_renderTargets` registry, and the context-restore protocol calls its\n * `_restore` closure AFTER the standalone texture replay. A caller-supplied\n * (BYO) color texture lives in the engine's `_textures` registry and is restored\n * there first; the RT then re-attaches its freshly-swapped handle.\n */\nimport { bindTextureForUpload, pickSizedInternalFormat, type GLTexture } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.UNSIGNED_BYTE` — the default (RGBA8) color attachment type. */\nconst UNSIGNED_BYTE = 0x1401;\n/** GL `gl.HALF_FLOAT`. */\nconst HALF_FLOAT = 0x140b;\n/** GL `gl.FLOAT`. */\nconst FLOAT = 0x1406;\n/** GL `gl.RGBA`. */\nconst RGBA = 0x1908;\n/** GL `gl.RGBA8` — the default sized internalFormat. */\nconst RGBA8 = 0x8058;\n/** GL `gl.LINEAR`. */\nconst LINEAR = 0x2601;\n/** GL `gl.CLAMP_TO_EDGE`. */\nconst CLAMP_TO_EDGE = 0x812f;\n\n/** Options for {@link createRenderTarget}. `width`/`height` are required; every\n * other field has a Babylon-matching default. The bare\n * `createRenderTarget(engine, { width, height })` makes an RGBA8 color-only\n * target with linear filtering and clamp wrapping. */\nexport interface GLRenderTargetOptions {\n /** Color attachment width in texels. Must be a positive integer. */\n width: number;\n /** Color attachment height in texels. Must be a positive integer. */\n height: number;\n /** Allocate a depth renderbuffer (`DEPTH_COMPONENT16`). Default `false`.\n * Stencil is NOT a create option — opt in (packed depth+stencil, or\n * stencil-only) via `generateRenderTargetStencil`\n * (`@babylonjs/lite-gl/depth-stencil`), which keeps the stencil/packed\n * renderbuffer code out of the render-target core bundle. */\n generateDepthBuffer?: boolean;\n /** Color texture minification filter. Default `gl.LINEAR`. */\n minFilter?: GLenum;\n /** Color texture magnification filter. Default `gl.LINEAR`. */\n magFilter?: GLenum;\n /** Color texture S wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapS?: GLenum;\n /** Color texture T wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapT?: GLenum;\n /** Attach a caller-supplied (BYO) color {@link GLTexture} instead of creating\n * one. When supplied the render target does NOT own or restore it — the\n * texture is engine-managed (restored by the standard texture-restore path\n * first) and the RT re-attaches its swapped handle afterwards. The caller is\n * responsible for sizing it to `width`×`height` and for disposing it. */\n colorTexture?: GLTexture;\n}\n\n/** Options for {@link createFloatRenderTarget} — {@link GLRenderTargetOptions}\n * plus the float color `type`. */\nexport interface GLFloatRenderTargetOptions extends GLRenderTargetOptions {\n /** Float color attachment type. Default `gl.HALF_FLOAT`. Pass `gl.FLOAT` for\n * full 32-bit. Downgraded to the best renderable type the engine supports\n * (`caps.textureFloatRender` / `caps.textureHalfFloatRender`), mirroring\n * Babylon's `getTextureType`. */\n type?: GLenum;\n}\n\n/** Resolved (defaults-applied) attachment description, retained on the render\n * target so `webglcontextrestored` can rebuild the exact same GPU set. */\ninterface ResolvedRTConfig {\n internalFormat: GLenum;\n format: GLenum;\n type: GLenum;\n hasDepth: boolean;\n minFilter: GLenum;\n magFilter: GLenum;\n wrapS: GLenum;\n wrapT: GLenum;\n /** True when the RT created (and therefore owns/restores/deletes) its color\n * texture; false for a BYO {@link GLRenderTargetOptions.colorTexture}. */\n ownsColorTexture: boolean;\n}\n\n/**\n * An offscreen render target — a `WebGLFramebuffer` wrapping a color\n * {@link GLTexture} and an optional depth / stencil renderbuffer. The lite-gl\n * counterpart of Babylon's `RenderTargetWrapper`.\n */\nexport interface GLRenderTarget {\n /** The color attachment, sampleable like any other {@link GLTexture}\n * (`setEffectTexture` / `bindTexture`). For an owned attachment its handle\n * is swapped on `webglcontextrestored` while consumers keep this same\n * reference. */\n texture: GLTexture;\n /** Color attachment width in texels. */\n width: number;\n /** Color attachment height in texels. */\n height: number;\n /** True once the color attachment + framebuffer are allocated. */\n isReady: boolean;\n /** @internal The framebuffer object. Swapped on context-restore. */\n _framebuffer: WebGLFramebuffer | null;\n /** @internal Depth-only (`DEPTH_COMPONENT16`) renderbuffer built by the core,\n * OR the packed/stencil renderbuffer installed by `generateRenderTargetStencil`\n * — a single field either way. Null when neither depth nor stencil is used. */\n _depthStencil: WebGLRenderbuffer | null;\n /**\n * @internal Optional stencil rebuild hook installed by\n * `generateRenderTargetStencil` (`@babylonjs/lite-gl/depth-stencil`). When\n * present it OWNS the depth/stencil renderbuffer (replacing the core\n * depth-only buffer) and is re-invoked after every FBO rebuild\n * (create-via-helper, resize, context-restore) so the attachment survives.\n */\n _rebuildDepthStencil?: (engine: GLEngineContext) => void;\n /** @internal Resolved attachment config, for context-restore rebuild. */\n _config: ResolvedRTConfig;\n /** @internal */\n _disposed: boolean;\n /** @internal Delete every GPU object the target owns (FBO, renderbuffer, and\n * the color texture iff owned). Resets the bound-framebuffer cache if it\n * pointed at this target. Called by `disposeRenderTarget`, `resizeRenderTarget`\n * and engine dispose. */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal Rebuild the FBO + renderbuffer (+ owned color texture) into\n * fresh handles after `webglcontextrestored`. */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/**\n * A pair of {@link GLRenderTarget}s for self-feedback effects: SAMPLE the\n * {@link GLPingPong.read | read} target (last frame's output) while RENDERING\n * into the {@link GLPingPong.write | write} target, then {@link GLPingPong.swap}.\n */\nexport interface GLPingPong {\n /** The target to SAMPLE this frame (the previous frame's output). */\n readonly read: GLRenderTarget;\n /** The target to RENDER into this frame. */\n readonly write: GLRenderTarget;\n /** Exchange `read` and `write`. Call after rendering the `write` target each\n * frame. Allocation-free — flips an internal index, no objects created. */\n swap(): void;\n /** @internal */\n _a: GLRenderTarget;\n /** @internal */\n _b: GLRenderTarget;\n /** @internal */\n _readIsA: boolean;\n /** @internal */\n _disposed: boolean;\n}\n\n/**\n * Create an offscreen **RGBA8** render target.\n *\n * The color attachment is an owned {@link GLTexture} (rebuilt by this target's\n * own restore hook), unless {@link GLRenderTargetOptions.colorTexture} supplies a\n * caller-managed (BYO) one. Mirrors Babylon's `createRenderTargetTexture`.\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLRenderTargetOptions} (`width`/`height` required).\n * @returns The new {@link GLRenderTarget}.\n * @throws If `width`/`height` are not positive integers, a GL handle could not\n * be allocated, or the resulting framebuffer is not complete. On failure every\n * partial GPU object (including an owned color texture) is released first.\n */\nexport function createRenderTarget(engine: GLEngineContext, options: GLRenderTargetOptions): GLRenderTarget {\n return buildRT(engine, options, RGBA8, RGBA, UNSIGNED_BYTE);\n}\n\n/**\n * Create an offscreen **float / half-float** render target — the HDR opt-in\n * counterpart of {@link createRenderTarget}. This is the only render-target\n * factory that references the `RGBA16F` / `RGBA32F` sized-format table, so RGBA8\n * consumers ship none of it.\n *\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The requested type is downgraded to the best renderable type the engine\n * supports (mirroring Babylon's `getTextureType`).\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLFloatRenderTargetOptions}.\n * @returns The new {@link GLRenderTarget}.\n * @throws As {@link createRenderTarget}.\n */\nexport function createFloatRenderTarget(engine: GLEngineContext, options: GLFloatRenderTargetOptions): GLRenderTarget {\n const type = resolveColorType(engine, options.type ?? HALF_FLOAT);\n const internalFormat = pickSizedInternalFormat(engine.gl, RGBA, type);\n return buildRT(engine, options, internalFormat, RGBA, type);\n}\n\n/**\n * Bind the render target's framebuffer as the draw target and set the viewport\n * to cover it. `rt = null` binds the default (canvas) framebuffer and resets the\n * viewport to the full canvas — the counterpart of Babylon's\n * `restoreDefaultFramebuffer`. Subsequent `drawEffect` / `drawIndexed` /\n * `clearEngine` calls write into the bound target.\n *\n * Cached. No-op on a lost/disposed context or a disposed `rt`. Mipmaps are NOT\n * regenerated here — refresh a target's mip chain explicitly via\n * {@link generateRenderTargetMipMaps} after rendering into it.\n *\n * @param engine - The engine.\n * @param rt - The render target to draw into, or `null` for the canvas.\n */\nexport function bindRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (rt !== null && rt._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const fb = rt === null ? null : rt._framebuffer;\n if (s.boundFramebuffer !== fb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n }\n engine._currentRenderTarget = rt;\n if (rt === null) {\n setViewportCached(engine, 0, 0, engine.canvas.width, engine.canvas.height);\n } else {\n setViewportCached(engine, 0, 0, rt.width, rt.height);\n }\n}\n\n/** Regenerate a render target's color-attachment mip chain from its (freshly\n * rendered) level-0 — mipmaps for render targets are a pure manual opt-in\n * (call this after rendering into the target). No-op for a disposed target, a\n * handle-less color attachment, or a lost/disposed context. */\nexport function generateRenderTargetMipMaps(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed || rt._disposed || rt.texture.handle === null) {\n return;\n }\n bindTextureForUpload(engine, rt.texture.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Resize the render target's color attachment (and depth/stencil renderbuffer).\n * Reallocates storage at the new size; the contents are discarded. The\n * `GLRenderTarget` / `GLTexture` identity is preserved, so consumers and\n * effect-sampler bindings holding the reference stay valid. If this target was\n * the live draw target, it is rebound (with the new-size viewport) afterwards.\n *\n * No-op when the size is unchanged or `rt` is disposed. While the context is\n * lost the new size is recorded but the GL reallocation is deferred to the\n * restore hook.\n *\n * @param engine - The engine.\n * @param rt - The render target to resize.\n * @param width - New width in texels (≥ 1).\n * @param height - New height in texels (≥ 1).\n */\nexport function resizeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget, width: number, height: number): void {\n if (rt._disposed) {\n return;\n }\n validateSize(width, height);\n if (rt.width === width && rt.height === height) {\n return;\n }\n rt.width = width;\n rt.height = height;\n rt.texture.width = width;\n rt.texture.height = height;\n if (engine._isLost || engine._disposed) {\n return;\n }\n // Capture the live binding BEFORE we delete the old FBO so we can restore it.\n const wasBound = engine._state.boundFramebuffer === rt._framebuffer && rt._framebuffer !== null;\n // For a BYO color texture, re-specify the caller's storage at the new size\n // (contents discarded, like the owned path). `_updateRaw` updates the\n // texture's tracked dims AND re-runs its upload closure — `_upload` alone\n // would re-upload at the stale ORIGINAL size, leaving the attachment a\n // different size than the FBO. An external handle without `_updateRaw` must\n // be resized by its owner; we then just rebuild the FBO around it. An owned\n // texture is recreated wholesale by allocateRenderTargetGpu.\n if (!rt._config.ownsColorTexture) {\n rt.texture._updateRaw?.(engine, null, width, height, 4);\n }\n rt._deleteGpu(engine.gl);\n allocateRenderTargetGpu(engine, rt);\n if (wasBound) {\n bindRenderTarget(engine, rt);\n }\n}\n\n/**\n * Synchronously read back a rectangle of the render target's color attachment\n * via `gl.readPixels` — the lite-gl equivalent of Babylon's\n * `_readTexturePixelsSync`. Binds the target's framebuffer (leaving it bound,\n * matching Babylon).\n *\n * The returned array element type follows the color attachment type:\n * `Uint8Array` for `UNSIGNED_BYTE`, `Float32Array` for `FLOAT`, `Uint16Array`\n * for `HALF_FLOAT`. Origin is GL bottom-left.\n *\n * @param engine - The engine.\n * @param rt - The render target to read from.\n * @param x - Lower-left X of the read rectangle, in texels.\n * @param y - Lower-left Y of the read rectangle, in texels.\n * @param width - Read rectangle width in texels.\n * @param height - Read rectangle height in texels.\n * @param into - Optional preallocated buffer (`width*height*4` elements of the\n * matching type). Reused to avoid per-call allocation.\n * @returns The pixel buffer (the provided `into`, or a freshly allocated one).\n * Empty buffer on a lost/disposed context.\n */\nexport function readRenderTargetPixels(engine: GLEngineContext, rt: GLRenderTarget, x: number, y: number, width: number, height: number, into?: ArrayBufferView): ArrayBufferView {\n const elements = width * height * 4;\n if (engine._isLost || engine._disposed || rt._disposed) {\n return into ?? new Uint8Array(0);\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.boundFramebuffer !== rt._framebuffer) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, rt._framebuffer);\n s.boundFramebuffer = rt._framebuffer;\n }\n const type = rt._config.type;\n let buffer = into;\n if (buffer === undefined) {\n buffer = type === gl.FLOAT ? new Float32Array(elements) : type === gl.HALF_FLOAT ? new Uint16Array(elements) : new Uint8Array(elements);\n }\n gl.readPixels(x, y, width, height, gl.RGBA, type, buffer);\n return buffer;\n}\n\n/**\n * Release the render target's framebuffer, depth/stencil renderbuffer and (iff\n * owned) color texture, and unregister it from the engine. Idempotent, and a\n * no-op for `null`/`undefined` (so an optional target can be released\n * unconditionally). Clears the bound-framebuffer cache if it pointed at this\n * target, and any sampler slot that held the color texture handle.\n *\n * A BYO {@link GLRenderTargetOptions.colorTexture} is NOT disposed here — it is\n * engine-managed and the caller owns its lifetime.\n *\n * @param engine - The engine.\n * @param rt - The render target to dispose, or `null`/`undefined` for a no-op.\n */\nexport function disposeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null | undefined): void {\n if (rt === null || rt === undefined || rt._disposed) {\n return;\n }\n rt._disposed = true;\n // Only the owned color texture is marked disposed here; a BYO texture stays\n // live for its caller-owner.\n if (rt._config.ownsColorTexture) {\n rt.texture._disposed = true;\n }\n if (engine._currentRenderTarget === rt) {\n engine._currentRenderTarget = null;\n }\n const i = engine._renderTargets.indexOf(rt);\n if (i !== -1) {\n engine._renderTargets.splice(i, 1);\n }\n // Capture the handle before _deleteGpu nulls it (owned case).\n const handle = rt.texture.handle;\n if (!engine._isLost && !engine._disposed) {\n rt._deleteGpu(engine.gl);\n } else {\n rt._framebuffer = null;\n rt._depthStencil = null;\n }\n if (handle !== null) {\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === handle) {\n bound[u] = null;\n }\n }\n }\n}\n\n/**\n * Create a {@link GLPingPong}: two same-sized {@link GLRenderTarget}s for\n * self-feedback effects. `read` starts as the first target and `write` the\n * second; {@link GLPingPong.swap} exchanges them allocation-free.\n *\n * @param engine - The engine to create GL resources on.\n * @param options - Applied identically to both targets.\n * @returns The new {@link GLPingPong}.\n * @throws As {@link createRenderTarget}. If the second target fails to build the\n * first is disposed before rethrowing (no leak).\n */\nexport function createPingPong(engine: GLEngineContext, options: GLRenderTargetOptions): GLPingPong {\n const a = createRenderTarget(engine, options);\n let b: GLRenderTarget;\n try {\n b = createRenderTarget(engine, options);\n } catch (e) {\n disposeRenderTarget(engine, a);\n throw e;\n }\n const pp: GLPingPong = {\n _a: a,\n _b: b,\n _readIsA: true,\n _disposed: false,\n get read(): GLRenderTarget {\n return pp._readIsA ? pp._a : pp._b;\n },\n get write(): GLRenderTarget {\n return pp._readIsA ? pp._b : pp._a;\n },\n swap(): void {\n pp._readIsA = !pp._readIsA;\n },\n };\n return pp;\n}\n\n/**\n * Resize both targets of a {@link GLPingPong}. No-op when disposed.\n *\n * @param engine - The engine that owns `pp`.\n * @param pp - The ping-pong pair to resize.\n * @param width - New width in texels (positive integer).\n * @param height - New height in texels (positive integer).\n */\nexport function resizePingPong(engine: GLEngineContext, pp: GLPingPong, width: number, height: number): void {\n if (pp._disposed) {\n return;\n }\n resizeRenderTarget(engine, pp._a, width, height);\n resizeRenderTarget(engine, pp._b, width, height);\n}\n\n/**\n * Release both targets of a {@link GLPingPong}. Idempotent, and a no-op for\n * `null`/`undefined` (matching {@link disposeRenderTarget}).\n *\n * @param engine - The engine that owns `pp`.\n * @param pp - The ping-pong pair to release, or `null`/`undefined` for a no-op.\n */\nexport function disposePingPong(engine: GLEngineContext, pp: GLPingPong | null | undefined): void {\n if (pp === null || pp === undefined || pp._disposed) {\n return;\n }\n pp._disposed = true;\n disposeRenderTarget(engine, pp._a);\n disposeRenderTarget(engine, pp._b);\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Shared private constructor. Validates size, resolves the config (given the\n * exact sized `internalFormat` by the caller — NO format-table lookup), wires\n * the owned-or-BYO color texture, allocates the GPU set atomically, and\n * registers the target. */\nfunction buildRT(engine: GLEngineContext, options: GLRenderTargetOptions, internalFormat: GLenum, format: GLenum, type: GLenum): GLRenderTarget {\n const width = options.width;\n const height = options.height;\n validateSize(width, height);\n const gl = engine.gl;\n const byo = options.colorTexture;\n const config: ResolvedRTConfig = {\n internalFormat,\n format,\n type,\n hasDepth: options.generateDepthBuffer ?? false,\n minFilter: options.minFilter ?? LINEAR,\n magFilter: options.magFilter ?? LINEAR,\n wrapS: options.wrapS ?? CLAMP_TO_EDGE,\n wrapT: options.wrapT ?? CLAMP_TO_EDGE,\n ownsColorTexture: byo === undefined,\n };\n\n const texture: GLTexture = byo ?? {\n handle: null as unknown as WebGLTexture,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n // Owned-by-RT: its storage is (re)allocated by allocateRenderTargetGpu,\n // never via the engine `_textures` replay (it is NOT registered there).\n _upload: () => {},\n _wasReady: false,\n };\n\n const rt: GLRenderTarget = {\n texture,\n width,\n height,\n isReady: false,\n _framebuffer: null,\n _depthStencil: null,\n _rebuildDepthStencil: undefined,\n _config: config,\n _disposed: false,\n _deleteGpu: () => {},\n _restore: () => {},\n };\n\n rt._deleteGpu = (glc: WebGL2RenderingContext): void => {\n const s = engine._state;\n if (rt._framebuffer !== null) {\n // Deleting the bound FBO reverts GL to framebuffer 0 (spec) — just\n // reset the cache, no explicit rebind needed.\n if (s.boundFramebuffer === rt._framebuffer) {\n s.boundFramebuffer = null;\n }\n glc.deleteFramebuffer(rt._framebuffer);\n rt._framebuffer = null;\n }\n if (rt._depthStencil !== null) {\n glc.deleteRenderbuffer(rt._depthStencil);\n rt._depthStencil = null;\n }\n // Never delete a BYO color texture — the caller-owner manages it.\n if (config.ownsColorTexture && rt.texture.handle !== null) {\n glc.deleteTexture(rt.texture.handle);\n rt.texture.handle = null as unknown as WebGLTexture;\n }\n rt.texture.isReady = false;\n rt.isReady = false;\n };\n\n rt._restore = (target: GLEngineContext): void => {\n // Resilient: a restore failure must not break the engine's restore loop.\n try {\n allocateRenderTargetGpu(target, rt);\n } catch (err) {\n console.error(\"lite-gl: render target restore failed\", err);\n }\n };\n\n allocateRenderTargetGpu(engine, rt);\n engine._renderTargets.push(rt);\n return rt;\n}\n\n/** Downgrade a requested float/half-float color type to the best renderable\n * type the engine supports, mirroring Babylon's `getTextureType`. */\nfunction resolveColorType(engine: GLEngineContext, type: GLenum): GLenum {\n const gl = engine.gl;\n if (type === FLOAT && !engine.caps.textureFloatRender) {\n return engine.caps.textureHalfFloatRender ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n }\n if (type === HALF_FLOAT && !engine.caps.textureHalfFloatRender) {\n return gl.UNSIGNED_BYTE;\n }\n return type;\n}\n\n/** Validate a render-target size is a pair of positive integers. */\nfunction validateSize(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1) {\n throw new Error(`lite-gl: render target size must be positive integers, got ${width}x${height}`);\n }\n}\n\n/**\n * (Re)allocate the color texture (iff owned), framebuffer and depth/stencil\n * renderbuffer into fresh handles, attach them, and validate completeness.\n * Shared by create / resize / context-restore. No-op on a lost/disposed context.\n *\n * ATOMIC: captures the previously-bound framebuffer and restores it in a\n * `finally`; on any failure deletes the partial FBO / renderbuffer (and the\n * owned color texture it created), nulls the fields, and rethrows — so a failed\n * build never leaks a GPU handle nor leaves a half-attached framebuffer bound.\n */\nfunction allocateRenderTargetGpu(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const c = rt._config;\n const prevFb = s.boundFramebuffer;\n let createdTexture: WebGLTexture | null = null;\n let fb: WebGLFramebuffer | null = null;\n let rb: WebGLRenderbuffer | null = null;\n try {\n // ── Color texture (owned only) ───────────────────────────────────────\n if (c.ownsColorTexture) {\n const texHandle = gl.createTexture();\n if (texHandle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null (render target color)\");\n }\n createdTexture = texHandle;\n rt.texture.handle = texHandle;\n bindTextureForUpload(engine, texHandle);\n gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, c.minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, c.magFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, c.wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, c.wrapT);\n rt.texture.isReady = true;\n rt.texture._wasReady = true;\n }\n\n // ── Framebuffer + attachments ────────────────────────────────────────\n fb = gl.createFramebuffer();\n if (fb === null) {\n throw new Error(\"lite-gl: gl.createFramebuffer returned null\");\n }\n rt._framebuffer = fb;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rt.texture.handle, 0);\n\n // ── Depth (core, DEPTH-ONLY) ─────────────────────────────────────────\n // The core only ever builds a DEPTH_COMPONENT16 depth buffer. Stencil /\n // packed depth-stencil is an opt-in installed by\n // `generateRenderTargetStencil` (`@babylonjs/lite-gl/depth-stencil`),\n // which sets `_rebuildDepthStencil` to a closure that REPLACES the\n // depth-only buffer below with its own packed/stencil renderbuffer. That\n // hook is re-run here on every rebuild (create / resize / context-restore)\n // so a helper-added stencil attachment survives at the new size.\n rt._depthStencil = null;\n if (c.hasDepth) {\n rb = gl.createRenderbuffer();\n if (rb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null\");\n }\n gl.bindRenderbuffer(gl.RENDERBUFFER, rb);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rt.width, rt.height);\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);\n gl.bindRenderbuffer(gl.RENDERBUFFER, null);\n rt._depthStencil = rb;\n }\n // A helper-attached stencil replaces/augments the depth-only buffer.\n rt._rebuildDepthStencil?.(engine);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete (status 0x${status.toString(16)})`);\n }\n rt.isReady = true;\n } catch (e) {\n // Free whatever depth/stencil renderbuffer is currently attached. After a\n // `_rebuildDepthStencil` hook ran, `rt._depthStencil` may be a packed buffer\n // the hook swapped in (it deletes the core `rb` itself on success), so free\n // the live `rt._depthStencil` rather than the stale local `rb`.\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = null;\n if (fb !== null) {\n gl.deleteFramebuffer(fb);\n }\n rt._framebuffer = null;\n // Delete ONLY a texture we created here (owned). Never a BYO texture.\n if (createdTexture !== null) {\n gl.deleteTexture(createdTexture);\n rt.texture.handle = null as unknown as WebGLTexture;\n rt.texture.isReady = false;\n }\n rt.isReady = false;\n throw e;\n } finally {\n // Restore the previously-bound draw target — creation/restore must not\n // silently redirect subsequent draws.\n if (s.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFb);\n s.boundFramebuffer = prevFb;\n }\n }\n}\n\n/** Inline cached `gl.viewport` — kept local so the render-target sub-entry has\n * no runtime dependency on the effect-renderer module. */\nfunction setViewportCached(engine: GLEngineContext, x: number, y: number, w: number, h: number): void {\n const s = engine._state;\n if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {\n return;\n }\n s.viewportX = x;\n s.viewportY = y;\n s.viewportW = w;\n s.viewportH = h;\n engine.gl.viewport(x, y, w, h);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"render-target.js","sourceRoot":"","sources":["../src/render-target.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Render-to-texture (offscreen framebuffer) support.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that only render fullscreen effects to the\n * canvas tree-shake the FBO code out.\n *\n * This is the lite-gl equivalent of Babylon's `RenderTargetWrapper` +\n * `ThinEngine.createRenderTargetTexture` / `bindFramebuffer` /\n * `restoreDefaultFramebuffer` / `_readTexturePixelsSync`. A render target owns a\n * color {@link GLTexture} (or attaches a caller-supplied one) plus an optional\n * depth and/or stencil renderbuffer, all wrapped in a single\n * `WebGLFramebuffer`.\n *\n * The default {@link createRenderTarget} makes an **RGBA8** color target and\n * ships none of the HDR sized-format knowledge; {@link createFloatRenderTarget}\n * is the separate opt-in for float / half-float color attachments (it alone\n * carries the `RGBA16F` / `RGBA32F` table, so RGBA8 consumers tree-shake it\n * away).\n *\n * The full color/depth/stencil GPU set is rebuilt automatically on\n * `webglcontextrestored` — the render target registers itself with the engine's\n * `_renderTargets` registry, and the context-restore protocol calls its\n * `_restore` closure AFTER the standalone texture replay. A caller-supplied\n * (BYO) color texture lives in the engine's `_textures` registry and is restored\n * there first; the RT then re-attaches its freshly-swapped handle.\n */\nimport { bindTextureForUpload, pickSizedInternalFormat, type GLTexture } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.UNSIGNED_BYTE` — the default (RGBA8) color attachment type. */\nconst UNSIGNED_BYTE = 0x1401;\n/** GL `gl.HALF_FLOAT`. */\nconst HALF_FLOAT = 0x140b;\n/** GL `gl.FLOAT`. */\nconst FLOAT = 0x1406;\n/** GL `gl.RGBA`. */\nconst RGBA = 0x1908;\n/** GL `gl.RGBA8` — the default sized internalFormat. */\nconst RGBA8 = 0x8058;\n/** GL `gl.LINEAR`. */\nconst LINEAR = 0x2601;\n/** GL `gl.CLAMP_TO_EDGE`. */\nconst CLAMP_TO_EDGE = 0x812f;\n\n/** Options for {@link createRenderTarget}. `width`/`height` are required; every\n * other field has a Babylon-matching default. The bare\n * `createRenderTarget(engine, { width, height })` makes an RGBA8 color-only\n * target with linear filtering and clamp wrapping. */\nexport interface GLRenderTargetOptions {\n /** Color attachment width in texels. Must be a positive integer. */\n width: number;\n /** Color attachment height in texels. Must be a positive integer. */\n height: number;\n /** Allocate a depth renderbuffer (`DEPTH_COMPONENT16`). Default `false`.\n * Stencil is NOT a create option — opt in (packed depth+stencil, or\n * stencil-only) via `generateRenderTargetStencil`\n * (`@babylonjs/lite-gl`), which keeps the stencil/packed\n * renderbuffer code out of the render-target core bundle. */\n generateDepthBuffer?: boolean;\n /** Color texture minification filter. Default `gl.LINEAR`. */\n minFilter?: GLenum;\n /** Color texture magnification filter. Default `gl.LINEAR`. */\n magFilter?: GLenum;\n /** Color texture S wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapS?: GLenum;\n /** Color texture T wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapT?: GLenum;\n /** Attach a caller-supplied (BYO) color {@link GLTexture} instead of creating\n * one. When supplied the render target does NOT own or restore it — the\n * texture is engine-managed (restored by the standard texture-restore path\n * first) and the RT re-attaches its swapped handle afterwards. The caller is\n * responsible for sizing it to `width`×`height` and for disposing it. */\n colorTexture?: GLTexture;\n}\n\n/** Options for {@link createFloatRenderTarget} — {@link GLRenderTargetOptions}\n * plus the float color `type`. */\nexport interface GLFloatRenderTargetOptions extends GLRenderTargetOptions {\n /** Float color attachment type. Default `gl.HALF_FLOAT`. Pass `gl.FLOAT` for\n * full 32-bit. Downgraded to the best renderable type the engine supports\n * (`caps.textureFloatRender` / `caps.textureHalfFloatRender`), mirroring\n * Babylon's `getTextureType`. */\n type?: GLenum;\n}\n\n/** Resolved (defaults-applied) attachment description, retained on the render\n * target so `webglcontextrestored` can rebuild the exact same GPU set. */\ninterface ResolvedRTConfig {\n internalFormat: GLenum;\n format: GLenum;\n type: GLenum;\n hasDepth: boolean;\n minFilter: GLenum;\n magFilter: GLenum;\n wrapS: GLenum;\n wrapT: GLenum;\n /** True when the RT created (and therefore owns/restores/deletes) its color\n * texture; false for a BYO {@link GLRenderTargetOptions.colorTexture}. */\n ownsColorTexture: boolean;\n}\n\n/**\n * An offscreen render target — a `WebGLFramebuffer` wrapping a color\n * {@link GLTexture} and an optional depth / stencil renderbuffer. The lite-gl\n * counterpart of Babylon's `RenderTargetWrapper`.\n */\nexport interface GLRenderTarget {\n /** The color attachment, sampleable like any other {@link GLTexture}\n * (`setEffectTexture` / `bindTexture`). For an owned attachment its handle\n * is swapped on `webglcontextrestored` while consumers keep this same\n * reference. */\n texture: GLTexture;\n /** Color attachment width in texels. */\n width: number;\n /** Color attachment height in texels. */\n height: number;\n /** True once the color attachment + framebuffer are allocated. */\n isReady: boolean;\n /** @internal The framebuffer object. Swapped on context-restore. */\n _framebuffer: WebGLFramebuffer | null;\n /** @internal Depth-only (`DEPTH_COMPONENT16`) renderbuffer built by the core,\n * OR the packed/stencil renderbuffer installed by `generateRenderTargetStencil`\n * — a single field either way. Null when neither depth nor stencil is used. */\n _depthStencil: WebGLRenderbuffer | null;\n /**\n * @internal Optional stencil rebuild hook installed by\n * `generateRenderTargetStencil` (`@babylonjs/lite-gl`). When\n * present it OWNS the depth/stencil renderbuffer (replacing the core\n * depth-only buffer) and is re-invoked after every FBO rebuild\n * (create-via-helper, resize, context-restore) so the attachment survives.\n */\n _rebuildDepthStencil?: (engine: GLEngineContext) => void;\n /** @internal Resolved attachment config, for context-restore rebuild. */\n _config: ResolvedRTConfig;\n /** @internal */\n _disposed: boolean;\n /** @internal Delete every GPU object the target owns (FBO, renderbuffer, and\n * the color texture iff owned). Resets the bound-framebuffer cache if it\n * pointed at this target. Called by `disposeRenderTarget`, `resizeRenderTarget`\n * and engine dispose. */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal Rebuild the FBO + renderbuffer (+ owned color texture) into\n * fresh handles after `webglcontextrestored`. */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/**\n * Create an offscreen **RGBA8** render target.\n *\n * The color attachment is an owned {@link GLTexture} (rebuilt by this target's\n * own restore hook), unless {@link GLRenderTargetOptions.colorTexture} supplies a\n * caller-managed (BYO) one. Mirrors Babylon's `createRenderTargetTexture`.\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLRenderTargetOptions} (`width`/`height` required).\n * @returns The new {@link GLRenderTarget}.\n * @throws If `width`/`height` are not positive integers, a GL handle could not\n * be allocated, or the resulting framebuffer is not complete. On failure every\n * partial GPU object (including an owned color texture) is released first.\n */\nexport function createRenderTarget(engine: GLEngineContext, options: GLRenderTargetOptions): GLRenderTarget {\n return buildRT(engine, options, RGBA8, RGBA, UNSIGNED_BYTE);\n}\n\n/**\n * Create an offscreen **float / half-float** render target — the HDR opt-in\n * counterpart of {@link createRenderTarget}. This is the only render-target\n * factory that references the `RGBA16F` / `RGBA32F` sized-format table, so RGBA8\n * consumers ship none of it.\n *\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The requested type is downgraded to the best renderable type the engine\n * supports (mirroring Babylon's `getTextureType`).\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLFloatRenderTargetOptions}.\n * @returns The new {@link GLRenderTarget}.\n * @throws As {@link createRenderTarget}.\n */\nexport function createFloatRenderTarget(engine: GLEngineContext, options: GLFloatRenderTargetOptions): GLRenderTarget {\n const type = resolveColorType(engine, options.type ?? HALF_FLOAT);\n const internalFormat = pickSizedInternalFormat(engine.gl, RGBA, type);\n return buildRT(engine, options, internalFormat, RGBA, type);\n}\n\n/**\n * Bind the render target's framebuffer as the draw target and set the viewport\n * to cover it. `rt = null` binds the default (canvas) framebuffer and resets the\n * viewport to the full canvas — the counterpart of Babylon's\n * `restoreDefaultFramebuffer`. Subsequent `drawEffect` / `drawIndexed` /\n * `clearEngine` calls write into the bound target.\n *\n * Cached. No-op on a lost/disposed context or a disposed `rt`. Mipmaps are NOT\n * regenerated here — refresh a target's mip chain explicitly via\n * {@link generateRenderTargetMipMaps} after rendering into it.\n *\n * @param engine - The engine.\n * @param rt - The render target to draw into, or `null` for the canvas.\n */\nexport function bindRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (rt !== null && rt._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const fb = rt === null ? null : rt._framebuffer;\n if (s.boundFramebuffer !== fb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n }\n engine._currentRenderTarget = rt;\n if (rt === null) {\n setViewportCached(engine, 0, 0, engine.canvas.width, engine.canvas.height);\n } else {\n setViewportCached(engine, 0, 0, rt.width, rt.height);\n }\n}\n\n/** Regenerate a render target's color-attachment mip chain from its (freshly\n * rendered) level-0 — mipmaps for render targets are a pure manual opt-in\n * (call this after rendering into the target). No-op for a disposed target, a\n * handle-less color attachment, or a lost/disposed context. */\nexport function generateRenderTargetMipMaps(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed || rt._disposed || rt.texture.handle === null) {\n return;\n }\n bindTextureForUpload(engine, rt.texture.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Resize the render target's color attachment (and depth/stencil renderbuffer).\n * Reallocates storage at the new size; the contents are discarded. The\n * `GLRenderTarget` / `GLTexture` identity is preserved, so consumers and\n * effect-sampler bindings holding the reference stay valid. If this target was\n * the live draw target, it is rebound (with the new-size viewport) afterwards.\n *\n * No-op when the size is unchanged or `rt` is disposed. While the context is\n * lost the new size is recorded but the GL reallocation is deferred to the\n * restore hook.\n *\n * @param engine - The engine.\n * @param rt - The render target to resize.\n * @param width - New width in texels (≥ 1).\n * @param height - New height in texels (≥ 1).\n */\nexport function resizeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget, width: number, height: number): void {\n if (rt._disposed) {\n return;\n }\n validateSize(width, height);\n if (rt.width === width && rt.height === height) {\n return;\n }\n rt.width = width;\n rt.height = height;\n rt.texture.width = width;\n rt.texture.height = height;\n if (engine._isLost || engine._disposed) {\n return;\n }\n // Capture the live binding BEFORE we delete the old FBO so we can restore it.\n const wasBound = engine._state.boundFramebuffer === rt._framebuffer && rt._framebuffer !== null;\n // For a BYO color texture, re-specify the caller's storage at the new size\n // (contents discarded, like the owned path). `_updateRaw` updates the\n // texture's tracked dims AND re-runs its upload closure — `_upload` alone\n // would re-upload at the stale ORIGINAL size, leaving the attachment a\n // different size than the FBO. An external handle without `_updateRaw` must\n // be resized by its owner; we then just rebuild the FBO around it. An owned\n // texture is recreated wholesale by allocateRenderTargetGpu.\n if (!rt._config.ownsColorTexture) {\n rt.texture._updateRaw?.(engine, null, width, height, 4);\n }\n rt._deleteGpu(engine.gl);\n allocateRenderTargetGpu(engine, rt);\n if (wasBound) {\n bindRenderTarget(engine, rt);\n }\n}\n\n/**\n * Synchronously read back a rectangle of the render target's color attachment\n * via `gl.readPixels` — the lite-gl equivalent of Babylon's\n * `_readTexturePixelsSync`. Binds the target's framebuffer (leaving it bound,\n * matching Babylon).\n *\n * The returned array element type follows the color attachment type:\n * `Uint8Array` for `UNSIGNED_BYTE`, `Float32Array` for `FLOAT`, `Uint16Array`\n * for `HALF_FLOAT`. Origin is GL bottom-left.\n *\n * @param engine - The engine.\n * @param rt - The render target to read from.\n * @param x - Lower-left X of the read rectangle, in texels.\n * @param y - Lower-left Y of the read rectangle, in texels.\n * @param width - Read rectangle width in texels.\n * @param height - Read rectangle height in texels.\n * @param into - Optional preallocated buffer (`width*height*4` elements of the\n * matching type). Reused to avoid per-call allocation.\n * @returns The pixel buffer (the provided `into`, or a freshly allocated one).\n * Empty buffer on a lost/disposed context.\n */\nexport function readRenderTargetPixels(engine: GLEngineContext, rt: GLRenderTarget, x: number, y: number, width: number, height: number, into?: ArrayBufferView): ArrayBufferView {\n const elements = width * height * 4;\n if (engine._isLost || engine._disposed || rt._disposed) {\n return into ?? new Uint8Array(0);\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.boundFramebuffer !== rt._framebuffer) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, rt._framebuffer);\n s.boundFramebuffer = rt._framebuffer;\n }\n const type = rt._config.type;\n let buffer = into;\n if (buffer === undefined) {\n buffer = type === gl.FLOAT ? new Float32Array(elements) : type === gl.HALF_FLOAT ? new Uint16Array(elements) : new Uint8Array(elements);\n }\n gl.readPixels(x, y, width, height, gl.RGBA, type, buffer);\n return buffer;\n}\n\n/**\n * Release the render target's framebuffer, depth/stencil renderbuffer and (iff\n * owned) color texture, and unregister it from the engine. Idempotent, and a\n * no-op for `null`/`undefined` (so an optional target can be released\n * unconditionally). Clears the bound-framebuffer cache if it pointed at this\n * target, and any sampler slot that held the color texture handle.\n *\n * A BYO {@link GLRenderTargetOptions.colorTexture} is NOT disposed here — it is\n * engine-managed and the caller owns its lifetime.\n *\n * @param engine - The engine.\n * @param rt - The render target to dispose, or `null`/`undefined` for a no-op.\n */\nexport function disposeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null | undefined): void {\n if (rt === null || rt === undefined || rt._disposed) {\n return;\n }\n rt._disposed = true;\n // Only the owned color texture is marked disposed here; a BYO texture stays\n // live for its caller-owner.\n if (rt._config.ownsColorTexture) {\n rt.texture._disposed = true;\n }\n if (engine._currentRenderTarget === rt) {\n engine._currentRenderTarget = null;\n }\n const i = engine._renderTargets.indexOf(rt);\n if (i !== -1) {\n engine._renderTargets.splice(i, 1);\n }\n // Capture the handle before _deleteGpu nulls it (owned case).\n const handle = rt.texture.handle;\n if (!engine._isLost && !engine._disposed) {\n rt._deleteGpu(engine.gl);\n } else {\n rt._framebuffer = null;\n rt._depthStencil = null;\n }\n if (handle !== null) {\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === handle) {\n bound[u] = null;\n }\n }\n }\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Shared private constructor. Validates size, resolves the config (given the\n * exact sized `internalFormat` by the caller — NO format-table lookup), wires\n * the owned-or-BYO color texture, allocates the GPU set atomically, and\n * registers the target. */\nfunction buildRT(engine: GLEngineContext, options: GLRenderTargetOptions, internalFormat: GLenum, format: GLenum, type: GLenum): GLRenderTarget {\n const width = options.width;\n const height = options.height;\n validateSize(width, height);\n const gl = engine.gl;\n const byo = options.colorTexture;\n const config: ResolvedRTConfig = {\n internalFormat,\n format,\n type,\n hasDepth: options.generateDepthBuffer ?? false,\n minFilter: options.minFilter ?? LINEAR,\n magFilter: options.magFilter ?? LINEAR,\n wrapS: options.wrapS ?? CLAMP_TO_EDGE,\n wrapT: options.wrapT ?? CLAMP_TO_EDGE,\n ownsColorTexture: byo === undefined,\n };\n\n const texture: GLTexture = byo ?? {\n handle: null as unknown as WebGLTexture,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n // Owned-by-RT: its storage is (re)allocated by allocateRenderTargetGpu,\n // never via the engine `_textures` replay (it is NOT registered there).\n _upload: () => {},\n _wasReady: false,\n };\n\n const rt: GLRenderTarget = {\n texture,\n width,\n height,\n isReady: false,\n _framebuffer: null,\n _depthStencil: null,\n _rebuildDepthStencil: undefined,\n _config: config,\n _disposed: false,\n _deleteGpu: () => {},\n _restore: () => {},\n };\n\n rt._deleteGpu = (glc: WebGL2RenderingContext): void => {\n const s = engine._state;\n if (rt._framebuffer !== null) {\n // Deleting the bound FBO reverts GL to framebuffer 0 (spec) — just\n // reset the cache, no explicit rebind needed.\n if (s.boundFramebuffer === rt._framebuffer) {\n s.boundFramebuffer = null;\n }\n glc.deleteFramebuffer(rt._framebuffer);\n rt._framebuffer = null;\n }\n if (rt._depthStencil !== null) {\n glc.deleteRenderbuffer(rt._depthStencil);\n rt._depthStencil = null;\n }\n // Never delete a BYO color texture — the caller-owner manages it.\n if (config.ownsColorTexture && rt.texture.handle !== null) {\n glc.deleteTexture(rt.texture.handle);\n rt.texture.handle = null as unknown as WebGLTexture;\n }\n rt.texture.isReady = false;\n rt.isReady = false;\n };\n\n rt._restore = (target: GLEngineContext): void => {\n // Resilient: a restore failure must not break the engine's restore loop.\n try {\n allocateRenderTargetGpu(target, rt);\n } catch (err) {\n console.error(\"lite-gl: render target restore failed\", err);\n }\n };\n\n allocateRenderTargetGpu(engine, rt);\n engine._renderTargets.push(rt);\n return rt;\n}\n\n/** Downgrade a requested float/half-float color type to the best renderable\n * type the engine supports, mirroring Babylon's `getTextureType`. */\nfunction resolveColorType(engine: GLEngineContext, type: GLenum): GLenum {\n const gl = engine.gl;\n if (type === FLOAT && !engine.caps.textureFloatRender) {\n return engine.caps.textureHalfFloatRender ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n }\n if (type === HALF_FLOAT && !engine.caps.textureHalfFloatRender) {\n return gl.UNSIGNED_BYTE;\n }\n return type;\n}\n\n/** Validate a render-target size is a pair of positive integers. */\nfunction validateSize(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1) {\n throw new Error(`lite-gl: render target size must be positive integers, got ${width}x${height}`);\n }\n}\n\n/**\n * (Re)allocate the color texture (iff owned), framebuffer and depth/stencil\n * renderbuffer into fresh handles, attach them, and validate completeness.\n * Shared by create / resize / context-restore. No-op on a lost/disposed context.\n *\n * ATOMIC: captures the previously-bound framebuffer and restores it in a\n * `finally`; on any failure deletes the partial FBO / renderbuffer (and the\n * owned color texture it created), nulls the fields, and rethrows — so a failed\n * build never leaks a GPU handle nor leaves a half-attached framebuffer bound.\n */\nfunction allocateRenderTargetGpu(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const c = rt._config;\n const prevFb = s.boundFramebuffer;\n let createdTexture: WebGLTexture | null = null;\n let fb: WebGLFramebuffer | null = null;\n let rb: WebGLRenderbuffer | null = null;\n try {\n // ── Color texture (owned only) ───────────────────────────────────────\n if (c.ownsColorTexture) {\n const texHandle = gl.createTexture();\n if (texHandle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null (render target color)\");\n }\n createdTexture = texHandle;\n rt.texture.handle = texHandle;\n bindTextureForUpload(engine, texHandle);\n gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, c.minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, c.magFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, c.wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, c.wrapT);\n rt.texture.isReady = true;\n rt.texture._wasReady = true;\n }\n\n // ── Framebuffer + attachments ────────────────────────────────────────\n fb = gl.createFramebuffer();\n if (fb === null) {\n throw new Error(\"lite-gl: gl.createFramebuffer returned null\");\n }\n rt._framebuffer = fb;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rt.texture.handle, 0);\n\n // ── Depth (core, DEPTH-ONLY) ─────────────────────────────────────────\n // The core only ever builds a DEPTH_COMPONENT16 depth buffer. Stencil /\n // packed depth-stencil is an opt-in installed by\n // `generateRenderTargetStencil` (`@babylonjs/lite-gl`),\n // which sets `_rebuildDepthStencil` to a closure that REPLACES the\n // depth-only buffer below with its own packed/stencil renderbuffer. That\n // hook is re-run here on every rebuild (create / resize / context-restore)\n // so a helper-added stencil attachment survives at the new size.\n rt._depthStencil = null;\n if (c.hasDepth) {\n rb = gl.createRenderbuffer();\n if (rb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null\");\n }\n gl.bindRenderbuffer(gl.RENDERBUFFER, rb);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rt.width, rt.height);\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);\n gl.bindRenderbuffer(gl.RENDERBUFFER, null);\n rt._depthStencil = rb;\n }\n // A helper-attached stencil replaces/augments the depth-only buffer.\n rt._rebuildDepthStencil?.(engine);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete (status 0x${status.toString(16)})`);\n }\n rt.isReady = true;\n } catch (e) {\n // Free whatever depth/stencil renderbuffer is currently attached. After a\n // `_rebuildDepthStencil` hook ran, `rt._depthStencil` may be a packed buffer\n // the hook swapped in (it deletes the core `rb` itself on success), so free\n // the live `rt._depthStencil` rather than the stale local `rb`.\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = null;\n if (fb !== null) {\n gl.deleteFramebuffer(fb);\n }\n rt._framebuffer = null;\n // Delete ONLY a texture we created here (owned). Never a BYO texture.\n if (createdTexture !== null) {\n gl.deleteTexture(createdTexture);\n rt.texture.handle = null as unknown as WebGLTexture;\n rt.texture.isReady = false;\n }\n rt.isReady = false;\n throw e;\n } finally {\n // Restore the previously-bound draw target — creation/restore must not\n // silently redirect subsequent draws.\n if (s.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFb);\n s.boundFramebuffer = prevFb;\n }\n }\n}\n\n/** Inline cached `gl.viewport` — kept local so the render-target module has\n * no runtime dependency on the effect-renderer module. */\nfunction setViewportCached(engine: GLEngineContext, x: number, y: number, w: number, h: number): void {\n const s = engine._state;\n if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {\n return;\n }\n s.viewportX = x;\n s.viewportY = y;\n s.viewportW = w;\n s.viewportH = h;\n engine.gl.viewport(x, y, w, h);\n}\n"]}
|
package/scissor.d.ts
CHANGED
|
@@ -1,72 +1,30 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */
|
|
32
|
-
readonly textureHalfFloatLinearFiltering: boolean;
|
|
33
|
-
/** Whether non-power-of-two textures need POT dimensions for mips / wrap.
|
|
34
|
-
* Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */
|
|
35
|
-
readonly needPOTTextures: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Pure-state handle for a WebGL2 canvas + its cached GL state.
|
|
40
|
-
*
|
|
41
|
-
* INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.
|
|
42
|
-
* Doing so silently corrupts the cache in `_state`. The package owns every
|
|
43
|
-
* GL call. (`engine.gl` is exposed only so downstream code that already has the
|
|
44
|
-
* pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT
|
|
45
|
-
* call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)
|
|
46
|
-
*/
|
|
47
|
-
declare interface GLEngineContext {
|
|
48
|
-
/** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is
|
|
49
|
-
* supported for worker render paths (e.g. the Lottie player); it has no CSS
|
|
50
|
-
* box, so it must be sized explicitly via `setGLEngineSize` rather than the
|
|
51
|
-
* CSS-derived `resizeGLEngine`. */
|
|
52
|
-
readonly canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
53
|
-
/** The raw WebGL2 context. Do NOT mutate GL state through it — see the
|
|
54
|
-
* type-level invariant above; the package owns every state-changing call. */
|
|
55
|
-
readonly gl: WebGL2RenderingContext;
|
|
56
|
-
/** Queried capability limits for this context. */
|
|
57
|
-
readonly caps: GLEngineCaps;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Enable the scissor test and set the clip rectangle (lower-left origin),
|
|
61
|
-
* cached. Re-issues `gl.scissor` only when the rectangle changes, and
|
|
62
|
-
* `gl.enable(SCISSOR_TEST)` only on the disabled→enabled transition.
|
|
63
|
-
*
|
|
64
|
-
* @param engine - The engine.
|
|
65
|
-
* @param x - Lower-left X of the scissor rectangle, in pixels.
|
|
66
|
-
* @param y - Lower-left Y of the scissor rectangle, in pixels.
|
|
67
|
-
* @param width - Rectangle width in pixels.
|
|
68
|
-
* @param height - Rectangle height in pixels.
|
|
69
|
-
*/
|
|
70
|
-
export declare function setScissor(engine: GLEngineContext, x: number, y: number, width: number, height: number): void;
|
|
71
|
-
|
|
72
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* Scissor-test state — the lite-gl counterpart of Babylon's
|
|
3
|
+
* `engine.enableScissor` / `disableScissor` (and the raw `gl.scissor` Babylon
|
|
4
|
+
* issues for clip rects). Cached in `GLState`.
|
|
5
|
+
*
|
|
6
|
+
* Coordinates are raw WebGL (lower-left origin). A consumer using a top-left
|
|
7
|
+
* coordinate convention (like ShapeBuilder) flips Y itself
|
|
8
|
+
* (`viewportHeight - rect.bottom`) before calling, exactly as it did against
|
|
9
|
+
* Babylon's `ThinEngine`.
|
|
10
|
+
*/
|
|
11
|
+
import type { GLEngineContext } from "./context.js";
|
|
12
|
+
/**
|
|
13
|
+
* Enable the scissor test and set the clip rectangle (lower-left origin),
|
|
14
|
+
* cached. Re-issues `gl.scissor` only when the rectangle changes, and
|
|
15
|
+
* `gl.enable(SCISSOR_TEST)` only on the disabled→enabled transition.
|
|
16
|
+
*
|
|
17
|
+
* @param engine - The engine.
|
|
18
|
+
* @param x - Lower-left X of the scissor rectangle, in pixels.
|
|
19
|
+
* @param y - Lower-left Y of the scissor rectangle, in pixels.
|
|
20
|
+
* @param width - Rectangle width in pixels.
|
|
21
|
+
* @param height - Rectangle height in pixels.
|
|
22
|
+
*/
|
|
23
|
+
export declare function setScissor(engine: GLEngineContext, x: number, y: number, width: number, height: number): void;
|
|
24
|
+
/**
|
|
25
|
+
* Disable the scissor test (`gl.disable(SCISSOR_TEST)`), cached. Repeated calls
|
|
26
|
+
* after the first are elided.
|
|
27
|
+
*
|
|
28
|
+
* @param engine - The engine.
|
|
29
|
+
*/
|
|
30
|
+
export declare function disableScissor(engine: GLEngineContext): void;
|
package/scissor.js
CHANGED
|
@@ -1,35 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
/** GL `gl.SCISSOR_TEST`. */
|
|
2
|
+
const SCISSOR_TEST = 0x0c11;
|
|
3
|
+
/**
|
|
4
|
+
* Enable the scissor test and set the clip rectangle (lower-left origin),
|
|
5
|
+
* cached. Re-issues `gl.scissor` only when the rectangle changes, and
|
|
6
|
+
* `gl.enable(SCISSOR_TEST)` only on the disabled→enabled transition.
|
|
7
|
+
*
|
|
8
|
+
* @param engine - The engine.
|
|
9
|
+
* @param x - Lower-left X of the scissor rectangle, in pixels.
|
|
10
|
+
* @param y - Lower-left Y of the scissor rectangle, in pixels.
|
|
11
|
+
* @param width - Rectangle width in pixels.
|
|
12
|
+
* @param height - Rectangle height in pixels.
|
|
13
|
+
*/
|
|
14
|
+
export function setScissor(engine, x, y, width, height) {
|
|
15
|
+
if (engine._isLost || engine._disposed) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const gl = engine.gl;
|
|
19
|
+
const s = engine._state;
|
|
20
|
+
if (s.scissorEnabled !== 1) {
|
|
21
|
+
s.scissorEnabled = 1;
|
|
22
|
+
gl.enable(SCISSOR_TEST);
|
|
23
|
+
}
|
|
24
|
+
if (s.scissorX !== x || s.scissorY !== y || s.scissorW !== width || s.scissorH !== height) {
|
|
25
|
+
s.scissorX = x;
|
|
26
|
+
s.scissorY = y;
|
|
27
|
+
s.scissorW = width;
|
|
28
|
+
s.scissorH = height;
|
|
29
|
+
gl.scissor(x, y, width, height);
|
|
30
|
+
}
|
|
19
31
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Disable the scissor test (`gl.disable(SCISSOR_TEST)`), cached. Repeated calls
|
|
34
|
+
* after the first are elided.
|
|
35
|
+
*
|
|
36
|
+
* @param engine - The engine.
|
|
37
|
+
*/
|
|
38
|
+
export function disableScissor(engine) {
|
|
39
|
+
if (engine._isLost || engine._disposed) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const s = engine._state;
|
|
43
|
+
if (s.scissorEnabled === 0) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
s.scissorEnabled = 0;
|
|
47
|
+
engine.gl.disable(SCISSOR_TEST);
|
|
30
48
|
}
|
|
31
|
-
|
|
32
|
-
disableScissor,
|
|
33
|
-
setScissor
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=scissor.js.map
|
|
49
|
+
//# sourceMappingURL=scissor.js.map
|
package/scissor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scissor.js","sources":["../src/scissor.ts"],"sourcesContent":["/**\n * Scissor-test state — the lite-gl counterpart of Babylon's\n * `engine.enableScissor` / `disableScissor` (and the raw `gl.scissor` Babylon\n * issues for clip rects). Cached in `GLState`.\n *\n * Coordinates are raw WebGL (lower-left origin). A consumer using a top-left\n * coordinate convention (like ShapeBuilder) flips Y itself\n * (`viewportHeight - rect.bottom`) before calling, exactly as it did against\n * Babylon's `ThinEngine`.\n */\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.SCISSOR_TEST`. */\nconst SCISSOR_TEST = 0x0c11;\n\n/**\n * Enable the scissor test and set the clip rectangle (lower-left origin),\n * cached. Re-issues `gl.scissor` only when the rectangle changes, and\n * `gl.enable(SCISSOR_TEST)` only on the disabled→enabled transition.\n *\n * @param engine - The engine.\n * @param x - Lower-left X of the scissor rectangle, in pixels.\n * @param y - Lower-left Y of the scissor rectangle, in pixels.\n * @param width - Rectangle width in pixels.\n * @param height - Rectangle height in pixels.\n */\nexport function setScissor(engine: GLEngineContext, x: number, y: number, width: number, height: number): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.scissorEnabled !== 1) {\n s.scissorEnabled = 1;\n gl.enable(SCISSOR_TEST);\n }\n if (s.scissorX !== x || s.scissorY !== y || s.scissorW !== width || s.scissorH !== height) {\n s.scissorX = x;\n s.scissorY = y;\n s.scissorW = width;\n s.scissorH = height;\n gl.scissor(x, y, width, height);\n }\n}\n\n/**\n * Disable the scissor test (`gl.disable(SCISSOR_TEST)`), cached. Repeated calls\n * after the first are elided.\n *\n * @param engine - The engine.\n */\nexport function disableScissor(engine: GLEngineContext): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (s.scissorEnabled === 0) {\n return;\n }\n s.scissorEnabled = 0;\n engine.gl.disable(SCISSOR_TEST);\n}\n"]
|
|
1
|
+
{"version":3,"file":"scissor.js","sourceRoot":"","sources":["../src/scissor.ts"],"names":[],"mappings":"AAYA,4BAA4B;AAC5B,MAAM,YAAY,GAAG,MAAM,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,MAAuB,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc;IACnG,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;QACrB,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxF,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC;QACpB,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAuB;IAClD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;IACX,CAAC;IACD,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AACpC,CAAC","sourcesContent":["/**\n * Scissor-test state — the lite-gl counterpart of Babylon's\n * `engine.enableScissor` / `disableScissor` (and the raw `gl.scissor` Babylon\n * issues for clip rects). Cached in `GLState`.\n *\n * Coordinates are raw WebGL (lower-left origin). A consumer using a top-left\n * coordinate convention (like ShapeBuilder) flips Y itself\n * (`viewportHeight - rect.bottom`) before calling, exactly as it did against\n * Babylon's `ThinEngine`.\n */\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.SCISSOR_TEST`. */\nconst SCISSOR_TEST = 0x0c11;\n\n/**\n * Enable the scissor test and set the clip rectangle (lower-left origin),\n * cached. Re-issues `gl.scissor` only when the rectangle changes, and\n * `gl.enable(SCISSOR_TEST)` only on the disabled→enabled transition.\n *\n * @param engine - The engine.\n * @param x - Lower-left X of the scissor rectangle, in pixels.\n * @param y - Lower-left Y of the scissor rectangle, in pixels.\n * @param width - Rectangle width in pixels.\n * @param height - Rectangle height in pixels.\n */\nexport function setScissor(engine: GLEngineContext, x: number, y: number, width: number, height: number): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.scissorEnabled !== 1) {\n s.scissorEnabled = 1;\n gl.enable(SCISSOR_TEST);\n }\n if (s.scissorX !== x || s.scissorY !== y || s.scissorW !== width || s.scissorH !== height) {\n s.scissorX = x;\n s.scissorY = y;\n s.scissorW = width;\n s.scissorH = height;\n gl.scissor(x, y, width, height);\n }\n}\n\n/**\n * Disable the scissor test (`gl.disable(SCISSOR_TEST)`), cached. Repeated calls\n * after the first are elided.\n *\n * @param engine - The engine.\n */\nexport function disableScissor(engine: GLEngineContext): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (s.scissorEnabled === 0) {\n return;\n }\n s.scissorEnabled = 0;\n engine.gl.disable(SCISSOR_TEST);\n}\n"]}
|
package/shader.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shader / program compilation helpers. Pure functions — they take a raw
|
|
3
|
+
* `WebGL2RenderingContext` and never touch the cache layer. Used by
|
|
4
|
+
* `effect.ts` during `createEffect` and during the context-restored
|
|
5
|
+
* re-compile path.
|
|
6
|
+
*/
|
|
7
|
+
/** Compile a single shader stage. Returns the shader handle; sets the
|
|
8
|
+
* `errorOut` array's element 0 to a non-null string on failure. */
|
|
9
|
+
export declare function compileShader(gl: WebGL2RenderingContext, source: string, stage: GLenum, errorOut: (string | null)[]): WebGLShader | null;
|
|
10
|
+
/** Attach + bind + link. Returns the program handle. Does NOT block on
|
|
11
|
+
* link completion — callers use `pollLinkStatus` to drive the parallel-
|
|
12
|
+
* shader-compile state machine. */
|
|
13
|
+
export declare function linkProgram(gl: WebGL2RenderingContext, vs: WebGLShader, fs: WebGLShader, attributeNames: readonly string[]): WebGLProgram | null;
|
|
14
|
+
/** Returns `true` when the program has finished linking and can be queried.
|
|
15
|
+
* When the `KHR_parallel_shader_compile` extension is present, this is the
|
|
16
|
+
* cheap async-friendly poll; without it, link is synchronous so the answer
|
|
17
|
+
* is always `true`. */
|
|
18
|
+
export declare function isLinkComplete(gl: WebGL2RenderingContext, program: WebGLProgram, parallel: {
|
|
19
|
+
COMPLETION_STATUS_KHR: number;
|
|
20
|
+
} | null): boolean;
|
|
21
|
+
/** Returns null on success, the info log on failure. */
|
|
22
|
+
export declare function getLinkError(gl: WebGL2RenderingContext, program: WebGLProgram): string | null;
|
package/shader.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shader / program compilation helpers. Pure functions — they take a raw
|
|
3
|
+
* `WebGL2RenderingContext` and never touch the cache layer. Used by
|
|
4
|
+
* `effect.ts` during `createEffect` and during the context-restored
|
|
5
|
+
* re-compile path.
|
|
6
|
+
*/
|
|
7
|
+
/** Compile a single shader stage. Returns the shader handle; sets the
|
|
8
|
+
* `errorOut` array's element 0 to a non-null string on failure. */
|
|
9
|
+
export function compileShader(gl, source, stage, errorOut) {
|
|
10
|
+
const shader = gl.createShader(stage);
|
|
11
|
+
if (shader === null) {
|
|
12
|
+
errorOut[0] = "gl.createShader returned null";
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
gl.shaderSource(shader, source);
|
|
16
|
+
gl.compileShader(shader);
|
|
17
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
18
|
+
errorOut[0] = gl.getShaderInfoLog(shader) ?? "shader compile failed";
|
|
19
|
+
gl.deleteShader(shader);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return shader;
|
|
23
|
+
}
|
|
24
|
+
/** Attach + bind + link. Returns the program handle. Does NOT block on
|
|
25
|
+
* link completion — callers use `pollLinkStatus` to drive the parallel-
|
|
26
|
+
* shader-compile state machine. */
|
|
27
|
+
export function linkProgram(gl, vs, fs, attributeNames) {
|
|
28
|
+
const program = gl.createProgram();
|
|
29
|
+
if (program === null) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
gl.attachShader(program, vs);
|
|
33
|
+
gl.attachShader(program, fs);
|
|
34
|
+
// Bind every declared attribute, but in particular guarantee that the FIRST
|
|
35
|
+
// attribute (`position`) maps to location 0 — the shared fullscreen-quad VAO
|
|
36
|
+
// depends on this so the same VAO works across every effect's program.
|
|
37
|
+
// Must run BEFORE linkProgram. The GLSL conversion also emits
|
|
38
|
+
// `layout(location = N)` as belt-and-suspenders.
|
|
39
|
+
for (let i = 0; i < attributeNames.length; i++) {
|
|
40
|
+
const name = attributeNames[i];
|
|
41
|
+
if (name !== undefined) {
|
|
42
|
+
gl.bindAttribLocation(program, i, name);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
gl.linkProgram(program);
|
|
46
|
+
return program;
|
|
47
|
+
}
|
|
48
|
+
/** Returns `true` when the program has finished linking and can be queried.
|
|
49
|
+
* When the `KHR_parallel_shader_compile` extension is present, this is the
|
|
50
|
+
* cheap async-friendly poll; without it, link is synchronous so the answer
|
|
51
|
+
* is always `true`. */
|
|
52
|
+
export function isLinkComplete(gl, program, parallel) {
|
|
53
|
+
if (parallel === null) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return Boolean(gl.getProgramParameter(program, parallel.COMPLETION_STATUS_KHR));
|
|
57
|
+
}
|
|
58
|
+
/** Returns null on success, the info log on failure. */
|
|
59
|
+
export function getLinkError(gl, program) {
|
|
60
|
+
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return gl.getProgramInfoLog(program) ?? "link failed";
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=shader.js.map
|
package/shader.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader.js","sourceRoot":"","sources":["../src/shader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;oEACoE;AACpE,MAAM,UAAU,aAAa,CAAC,EAA0B,EAAE,MAAc,EAAE,KAAa,EAAE,QAA2B;IAChH,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClB,QAAQ,CAAC,CAAC,CAAC,GAAG,+BAA+B,CAAC;QAC9C,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;QACpD,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC;QACrE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;oCAEoC;AACpC,MAAM,UAAU,WAAW,CAAC,EAA0B,EAAE,EAAe,EAAE,EAAe,EAAE,cAAiC;IACvH,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IACnC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7B,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7B,4EAA4E;IAC5E,6EAA6E;IAC7E,uEAAuE;IACvE,8DAA8D;IAC9D,iDAAiD;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IACD,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;wBAGwB;AACxB,MAAM,UAAU,cAAc,CAAC,EAA0B,EAAE,OAAqB,EAAE,QAAkD;IAChI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,OAAO,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,EAA0B,EAAE,OAAqB;IAC1E,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC;AAC1D,CAAC","sourcesContent":["/**\n * Shader / program compilation helpers. Pure functions — they take a raw\n * `WebGL2RenderingContext` and never touch the cache layer. Used by\n * `effect.ts` during `createEffect` and during the context-restored\n * re-compile path.\n */\n\n/** Compile a single shader stage. Returns the shader handle; sets the\n * `errorOut` array's element 0 to a non-null string on failure. */\nexport function compileShader(gl: WebGL2RenderingContext, source: string, stage: GLenum, errorOut: (string | null)[]): WebGLShader | null {\n const shader = gl.createShader(stage);\n if (shader === null) {\n errorOut[0] = \"gl.createShader returned null\";\n return null;\n }\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n errorOut[0] = gl.getShaderInfoLog(shader) ?? \"shader compile failed\";\n gl.deleteShader(shader);\n return null;\n }\n return shader;\n}\n\n/** Attach + bind + link. Returns the program handle. Does NOT block on\n * link completion — callers use `pollLinkStatus` to drive the parallel-\n * shader-compile state machine. */\nexport function linkProgram(gl: WebGL2RenderingContext, vs: WebGLShader, fs: WebGLShader, attributeNames: readonly string[]): WebGLProgram | null {\n const program = gl.createProgram();\n if (program === null) {\n return null;\n }\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n // Bind every declared attribute, but in particular guarantee that the FIRST\n // attribute (`position`) maps to location 0 — the shared fullscreen-quad VAO\n // depends on this so the same VAO works across every effect's program.\n // Must run BEFORE linkProgram. The GLSL conversion also emits\n // `layout(location = N)` as belt-and-suspenders.\n for (let i = 0; i < attributeNames.length; i++) {\n const name = attributeNames[i];\n if (name !== undefined) {\n gl.bindAttribLocation(program, i, name);\n }\n }\n gl.linkProgram(program);\n return program;\n}\n\n/** Returns `true` when the program has finished linking and can be queried.\n * When the `KHR_parallel_shader_compile` extension is present, this is the\n * cheap async-friendly poll; without it, link is synchronous so the answer\n * is always `true`. */\nexport function isLinkComplete(gl: WebGL2RenderingContext, program: WebGLProgram, parallel: { COMPLETION_STATUS_KHR: number } | null): boolean {\n if (parallel === null) {\n return true;\n }\n return Boolean(gl.getProgramParameter(program, parallel.COMPLETION_STATUS_KHR));\n}\n\n/** Returns null on success, the info log on failure. */\nexport function getLinkError(gl: WebGL2RenderingContext, program: WebGLProgram): string | null {\n if (gl.getProgramParameter(program, gl.LINK_STATUS)) {\n return null;\n }\n return gl.getProgramInfoLog(program) ?? \"link failed\";\n}\n"]}
|