@babylonjs/lite-gl 0.1.0 → 0.2.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 -34
- 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 +233 -290
- package/render-target.js +534 -335
- 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/depth-stencil.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"depth-stencil.js","sources":["../src/depth-stencil.ts"],"sourcesContent":["/**\n * Depth, stencil, color-mask and clear state — the lite-gl counterpart of\n * Babylon's `_depthCullingState` / `_stencilState` / `setColorWrite` / `clear`.\n *\n * Like Babylon, these setters are DEFERRED: they buffer the requested values\n * into the DESIRED (`d*`) mirror fields of `GLState` and raise `statesDirty`,\n * issuing NO `gl.*` calls themselves. `applyGLStates` (apply-states.ts) flushes\n * the diff to GL right before each draw (and before `clearEngine`'s `gl.clear`,\n * since a clear respects the current write masks). Every field is reconciled\n * independently, so a flush that changes only one sub-state (e.g. just the\n * stencil op triple) issues only that GL call. Omitted setter fields leave the\n * corresponding desired value untouched (merge-from-desired).\n *\n * All setters are no-ops on a lost/disposed context.\n *\n * This module also hosts {@link generateRenderTargetStencil} — the tree-shakeable\n * opt-in that gives a `/render-target` {@link GLRenderTarget} a stencil (or packed\n * depth+stencil) attachment. Keeping the STENCIL_INDEX8 / DEPTH24_STENCIL8\n * renderbuffer code here (rather than in the render-target core) means a consumer\n * that only needs a depth buffer never ships it. The one-way type import below\n * (`depth-stencil` importing `render-target`) introduces NO cycle: render-target\n * must not import this module.\n */\nimport type { GLEngineContext } from \"./context.js\";\nimport type { GLRenderTarget } from \"./render-target.js\";\nimport { applyGLStates } from \"./apply-states.js\";\nimport {\n RS_CLEAR_A,\n RS_CLEAR_B,\n RS_CLEAR_G,\n RS_CLEAR_R,\n RS_COLOR_MASK,\n RS_CULL_ENABLED,\n RS_CULL_FACE,\n RS_DEPTH_FUNC,\n RS_DEPTH_MASK,\n RS_DEPTH_TEST,\n RS_DESIRED,\n RS_STENCIL_FUNC_FUNC,\n RS_STENCIL_FUNC_MASK,\n RS_STENCIL_FUNC_REF,\n RS_STENCIL_MASK,\n RS_STENCIL_OP_FAIL,\n RS_STENCIL_OP_ZFAIL,\n RS_STENCIL_OP_ZPASS,\n RS_STENCIL_TEST,\n} from \"./state.js\";\n\n// ── Clear bits (used by `clearEngine`).\n/** GL clear bits. */\nconst COLOR_BUFFER_BIT = 0x4000;\nconst DEPTH_BUFFER_BIT = 0x0100;\nconst STENCIL_BUFFER_BIT = 0x0400;\n\n// ── Test-enable enums for the per-category reconcilers below.\n/** GL `gl.DEPTH_TEST`. */\nconst DEPTH_TEST = 0x0b71;\n/** GL `gl.CULL_FACE`. */\nconst CULL_FACE = 0x0b44;\n/** GL `gl.STENCIL_TEST`. */\nconst STENCIL_TEST = 0x0b90;\n\n// ── Framebuffer / renderbuffer enums (used only by generateRenderTargetStencil).\n// Module-local consts mirror render-target.ts's constant style. Because the\n// render-target core no longer references the stencil/packed enums, they live\n// here and tree-shake away for consumers that never opt into a stencil buffer.\n/** GL `gl.FRAMEBUFFER`. */\nconst FRAMEBUFFER = 0x8d40;\n/** GL `gl.RENDERBUFFER`. */\nconst RENDERBUFFER = 0x8d41;\n/** GL `gl.DEPTH24_STENCIL8` — packed depth+stencil sized format. */\nconst DEPTH24_STENCIL8 = 0x88f0;\n/** GL `gl.STENCIL_INDEX8` — stencil-only sized format. */\nconst STENCIL_INDEX8 = 0x8d48;\n/** GL `gl.DEPTH_STENCIL_ATTACHMENT`. */\nconst DEPTH_STENCIL_ATTACHMENT = 0x821a;\n/** GL `gl.STENCIL_ATTACHMENT`. */\nconst STENCIL_ATTACHMENT = 0x8d20;\n/** GL `gl.DEPTH_ATTACHMENT` — where the render-target core attaches its depth-only\n * renderbuffer (re-established when rolling back a failed stencil attach). */\nconst DEPTH_ATTACHMENT = 0x8d00;\n/** GL `gl.FRAMEBUFFER_COMPLETE`. */\nconst FRAMEBUFFER_COMPLETE = 0x8cd5;\n\n/** Depth-buffer configuration for {@link setDepthState}. Omitted fields are\n * left unchanged. */\nexport interface GLDepthState {\n /** Enable/disable the depth test (`gl.enable/disable(DEPTH_TEST)`). */\n test?: boolean;\n /** Enable/disable depth writes (`gl.depthMask`). */\n write?: boolean;\n /** Depth comparison function (`gl.depthFunc`), e.g. `gl.LESS`. */\n func?: GLenum;\n}\n\n/** Stencil configuration for {@link setStencilState}. Omitted fields are left\n * unchanged. The `func`/`ref`/`funcMask` triple and the\n * `opFail`/`opZFail`/`opZPass` triple are each applied as a unit (any member\n * present re-issues that GL call, merging the unspecified members from cache). */\nexport interface GLStencilState {\n /** Enable/disable the stencil test (`gl.enable/disable(STENCIL_TEST)`). */\n test?: boolean;\n /** Stencil write mask (`gl.stencilMask`). */\n mask?: number;\n /** Comparison function (`gl.stencilFunc` arg 1), e.g. `gl.ALWAYS`. */\n func?: GLenum;\n /** Reference value (`gl.stencilFunc` arg 2). */\n ref?: number;\n /** Comparison mask (`gl.stencilFunc` arg 3). */\n funcMask?: number;\n /** Op when the stencil test fails (`gl.stencilOp` arg 1). */\n opFail?: GLenum;\n /** Op when the stencil test passes but depth fails (`gl.stencilOp` arg 2). */\n opZFail?: GLenum;\n /** Op when both stencil and depth pass (`gl.stencilOp` arg 3). */\n opZPass?: GLenum;\n}\n\n/** Options for {@link clearEngine}. */\nexport interface GLClearOptions {\n /** When set, clears the color buffer to this RGBA color (alpha default 1). */\n color?: { r: number; g: number; b: number; a?: number };\n /** Clear the depth buffer (respects the current depth write mask). */\n depth?: boolean;\n /** Clear the stencil buffer (respects the current stencil write mask). */\n stencil?: boolean;\n}\n\n/**\n * Buffer depth-buffer state (test enable, write mask, comparison function) into\n * the DESIRED state — the lite-gl equivalent of mutating Babylon's\n * `engine.depthCullingState.{depthTest,depthMask,depthFunc}`. Flushed to GL by\n * `applyGLStates` before the next draw / clear; omitted fields are untouched.\n *\n * @param engine - The engine.\n * @param state - The depth fields to change. Omitted fields are untouched.\n */\nexport function setDepthState(engine: GLEngineContext, state: GLDepthState): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (state.test !== undefined) {\n s.rs[RS_DEPTH_TEST + RS_DESIRED] = state.test ? 1 : 0;\n }\n if (state.write !== undefined) {\n s.rs[RS_DEPTH_MASK + RS_DESIRED] = state.write ? 1 : 0;\n }\n if (state.func !== undefined) {\n s.rs[RS_DEPTH_FUNC + RS_DESIRED] = state.func;\n }\n s._flushDepthCull = flushDepthCull;\n s.statesDirty = true;\n}\n\n/**\n * Enable/disable face culling and (optionally) set the cull face — the lite-gl\n * equivalent of `engine.depthCullingState.cull` + `cullFace`.\n *\n * @param engine - The engine.\n * @param enabled - Enable (`true`) or disable (`false`) `gl.CULL_FACE`.\n * @param face - Optional cull face (`gl.BACK` / `gl.FRONT` / `gl.FRONT_AND_BACK`).\n */\nexport function setCullState(engine: GLEngineContext, enabled: boolean, face?: GLenum): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n s.rs[RS_CULL_ENABLED + RS_DESIRED] = enabled ? 1 : 0;\n if (face !== undefined) {\n s.rs[RS_CULL_FACE + RS_DESIRED] = face;\n }\n s._flushDepthCull = flushDepthCull;\n s.statesDirty = true;\n}\n\n/**\n * Buffer stencil state (test enable, write mask, comparison func triple, op\n * triple) into the DESIRED state — the lite-gl equivalent of mutating Babylon's\n * `engine.stencilState.*`. Flushed by `applyGLStates` before the next draw /\n * clear; omitted fields are untouched (merge-from-desired).\n *\n * @param engine - The engine.\n * @param state - The stencil fields to change. Omitted fields are untouched.\n */\nexport function setStencilState(engine: GLEngineContext, state: GLStencilState): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (state.test !== undefined) {\n s.rs[RS_STENCIL_TEST + RS_DESIRED] = state.test ? 1 : 0;\n }\n if (state.mask !== undefined) {\n s.rs[RS_STENCIL_MASK + RS_DESIRED] = state.mask;\n }\n if (state.func !== undefined) {\n s.rs[RS_STENCIL_FUNC_FUNC + RS_DESIRED] = state.func;\n }\n if (state.ref !== undefined) {\n s.rs[RS_STENCIL_FUNC_REF + RS_DESIRED] = state.ref;\n }\n if (state.funcMask !== undefined) {\n s.rs[RS_STENCIL_FUNC_MASK + RS_DESIRED] = state.funcMask;\n }\n if (state.opFail !== undefined) {\n s.rs[RS_STENCIL_OP_FAIL + RS_DESIRED] = state.opFail;\n }\n if (state.opZFail !== undefined) {\n s.rs[RS_STENCIL_OP_ZFAIL + RS_DESIRED] = state.opZFail;\n }\n if (state.opZPass !== undefined) {\n s.rs[RS_STENCIL_OP_ZPASS + RS_DESIRED] = state.opZPass;\n }\n s._flushStencil = flushStencil;\n s.statesDirty = true;\n}\n\n/**\n * Buffer the color write mask into the DESIRED state — the lite-gl equivalent of\n * Babylon's `setColorWrite` (which passes the same flag to all four channels).\n * Flushed to GL (`gl.colorMask`) by `applyGLStates` before the next draw /\n * clear.\n *\n * @param engine - The engine.\n * @param r - Write red.\n * @param g - Write green.\n * @param b - Write blue.\n * @param a - Write alpha.\n */\nexport function setColorMask(engine: GLEngineContext, r: boolean, g: boolean, b: boolean, a: boolean): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const packed = (r ? 8 : 0) | (g ? 4 : 0) | (b ? 2 : 0) | (a ? 1 : 0);\n const s = engine._state;\n s.rs[RS_COLOR_MASK + RS_DESIRED] = packed;\n s._flushColorMask = flushColorMask;\n s.statesDirty = true;\n}\n\n/**\n * Clear the currently-bound framebuffer's color / depth / stencil buffers — the\n * lite-gl equivalent of Babylon's `clear(color, backBuffer, depth, stencil)`.\n * Depth/stencil clears respect the current write masks (set them first via\n * {@link setDepthState} / {@link setStencilState}). No-op when nothing is\n * requested or the context is lost/disposed.\n *\n * @param engine - The engine.\n * @param options - Which buffers to clear (and the color value).\n */\nexport function clearEngine(engine: GLEngineContext, options: GLClearOptions): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n let mask = 0;\n if (options.color !== undefined) {\n const c = options.color;\n const a = c.a ?? 1;\n const rs = engine._state.rs;\n // Cached: gl.clearColor is per-context state GL retains, so only re-issue\n // it when the requested color actually changes (Babylon re-sets it every\n // clear; this elides the redundant JS↔native call for constant backgrounds).\n if (rs[RS_CLEAR_R] !== c.r || rs[RS_CLEAR_G] !== c.g || rs[RS_CLEAR_B] !== c.b || rs[RS_CLEAR_A] !== a) {\n gl.clearColor(c.r, c.g, c.b, a);\n rs[RS_CLEAR_R] = c.r;\n rs[RS_CLEAR_G] = c.g;\n rs[RS_CLEAR_B] = c.b;\n rs[RS_CLEAR_A] = a;\n }\n mask |= COLOR_BUFFER_BIT;\n }\n if (options.depth === true) {\n mask |= DEPTH_BUFFER_BIT;\n }\n if (options.stencil === true) {\n mask |= STENCIL_BUFFER_BIT;\n }\n if (mask !== 0) {\n // Babylon parity: a clear respects the current depth/stencil/color write\n // masks, so flush any deferred state before clearing.\n applyGLStates(engine);\n gl.clear(mask);\n }\n}\n\n/* ─────────────────── deferred render-state reconcilers ──────────────────────\n * The per-category half of `applyGLStates`. Each setter above installs the\n * matching reconciler onto its `_state._flush*` slot; `applyGLStates`\n * (apply-states.ts) dispatches ONLY through those slots. Co-locating them with\n * their setters makes each one reachable solely when its setter is in the bundle,\n * so a scene that never touches depth/cull, stencil, or color-mask tree-shakes\n * the corresponding reconciler — and its GL code — away entirely. Each reconciles\n * its DESIRED (`rs[RS_X + RS_DESIRED]`) slots against the ACTUAL twins (`rs[RS_X]`)\n * and issues only the `gl.*` calls that changed, in the same order and with the\n * same elision rules as the former monolithic flush. */\n\n/** Reconcile depth + cull (Babylon's `_depthCullingState.apply`). @internal */\nfunction flushDepthCull(engine: GLEngineContext): void {\n const gl = engine.gl;\n const rs = engine._state.rs;\n const dTest = rs[RS_DEPTH_TEST + RS_DESIRED]!;\n if (dTest !== rs[RS_DEPTH_TEST]) {\n rs[RS_DEPTH_TEST] = dTest;\n if (dTest === 1) {\n gl.enable(DEPTH_TEST);\n } else {\n gl.disable(DEPTH_TEST);\n }\n }\n const dMask = rs[RS_DEPTH_MASK + RS_DESIRED]!;\n if (dMask !== rs[RS_DEPTH_MASK]) {\n rs[RS_DEPTH_MASK] = dMask;\n gl.depthMask(dMask === 1);\n }\n const dFunc = rs[RS_DEPTH_FUNC + RS_DESIRED]!;\n if (dFunc !== rs[RS_DEPTH_FUNC]) {\n rs[RS_DEPTH_FUNC] = dFunc;\n gl.depthFunc(dFunc);\n }\n const dCull = rs[RS_CULL_ENABLED + RS_DESIRED]!;\n if (dCull !== rs[RS_CULL_ENABLED]) {\n rs[RS_CULL_ENABLED] = dCull;\n if (dCull === 1) {\n gl.enable(CULL_FACE);\n } else {\n gl.disable(CULL_FACE);\n }\n }\n const dCullFace = rs[RS_CULL_FACE + RS_DESIRED]!;\n if (dCullFace !== rs[RS_CULL_FACE]) {\n rs[RS_CULL_FACE] = dCullFace;\n gl.cullFace(dCullFace);\n }\n}\n\n/** Reconcile the stencil test / mask / func-triple / op-triple (Babylon's\n * `_stencilState.apply`); each triple is issued as a unit. @internal */\nfunction flushStencil(engine: GLEngineContext): void {\n const gl = engine.gl;\n const rs = engine._state.rs;\n const dTest = rs[RS_STENCIL_TEST + RS_DESIRED]!;\n if (dTest !== rs[RS_STENCIL_TEST]) {\n rs[RS_STENCIL_TEST] = dTest;\n if (dTest === 1) {\n gl.enable(STENCIL_TEST);\n } else {\n gl.disable(STENCIL_TEST);\n }\n }\n const dMask = rs[RS_STENCIL_MASK + RS_DESIRED]!;\n if (dMask !== rs[RS_STENCIL_MASK]) {\n rs[RS_STENCIL_MASK] = dMask;\n gl.stencilMask(dMask);\n }\n const dFuncFunc = rs[RS_STENCIL_FUNC_FUNC + RS_DESIRED]!;\n const dFuncRef = rs[RS_STENCIL_FUNC_REF + RS_DESIRED]!;\n const dFuncMask = rs[RS_STENCIL_FUNC_MASK + RS_DESIRED]!;\n if (dFuncFunc !== rs[RS_STENCIL_FUNC_FUNC] || dFuncRef !== rs[RS_STENCIL_FUNC_REF] || dFuncMask !== rs[RS_STENCIL_FUNC_MASK]) {\n rs[RS_STENCIL_FUNC_FUNC] = dFuncFunc;\n rs[RS_STENCIL_FUNC_REF] = dFuncRef;\n rs[RS_STENCIL_FUNC_MASK] = dFuncMask;\n gl.stencilFunc(dFuncFunc, dFuncRef, dFuncMask);\n }\n const dOpFail = rs[RS_STENCIL_OP_FAIL + RS_DESIRED]!;\n const dOpZFail = rs[RS_STENCIL_OP_ZFAIL + RS_DESIRED]!;\n const dOpZPass = rs[RS_STENCIL_OP_ZPASS + RS_DESIRED]!;\n if (dOpFail !== rs[RS_STENCIL_OP_FAIL] || dOpZFail !== rs[RS_STENCIL_OP_ZFAIL] || dOpZPass !== rs[RS_STENCIL_OP_ZPASS]) {\n rs[RS_STENCIL_OP_FAIL] = dOpFail;\n rs[RS_STENCIL_OP_ZFAIL] = dOpZFail;\n rs[RS_STENCIL_OP_ZPASS] = dOpZPass;\n gl.stencilOp(dOpFail, dOpZFail, dOpZPass);\n }\n}\n\n/** Reconcile the packed color-write mask (Babylon's `setColorWrite`). @internal */\nfunction flushColorMask(engine: GLEngineContext): void {\n const rs = engine._state.rs;\n const dColorMask = rs[RS_COLOR_MASK + RS_DESIRED]!;\n if (dColorMask !== rs[RS_COLOR_MASK]) {\n rs[RS_COLOR_MASK] = dColorMask;\n engine.gl.colorMask((dColorMask & 8) !== 0, (dColorMask & 4) !== 0, (dColorMask & 2) !== 0, (dColorMask & 1) !== 0);\n }\n}\n\n/**\n * Opt-in: give a `/render-target` {@link GLRenderTarget} a stencil attachment,\n * replacing the core's depth-only `DEPTH_COMPONENT16` renderbuffer with either a\n * packed **`DEPTH24_STENCIL8`** buffer (default — depth *and* stencil) or a\n * stencil-only **`STENCIL_INDEX8`** buffer.\n *\n * Stencil is intentionally NOT a {@link createRenderTarget} option: keeping this\n * helper in the `/depth-stencil` sub-entry means the stencil/packed renderbuffer\n * code tree-shakes out of every bundle that only needs a color (and optional\n * depth) target.\n *\n * The attachment is **restore-correct**: it is rebuilt automatically — at the new\n * size on {@link resizeRenderTarget}, and into the fresh framebuffer after a\n * `webglcontextrestored` event — so the stencil survives for the life of the\n * target, and {@link disposeRenderTarget} releases it along with the target.\n *\n * No-op on a lost/disposed context or a disposed target.\n *\n * @param engine - The engine that owns `rt`.\n * @param rt - The render target to attach the stencil buffer to.\n * @param options - `depth` (default `true`): when `true` the attachment is a\n * packed depth+stencil buffer (`DEPTH24_STENCIL8` on `DEPTH_STENCIL_ATTACHMENT`)\n * — the common case, and the correct choice when the target was created with\n * `generateDepthBuffer: true`. When `false` the attachment is stencil-only\n * (`STENCIL_INDEX8` on `STENCIL_ATTACHMENT`).\n * @throws If a renderbuffer handle could not be allocated or the framebuffer is\n * incomplete after attaching.\n */\nexport function generateRenderTargetStencil(engine: GLEngineContext, rt: GLRenderTarget, options?: { depth?: boolean }): void {\n if (engine._isLost || engine._disposed || rt._disposed) {\n return;\n }\n const packDepth = options?.depth ?? true;\n const attachment = packDepth ? DEPTH_STENCIL_ATTACHMENT : STENCIL_ATTACHMENT;\n const format = packDepth ? DEPTH24_STENCIL8 : STENCIL_INDEX8;\n\n const build = (e: GLEngineContext): void => {\n const gl = e.gl;\n // Capture the caller's draw target so this helper is STATE-NEUTRAL: it must\n // not silently redirect subsequent draws to `rt` (during an internal\n // rebuild `prevFb` is `rt._framebuffer`, which the core re-checks next).\n const prevFb = e._state.boundFramebuffer;\n const newRb = gl.createRenderbuffer();\n if (newRb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null (render target stencil)\");\n }\n let committed = false;\n try {\n gl.bindFramebuffer(FRAMEBUFFER, rt._framebuffer);\n e._state.boundFramebuffer = rt._framebuffer;\n gl.bindRenderbuffer(RENDERBUFFER, newRb);\n gl.renderbufferStorage(RENDERBUFFER, format, rt.width, rt.height);\n gl.framebufferRenderbuffer(FRAMEBUFFER, attachment, RENDERBUFFER, newRb);\n gl.bindRenderbuffer(RENDERBUFFER, null);\n const status = gl.checkFramebufferStatus(FRAMEBUFFER);\n if (status !== FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete after stencil attach (status 0x${status.toString(16)})`);\n }\n // Commit only after a complete attachment: release the buffer we\n // replaced (the core depth-only one, or our own from a prior rebuild).\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = newRb;\n committed = true;\n } finally {\n if (!committed) {\n // Any non-committed exit (incomplete framebuffer OR an unexpected\n // GL throw): detach + delete the buffer we couldn't adopt so it\n // never leaks, leaving the attachment point empty for the\n // caller-level rollback to re-establish the prior buffer.\n gl.framebufferRenderbuffer(FRAMEBUFFER, attachment, RENDERBUFFER, null);\n gl.deleteRenderbuffer(newRb);\n }\n // Restore the caller's draw target + the bound-framebuffer cache.\n if (e._state.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(FRAMEBUFFER, prevFb);\n e._state.boundFramebuffer = prevFb;\n }\n }\n };\n\n // Build once now, but COMMIT the resize/restore hook only if it succeeds — a\n // failed opt-in must leave the target exactly as it was. The packed attach\n // above can clear the core `DEPTH_ATTACHMENT`, so on failure restore the prior\n // hook AND re-establish the prior depth/stencil attachment (the prior hook's,\n // or the core depth-only buffer).\n const prevHook = rt._rebuildDepthStencil;\n const prevDepthStencil = rt._depthStencil;\n try {\n build(engine);\n } catch (err) {\n rt._rebuildDepthStencil = prevHook;\n try {\n if (prevHook !== undefined) {\n prevHook(engine);\n } else if (prevDepthStencil !== null) {\n reattachCoreDepthBuffer(engine, rt, prevDepthStencil);\n }\n } catch {\n // Best-effort restore; surface the original failure below.\n }\n throw err;\n }\n rt._rebuildDepthStencil = build;\n}\n\n/**\n * Re-attach a core depth-only renderbuffer at `DEPTH_ATTACHMENT` — used to roll a\n * render target back when a packed {@link generateRenderTargetStencil} attach\n * fails completeness (attaching at `DEPTH_STENCIL_ATTACHMENT` clears the core\n * `DEPTH_ATTACHMENT`). State-neutral: restores the caller's bound framebuffer.\n * @internal\n */\nfunction reattachCoreDepthBuffer(engine: GLEngineContext, rt: GLRenderTarget, depthBuffer: WebGLRenderbuffer): void {\n const gl = engine.gl;\n const prevFb = engine._state.boundFramebuffer;\n gl.bindFramebuffer(FRAMEBUFFER, rt._framebuffer);\n engine._state.boundFramebuffer = rt._framebuffer;\n gl.framebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, depthBuffer);\n if (engine._state.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(FRAMEBUFFER, prevFb);\n engine._state.boundFramebuffer = prevFb;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"depth-stencil.js","sourceRoot":"","sources":["../src/depth-stencil.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Depth, stencil, color-mask and clear state — the lite-gl counterpart of\n * Babylon's `_depthCullingState` / `_stencilState` / `setColorWrite` / `clear`.\n *\n * Like Babylon, these setters are DEFERRED: they buffer the requested values\n * into the DESIRED (`d*`) mirror fields of `GLState` and raise `statesDirty`,\n * issuing NO `gl.*` calls themselves. `applyGLStates` (apply-states.ts) flushes\n * the diff to GL right before each draw (and before `clearEngine`'s `gl.clear`,\n * since a clear respects the current write masks). Every field is reconciled\n * independently, so a flush that changes only one sub-state (e.g. just the\n * stencil op triple) issues only that GL call. Omitted setter fields leave the\n * corresponding desired value untouched (merge-from-desired).\n *\n * All setters are no-ops on a lost/disposed context.\n *\n * This module also hosts {@link generateRenderTargetStencil} — the tree-shakeable\n * opt-in that gives a `/render-target` {@link GLRenderTarget} a stencil (or packed\n * depth+stencil) attachment. Keeping the STENCIL_INDEX8 / DEPTH24_STENCIL8\n * renderbuffer code here (rather than in the render-target core) means a consumer\n * that only needs a depth buffer never ships it. The one-way type import below\n * (`depth-stencil` importing `render-target`) introduces NO cycle: render-target\n * must not import this module.\n */\nimport type { GLEngineContext } from \"./context.js\";\nimport type { GLRenderTarget } from \"./render-target.js\";\nimport { applyGLStates } from \"./apply-states.js\";\nimport {\n RS_CLEAR_A,\n RS_CLEAR_B,\n RS_CLEAR_G,\n RS_CLEAR_R,\n RS_COLOR_MASK,\n RS_CULL_ENABLED,\n RS_CULL_FACE,\n RS_DEPTH_FUNC,\n RS_DEPTH_MASK,\n RS_DEPTH_TEST,\n RS_DESIRED,\n RS_STENCIL_FUNC_FUNC,\n RS_STENCIL_FUNC_MASK,\n RS_STENCIL_FUNC_REF,\n RS_STENCIL_MASK,\n RS_STENCIL_OP_FAIL,\n RS_STENCIL_OP_ZFAIL,\n RS_STENCIL_OP_ZPASS,\n RS_STENCIL_TEST,\n} from \"./state.js\";\n\n// ── Clear bits (used by `clearEngine`).\n/** GL clear bits. */\nconst COLOR_BUFFER_BIT = 0x4000;\nconst DEPTH_BUFFER_BIT = 0x0100;\nconst STENCIL_BUFFER_BIT = 0x0400;\n\n// ── Test-enable enums for the per-category reconcilers below.\n/** GL `gl.DEPTH_TEST`. */\nconst DEPTH_TEST = 0x0b71;\n/** GL `gl.CULL_FACE`. */\nconst CULL_FACE = 0x0b44;\n/** GL `gl.STENCIL_TEST`. */\nconst STENCIL_TEST = 0x0b90;\n\n// ── Framebuffer / renderbuffer enums (used only by generateRenderTargetStencil).\n// Module-local consts mirror render-target.ts's constant style. Because the\n// render-target core no longer references the stencil/packed enums, they live\n// here and tree-shake away for consumers that never opt into a stencil buffer.\n/** GL `gl.FRAMEBUFFER`. */\nconst FRAMEBUFFER = 0x8d40;\n/** GL `gl.RENDERBUFFER`. */\nconst RENDERBUFFER = 0x8d41;\n/** GL `gl.DEPTH24_STENCIL8` — packed depth+stencil sized format. */\nconst DEPTH24_STENCIL8 = 0x88f0;\n/** GL `gl.STENCIL_INDEX8` — stencil-only sized format. */\nconst STENCIL_INDEX8 = 0x8d48;\n/** GL `gl.DEPTH_STENCIL_ATTACHMENT`. */\nconst DEPTH_STENCIL_ATTACHMENT = 0x821a;\n/** GL `gl.STENCIL_ATTACHMENT`. */\nconst STENCIL_ATTACHMENT = 0x8d20;\n/** GL `gl.DEPTH_ATTACHMENT` — where the render-target core attaches its depth-only\n * renderbuffer (re-established when rolling back a failed stencil attach). */\nconst DEPTH_ATTACHMENT = 0x8d00;\n/** GL `gl.FRAMEBUFFER_COMPLETE`. */\nconst FRAMEBUFFER_COMPLETE = 0x8cd5;\n\n/** Depth-buffer configuration for {@link setDepthState}. Omitted fields are\n * left unchanged. */\nexport interface GLDepthState {\n /** Enable/disable the depth test (`gl.enable/disable(DEPTH_TEST)`). */\n test?: boolean;\n /** Enable/disable depth writes (`gl.depthMask`). */\n write?: boolean;\n /** Depth comparison function (`gl.depthFunc`), e.g. `gl.LESS`. */\n func?: GLenum;\n}\n\n/** Stencil configuration for {@link setStencilState}. Omitted fields are left\n * unchanged. The `func`/`ref`/`funcMask` triple and the\n * `opFail`/`opZFail`/`opZPass` triple are each applied as a unit (any member\n * present re-issues that GL call, merging the unspecified members from cache). */\nexport interface GLStencilState {\n /** Enable/disable the stencil test (`gl.enable/disable(STENCIL_TEST)`). */\n test?: boolean;\n /** Stencil write mask (`gl.stencilMask`). */\n mask?: number;\n /** Comparison function (`gl.stencilFunc` arg 1), e.g. `gl.ALWAYS`. */\n func?: GLenum;\n /** Reference value (`gl.stencilFunc` arg 2). */\n ref?: number;\n /** Comparison mask (`gl.stencilFunc` arg 3). */\n funcMask?: number;\n /** Op when the stencil test fails (`gl.stencilOp` arg 1). */\n opFail?: GLenum;\n /** Op when the stencil test passes but depth fails (`gl.stencilOp` arg 2). */\n opZFail?: GLenum;\n /** Op when both stencil and depth pass (`gl.stencilOp` arg 3). */\n opZPass?: GLenum;\n}\n\n/** Options for {@link clearEngine}. */\nexport interface GLClearOptions {\n /** When set, clears the color buffer to this RGBA color (alpha default 1). */\n color?: { r: number; g: number; b: number; a?: number };\n /** Clear the depth buffer (respects the current depth write mask). */\n depth?: boolean;\n /** Clear the stencil buffer (respects the current stencil write mask). */\n stencil?: boolean;\n}\n\n/**\n * Buffer depth-buffer state (test enable, write mask, comparison function) into\n * the DESIRED state — the lite-gl equivalent of mutating Babylon's\n * `engine.depthCullingState.{depthTest,depthMask,depthFunc}`. Flushed to GL by\n * `applyGLStates` before the next draw / clear; omitted fields are untouched.\n *\n * @param engine - The engine.\n * @param state - The depth fields to change. Omitted fields are untouched.\n */\nexport function setDepthState(engine: GLEngineContext, state: GLDepthState): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (state.test !== undefined) {\n s.rs[RS_DEPTH_TEST + RS_DESIRED] = state.test ? 1 : 0;\n }\n if (state.write !== undefined) {\n s.rs[RS_DEPTH_MASK + RS_DESIRED] = state.write ? 1 : 0;\n }\n if (state.func !== undefined) {\n s.rs[RS_DEPTH_FUNC + RS_DESIRED] = state.func;\n }\n s._flushDepthCull = flushDepthCull;\n s.statesDirty = true;\n}\n\n/**\n * Enable/disable face culling and (optionally) set the cull face — the lite-gl\n * equivalent of `engine.depthCullingState.cull` + `cullFace`.\n *\n * @param engine - The engine.\n * @param enabled - Enable (`true`) or disable (`false`) `gl.CULL_FACE`.\n * @param face - Optional cull face (`gl.BACK` / `gl.FRONT` / `gl.FRONT_AND_BACK`).\n */\nexport function setCullState(engine: GLEngineContext, enabled: boolean, face?: GLenum): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n s.rs[RS_CULL_ENABLED + RS_DESIRED] = enabled ? 1 : 0;\n if (face !== undefined) {\n s.rs[RS_CULL_FACE + RS_DESIRED] = face;\n }\n s._flushDepthCull = flushDepthCull;\n s.statesDirty = true;\n}\n\n/**\n * Buffer stencil state (test enable, write mask, comparison func triple, op\n * triple) into the DESIRED state — the lite-gl equivalent of mutating Babylon's\n * `engine.stencilState.*`. Flushed by `applyGLStates` before the next draw /\n * clear; omitted fields are untouched (merge-from-desired).\n *\n * @param engine - The engine.\n * @param state - The stencil fields to change. Omitted fields are untouched.\n */\nexport function setStencilState(engine: GLEngineContext, state: GLStencilState): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n if (state.test !== undefined) {\n s.rs[RS_STENCIL_TEST + RS_DESIRED] = state.test ? 1 : 0;\n }\n if (state.mask !== undefined) {\n s.rs[RS_STENCIL_MASK + RS_DESIRED] = state.mask;\n }\n if (state.func !== undefined) {\n s.rs[RS_STENCIL_FUNC_FUNC + RS_DESIRED] = state.func;\n }\n if (state.ref !== undefined) {\n s.rs[RS_STENCIL_FUNC_REF + RS_DESIRED] = state.ref;\n }\n if (state.funcMask !== undefined) {\n s.rs[RS_STENCIL_FUNC_MASK + RS_DESIRED] = state.funcMask;\n }\n if (state.opFail !== undefined) {\n s.rs[RS_STENCIL_OP_FAIL + RS_DESIRED] = state.opFail;\n }\n if (state.opZFail !== undefined) {\n s.rs[RS_STENCIL_OP_ZFAIL + RS_DESIRED] = state.opZFail;\n }\n if (state.opZPass !== undefined) {\n s.rs[RS_STENCIL_OP_ZPASS + RS_DESIRED] = state.opZPass;\n }\n s._flushStencil = flushStencil;\n s.statesDirty = true;\n}\n\n/**\n * Buffer the color write mask into the DESIRED state — the lite-gl equivalent of\n * Babylon's `setColorWrite` (which passes the same flag to all four channels).\n * Flushed to GL (`gl.colorMask`) by `applyGLStates` before the next draw /\n * clear.\n *\n * @param engine - The engine.\n * @param r - Write red.\n * @param g - Write green.\n * @param b - Write blue.\n * @param a - Write alpha.\n */\nexport function setColorMask(engine: GLEngineContext, r: boolean, g: boolean, b: boolean, a: boolean): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const packed = (r ? 8 : 0) | (g ? 4 : 0) | (b ? 2 : 0) | (a ? 1 : 0);\n const s = engine._state;\n s.rs[RS_COLOR_MASK + RS_DESIRED] = packed;\n s._flushColorMask = flushColorMask;\n s.statesDirty = true;\n}\n\n/**\n * Clear the currently-bound framebuffer's color / depth / stencil buffers — the\n * lite-gl equivalent of Babylon's `clear(color, backBuffer, depth, stencil)`.\n * Depth/stencil clears respect the current write masks (set them first via\n * {@link setDepthState} / {@link setStencilState}). No-op when nothing is\n * requested or the context is lost/disposed.\n *\n * @param engine - The engine.\n * @param options - Which buffers to clear (and the color value).\n */\nexport function clearEngine(engine: GLEngineContext, options: GLClearOptions): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n let mask = 0;\n if (options.color !== undefined) {\n const c = options.color;\n const a = c.a ?? 1;\n const rs = engine._state.rs;\n // Cached: gl.clearColor is per-context state GL retains, so only re-issue\n // it when the requested color actually changes (Babylon re-sets it every\n // clear; this elides the redundant JS↔native call for constant backgrounds).\n if (rs[RS_CLEAR_R] !== c.r || rs[RS_CLEAR_G] !== c.g || rs[RS_CLEAR_B] !== c.b || rs[RS_CLEAR_A] !== a) {\n gl.clearColor(c.r, c.g, c.b, a);\n rs[RS_CLEAR_R] = c.r;\n rs[RS_CLEAR_G] = c.g;\n rs[RS_CLEAR_B] = c.b;\n rs[RS_CLEAR_A] = a;\n }\n mask |= COLOR_BUFFER_BIT;\n }\n if (options.depth === true) {\n mask |= DEPTH_BUFFER_BIT;\n }\n if (options.stencil === true) {\n mask |= STENCIL_BUFFER_BIT;\n }\n if (mask !== 0) {\n // Babylon parity: a clear respects the current depth/stencil/color write\n // masks, so flush any deferred state before clearing.\n applyGLStates(engine);\n gl.clear(mask);\n }\n}\n\n/* ─────────────────── deferred render-state reconcilers ──────────────────────\n * The per-category half of `applyGLStates`. Each setter above installs the\n * matching reconciler onto its `_state._flush*` slot; `applyGLStates`\n * (apply-states.ts) dispatches ONLY through those slots. Co-locating them with\n * their setters makes each one reachable solely when its setter is in the bundle,\n * so a scene that never touches depth/cull, stencil, or color-mask tree-shakes\n * the corresponding reconciler — and its GL code — away entirely. Each reconciles\n * its DESIRED (`rs[RS_X + RS_DESIRED]`) slots against the ACTUAL twins (`rs[RS_X]`)\n * and issues only the `gl.*` calls that changed, in the same order and with the\n * same elision rules as the former monolithic flush. */\n\n/** Reconcile depth + cull (Babylon's `_depthCullingState.apply`). @internal */\nfunction flushDepthCull(engine: GLEngineContext): void {\n const gl = engine.gl;\n const rs = engine._state.rs;\n const dTest = rs[RS_DEPTH_TEST + RS_DESIRED]!;\n if (dTest !== rs[RS_DEPTH_TEST]) {\n rs[RS_DEPTH_TEST] = dTest;\n if (dTest === 1) {\n gl.enable(DEPTH_TEST);\n } else {\n gl.disable(DEPTH_TEST);\n }\n }\n const dMask = rs[RS_DEPTH_MASK + RS_DESIRED]!;\n if (dMask !== rs[RS_DEPTH_MASK]) {\n rs[RS_DEPTH_MASK] = dMask;\n gl.depthMask(dMask === 1);\n }\n const dFunc = rs[RS_DEPTH_FUNC + RS_DESIRED]!;\n if (dFunc !== rs[RS_DEPTH_FUNC]) {\n rs[RS_DEPTH_FUNC] = dFunc;\n gl.depthFunc(dFunc);\n }\n const dCull = rs[RS_CULL_ENABLED + RS_DESIRED]!;\n if (dCull !== rs[RS_CULL_ENABLED]) {\n rs[RS_CULL_ENABLED] = dCull;\n if (dCull === 1) {\n gl.enable(CULL_FACE);\n } else {\n gl.disable(CULL_FACE);\n }\n }\n const dCullFace = rs[RS_CULL_FACE + RS_DESIRED]!;\n if (dCullFace !== rs[RS_CULL_FACE]) {\n rs[RS_CULL_FACE] = dCullFace;\n gl.cullFace(dCullFace);\n }\n}\n\n/** Reconcile the stencil test / mask / func-triple / op-triple (Babylon's\n * `_stencilState.apply`); each triple is issued as a unit. @internal */\nfunction flushStencil(engine: GLEngineContext): void {\n const gl = engine.gl;\n const rs = engine._state.rs;\n const dTest = rs[RS_STENCIL_TEST + RS_DESIRED]!;\n if (dTest !== rs[RS_STENCIL_TEST]) {\n rs[RS_STENCIL_TEST] = dTest;\n if (dTest === 1) {\n gl.enable(STENCIL_TEST);\n } else {\n gl.disable(STENCIL_TEST);\n }\n }\n const dMask = rs[RS_STENCIL_MASK + RS_DESIRED]!;\n if (dMask !== rs[RS_STENCIL_MASK]) {\n rs[RS_STENCIL_MASK] = dMask;\n gl.stencilMask(dMask);\n }\n const dFuncFunc = rs[RS_STENCIL_FUNC_FUNC + RS_DESIRED]!;\n const dFuncRef = rs[RS_STENCIL_FUNC_REF + RS_DESIRED]!;\n const dFuncMask = rs[RS_STENCIL_FUNC_MASK + RS_DESIRED]!;\n if (dFuncFunc !== rs[RS_STENCIL_FUNC_FUNC] || dFuncRef !== rs[RS_STENCIL_FUNC_REF] || dFuncMask !== rs[RS_STENCIL_FUNC_MASK]) {\n rs[RS_STENCIL_FUNC_FUNC] = dFuncFunc;\n rs[RS_STENCIL_FUNC_REF] = dFuncRef;\n rs[RS_STENCIL_FUNC_MASK] = dFuncMask;\n gl.stencilFunc(dFuncFunc, dFuncRef, dFuncMask);\n }\n const dOpFail = rs[RS_STENCIL_OP_FAIL + RS_DESIRED]!;\n const dOpZFail = rs[RS_STENCIL_OP_ZFAIL + RS_DESIRED]!;\n const dOpZPass = rs[RS_STENCIL_OP_ZPASS + RS_DESIRED]!;\n if (dOpFail !== rs[RS_STENCIL_OP_FAIL] || dOpZFail !== rs[RS_STENCIL_OP_ZFAIL] || dOpZPass !== rs[RS_STENCIL_OP_ZPASS]) {\n rs[RS_STENCIL_OP_FAIL] = dOpFail;\n rs[RS_STENCIL_OP_ZFAIL] = dOpZFail;\n rs[RS_STENCIL_OP_ZPASS] = dOpZPass;\n gl.stencilOp(dOpFail, dOpZFail, dOpZPass);\n }\n}\n\n/** Reconcile the packed color-write mask (Babylon's `setColorWrite`). @internal */\nfunction flushColorMask(engine: GLEngineContext): void {\n const rs = engine._state.rs;\n const dColorMask = rs[RS_COLOR_MASK + RS_DESIRED]!;\n if (dColorMask !== rs[RS_COLOR_MASK]) {\n rs[RS_COLOR_MASK] = dColorMask;\n engine.gl.colorMask((dColorMask & 8) !== 0, (dColorMask & 4) !== 0, (dColorMask & 2) !== 0, (dColorMask & 1) !== 0);\n }\n}\n\n/**\n * Opt-in: give a `/render-target` {@link GLRenderTarget} a stencil attachment,\n * replacing the core's depth-only `DEPTH_COMPONENT16` renderbuffer with either a\n * packed **`DEPTH24_STENCIL8`** buffer (default — depth *and* stencil) or a\n * stencil-only **`STENCIL_INDEX8`** buffer.\n *\n * Stencil is intentionally NOT a {@link createRenderTarget} option: keeping this\n * helper in the depth-stencil module means the stencil/packed renderbuffer\n * code tree-shakes out of every bundle that only needs a color (and optional\n * depth) target.\n *\n * The attachment is **restore-correct**: it is rebuilt automatically — at the new\n * size on {@link resizeRenderTarget}, and into the fresh framebuffer after a\n * `webglcontextrestored` event — so the stencil survives for the life of the\n * target, and {@link disposeRenderTarget} releases it along with the target.\n *\n * No-op on a lost/disposed context or a disposed target.\n *\n * @param engine - The engine that owns `rt`.\n * @param rt - The render target to attach the stencil buffer to.\n * @param options - `depth` (default `true`): when `true` the attachment is a\n * packed depth+stencil buffer (`DEPTH24_STENCIL8` on `DEPTH_STENCIL_ATTACHMENT`)\n * — the common case, and the correct choice when the target was created with\n * `generateDepthBuffer: true`. When `false` the attachment is stencil-only\n * (`STENCIL_INDEX8` on `STENCIL_ATTACHMENT`).\n * @throws If a renderbuffer handle could not be allocated or the framebuffer is\n * incomplete after attaching.\n */\nexport function generateRenderTargetStencil(engine: GLEngineContext, rt: GLRenderTarget, options?: { depth?: boolean }): void {\n if (engine._isLost || engine._disposed || rt._disposed) {\n return;\n }\n const packDepth = options?.depth ?? true;\n const attachment = packDepth ? DEPTH_STENCIL_ATTACHMENT : STENCIL_ATTACHMENT;\n const format = packDepth ? DEPTH24_STENCIL8 : STENCIL_INDEX8;\n\n const build = (e: GLEngineContext): void => {\n const gl = e.gl;\n // Capture the caller's draw target so this helper is STATE-NEUTRAL: it must\n // not silently redirect subsequent draws to `rt` (during an internal\n // rebuild `prevFb` is `rt._framebuffer`, which the core re-checks next).\n const prevFb = e._state.boundFramebuffer;\n const newRb = gl.createRenderbuffer();\n if (newRb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null (render target stencil)\");\n }\n let committed = false;\n try {\n gl.bindFramebuffer(FRAMEBUFFER, rt._framebuffer);\n e._state.boundFramebuffer = rt._framebuffer;\n gl.bindRenderbuffer(RENDERBUFFER, newRb);\n gl.renderbufferStorage(RENDERBUFFER, format, rt.width, rt.height);\n gl.framebufferRenderbuffer(FRAMEBUFFER, attachment, RENDERBUFFER, newRb);\n gl.bindRenderbuffer(RENDERBUFFER, null);\n const status = gl.checkFramebufferStatus(FRAMEBUFFER);\n if (status !== FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete after stencil attach (status 0x${status.toString(16)})`);\n }\n // Commit only after a complete attachment: release the buffer we\n // replaced (the core depth-only one, or our own from a prior rebuild).\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = newRb;\n committed = true;\n } finally {\n if (!committed) {\n // Any non-committed exit (incomplete framebuffer OR an unexpected\n // GL throw): detach + delete the buffer we couldn't adopt so it\n // never leaks, leaving the attachment point empty for the\n // caller-level rollback to re-establish the prior buffer.\n gl.framebufferRenderbuffer(FRAMEBUFFER, attachment, RENDERBUFFER, null);\n gl.deleteRenderbuffer(newRb);\n }\n // Restore the caller's draw target + the bound-framebuffer cache.\n if (e._state.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(FRAMEBUFFER, prevFb);\n e._state.boundFramebuffer = prevFb;\n }\n }\n };\n\n // Build once now, but COMMIT the resize/restore hook only if it succeeds — a\n // failed opt-in must leave the target exactly as it was. The packed attach\n // above can clear the core `DEPTH_ATTACHMENT`, so on failure restore the prior\n // hook AND re-establish the prior depth/stencil attachment (the prior hook's,\n // or the core depth-only buffer).\n const prevHook = rt._rebuildDepthStencil;\n const prevDepthStencil = rt._depthStencil;\n try {\n build(engine);\n } catch (err) {\n rt._rebuildDepthStencil = prevHook;\n try {\n if (prevHook !== undefined) {\n prevHook(engine);\n } else if (prevDepthStencil !== null) {\n reattachCoreDepthBuffer(engine, rt, prevDepthStencil);\n }\n } catch {\n // Best-effort restore; surface the original failure below.\n }\n throw err;\n }\n rt._rebuildDepthStencil = build;\n}\n\n/**\n * Re-attach a core depth-only renderbuffer at `DEPTH_ATTACHMENT` — used to roll a\n * render target back when a packed {@link generateRenderTargetStencil} attach\n * fails completeness (attaching at `DEPTH_STENCIL_ATTACHMENT` clears the core\n * `DEPTH_ATTACHMENT`). State-neutral: restores the caller's bound framebuffer.\n * @internal\n */\nfunction reattachCoreDepthBuffer(engine: GLEngineContext, rt: GLRenderTarget, depthBuffer: WebGLRenderbuffer): void {\n const gl = engine.gl;\n const prevFb = engine._state.boundFramebuffer;\n gl.bindFramebuffer(FRAMEBUFFER, rt._framebuffer);\n engine._state.boundFramebuffer = rt._framebuffer;\n gl.framebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, depthBuffer);\n if (engine._state.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(FRAMEBUFFER, prevFb);\n engine._state.boundFramebuffer = prevFb;\n }\n}\n"]}
|
package/dynamic-texture.d.ts
CHANGED
|
@@ -1,149 +1,59 @@
|
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Pure-state handle for a WebGL2 canvas + its cached GL state.
|
|
64
|
-
*
|
|
65
|
-
* INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.
|
|
66
|
-
* Doing so silently corrupts the cache in `_state`. The package owns every
|
|
67
|
-
* GL call. (`engine.gl` is exposed only so downstream code that already has the
|
|
68
|
-
* pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT
|
|
69
|
-
* call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)
|
|
70
|
-
*/
|
|
71
|
-
declare interface GLEngineContext {
|
|
72
|
-
/** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is
|
|
73
|
-
* supported for worker render paths (e.g. the Lottie player); it has no CSS
|
|
74
|
-
* box, so it must be sized explicitly via `setGLEngineSize` rather than the
|
|
75
|
-
* CSS-derived `resizeGLEngine`. */
|
|
76
|
-
readonly canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
77
|
-
/** The raw WebGL2 context. Do NOT mutate GL state through it — see the
|
|
78
|
-
* type-level invariant above; the package owns every state-changing call. */
|
|
79
|
-
readonly gl: WebGL2RenderingContext;
|
|
80
|
-
/** Queried capability limits for this context. */
|
|
81
|
-
readonly caps: GLEngineCaps;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Pure-state texture handle. The `handle` field is MUTABLE so the same logical
|
|
85
|
-
* texture survives a `webglcontextrestored` event — every consumer keeps the
|
|
86
|
-
* same `GLTexture` reference; only the internal `WebGLTexture` is swapped.
|
|
87
|
-
*
|
|
88
|
-
* `loadTexture2D` also uses the same handle for the 1×1 placeholder upload AND
|
|
89
|
-
* the final image upload — so a `bindTexture(engine, unit, tex)` made before the
|
|
90
|
-
* image has decoded remains valid once the image arrives.
|
|
91
|
-
*/
|
|
92
|
-
declare interface GLTexture {
|
|
93
|
-
/** The live `WebGLTexture`. MUTABLE — swapped for a fresh handle on
|
|
94
|
-
* `webglcontextrestored` while consumers keep the same `GLTexture` reference. */
|
|
95
|
-
handle: WebGLTexture;
|
|
96
|
-
/** GL texture target (always `gl.TEXTURE_2D` for this package). */
|
|
97
|
-
readonly target: GLenum;
|
|
98
|
-
/** Texture width in texels. Updated once an async upload resolves. */
|
|
99
|
-
width: number;
|
|
100
|
-
/** Texture height in texels. Updated once an async upload resolves. */
|
|
101
|
-
height: number;
|
|
102
|
-
/** True when the texture is safe to sample with final content (placeholders
|
|
103
|
-
* read as not-ready until their image/upload completes). */
|
|
104
|
-
isReady: boolean;
|
|
105
|
-
|
|
106
|
-
/** Texture sampling / wrap options. All have GL-spec defaults. Mipmaps are NOT
|
|
107
|
-
* a create option — generate the chain explicitly via {@link generateTextureMipMaps}. */
|
|
108
|
-
declare interface GLTextureOptions {
|
|
109
|
-
/** Default: false (matches Babylon's default raw-texture behaviour). */
|
|
110
|
-
invertY?: boolean;
|
|
111
|
-
/** Default: gl.LINEAR. */
|
|
112
|
-
minFilter?: GLenum;
|
|
113
|
-
/** Default: gl.LINEAR. */
|
|
114
|
-
magFilter?: GLenum;
|
|
115
|
-
/** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`
|
|
116
|
-
* (NPOT-safe in WebGL2). */
|
|
117
|
-
wrapS?: GLenum;
|
|
118
|
-
/** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`. */
|
|
119
|
-
wrapT?: GLenum;
|
|
120
|
-
/** `gl.pixelStorei(UNPACK_ALIGNMENT)` for the upload (1/2/4/8). Default 4.
|
|
121
|
-
* Use 1 for tightly-packed non-RGBA rows. */
|
|
122
|
-
unpackAlignment?: number;
|
|
123
|
-
/** Premultiply alpha at upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`). Default
|
|
124
|
-
* false. */
|
|
125
|
-
premultiplyAlpha?: boolean;
|
|
126
|
-
/** Explicit sized internalFormat for `texImage2D`. When provided it is used
|
|
127
|
-
* verbatim and the inline LDR resolver is bypassed — this is how
|
|
128
|
-
* {@link createFloatTexture} injects its `RGBA16F` / `RGBA32F` choice
|
|
129
|
-
* without the byte path ever referencing the float-format table (keeping it
|
|
130
|
-
* tree-shakeable out of RGBA8-only bundles). Default: derived from
|
|
131
|
-
* `format`/`type` via the LDR resolver. */
|
|
132
|
-
internalFormat?: GLenum;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /
|
|
136
|
-
* `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the
|
|
137
|
-
* WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source
|
|
138
|
-
* is retained on the texture so it is replayed on `webglcontextrestored`.
|
|
139
|
-
* No-op when the context is lost/disposed or the texture is disposed.
|
|
140
|
-
*
|
|
141
|
-
* @param engine - The engine that owns the texture.
|
|
142
|
-
* @param tex - A texture created by {@link createDynamicTexture}.
|
|
143
|
-
* @param source - The 2D pixel source to upload.
|
|
144
|
-
* @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.
|
|
145
|
-
* @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).
|
|
146
|
-
* Default `false`, matching Babylon's `updateDynamicTexture` default. */
|
|
147
|
-
export declare function updateDynamicTexture(engine: GLEngineContext, tex: GLTexture, source: TexImageSource, invertY?: boolean, premultiplyAlpha?: boolean): void;
|
|
148
|
-
|
|
149
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic (canvas-/bitmap-backed) textures.
|
|
3
|
+
*
|
|
4
|
+
* Part of the public API via the `@babylonjs/lite-gl` barrel. The package is
|
|
5
|
+
* `sideEffects: false`, so consumers that never push 2D pixel sources into a
|
|
6
|
+
* texture tree-shake this code out.
|
|
7
|
+
*
|
|
8
|
+
* The WebGL counterpart of Babylon's `ThinEngine.createDynamicTexture` +
|
|
9
|
+
* `updateDynamicTexture`. A dynamic texture is a blank RGBA8 allocation whose
|
|
10
|
+
* pixels are pushed on demand from a canvas / `OffscreenCanvas` / image / video
|
|
11
|
+
* / `ImageBitmap` / `ImageData` source. The most recent source is retained
|
|
12
|
+
* internally and replayed into the fresh handle on `webglcontextrestored` by the
|
|
13
|
+
* engine's standard context-restore protocol.
|
|
14
|
+
*/
|
|
15
|
+
import { type GLTexture, type GLTextureOptions } from "./texture.js";
|
|
16
|
+
import type { GLEngineContext } from "./context.js";
|
|
17
|
+
/** Create a texture backed by an empty (blank) `width × height` RGBA8
|
|
18
|
+
* allocation, whose pixels are pushed on demand with
|
|
19
|
+
* {@link updateDynamicTexture} — the WebGL counterpart of Babylon's
|
|
20
|
+
* `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.
|
|
21
|
+
*
|
|
22
|
+
* The texture is immediately sampleable (reads as transparent black until the
|
|
23
|
+
* first update). It is context-restore-safe: the most recent source pushed via
|
|
24
|
+
* {@link updateDynamicTexture} is replayed into the fresh handle on
|
|
25
|
+
* `webglcontextrestored` (and re-blanked if no update happened yet).
|
|
26
|
+
*
|
|
27
|
+
* `options.invertY` is ignored here (the blank allocation is flip-invariant);
|
|
28
|
+
* per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.
|
|
29
|
+
*
|
|
30
|
+
* @param engine - The engine to create GL resources on.
|
|
31
|
+
* @param width - Texture width in texels (clamped to ≥ 1).
|
|
32
|
+
* @param height - Texture height in texels (clamped to ≥ 1).
|
|
33
|
+
* @param options - Optional sampling/wrap config (see {@link GLTextureOptions})
|
|
34
|
+
* plus this factory's own `generateMipMaps` flag (mipmaps are built after an
|
|
35
|
+
* update when a source is present; defaults to `false`).
|
|
36
|
+
* @returns The new {@link GLTexture}. */
|
|
37
|
+
export declare function createDynamicTexture(engine: GLEngineContext, width: number, height: number, options?: GLTextureOptions & {
|
|
38
|
+
generateMipMaps?: boolean;
|
|
39
|
+
}): GLTexture;
|
|
40
|
+
/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /
|
|
41
|
+
* `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the
|
|
42
|
+
* WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source
|
|
43
|
+
* is retained on the texture so it is replayed on `webglcontextrestored`.
|
|
44
|
+
* No-op when the context is lost/disposed or the texture is disposed.
|
|
45
|
+
*
|
|
46
|
+
* @param engine - The engine that owns the texture.
|
|
47
|
+
* @param tex - A texture created by {@link createDynamicTexture}.
|
|
48
|
+
* @param source - The 2D pixel source to upload.
|
|
49
|
+
* @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.
|
|
50
|
+
* @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).
|
|
51
|
+
* Default `false`, matching Babylon's `updateDynamicTexture` default. */
|
|
52
|
+
export declare function updateDynamicTexture(engine: GLEngineContext, tex: GLTexture, source: TexImageSource, invertY?: boolean, premultiplyAlpha?: boolean): void;
|
|
53
|
+
/** Forget the source a dynamic texture retained for context-restore replay.
|
|
54
|
+
* The current GPU pixels are kept (no re-upload), but the source reference is
|
|
55
|
+
* dropped so it can be garbage-collected — and a subsequent
|
|
56
|
+
* `webglcontextrestored` will re-blank the texture instead of replaying. Use
|
|
57
|
+
* after the final {@link updateDynamicTexture} once the source (e.g. a large
|
|
58
|
+
* atlas canvas) is no longer needed. No-op on a non-dynamic texture. */
|
|
59
|
+
export declare function clearDynamicTextureSource(tex: GLTexture): void;
|
package/dynamic-texture.js
CHANGED
|
@@ -1,73 +1,127 @@
|
|
|
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
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic (canvas-/bitmap-backed) textures.
|
|
3
|
+
*
|
|
4
|
+
* Part of the public API via the `@babylonjs/lite-gl` barrel. The package is
|
|
5
|
+
* `sideEffects: false`, so consumers that never push 2D pixel sources into a
|
|
6
|
+
* texture tree-shake this code out.
|
|
7
|
+
*
|
|
8
|
+
* The WebGL counterpart of Babylon's `ThinEngine.createDynamicTexture` +
|
|
9
|
+
* `updateDynamicTexture`. A dynamic texture is a blank RGBA8 allocation whose
|
|
10
|
+
* pixels are pushed on demand from a canvas / `OffscreenCanvas` / image / video
|
|
11
|
+
* / `ImageBitmap` / `ImageData` source. The most recent source is retained
|
|
12
|
+
* internally and replayed into the fresh handle on `webglcontextrestored` by the
|
|
13
|
+
* engine's standard context-restore protocol.
|
|
14
|
+
*/
|
|
15
|
+
import { bindTextureForUpload, setUnpackState } from "./texture.js";
|
|
16
|
+
/** Create a texture backed by an empty (blank) `width × height` RGBA8
|
|
17
|
+
* allocation, whose pixels are pushed on demand with
|
|
18
|
+
* {@link updateDynamicTexture} — the WebGL counterpart of Babylon's
|
|
19
|
+
* `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.
|
|
20
|
+
*
|
|
21
|
+
* The texture is immediately sampleable (reads as transparent black until the
|
|
22
|
+
* first update). It is context-restore-safe: the most recent source pushed via
|
|
23
|
+
* {@link updateDynamicTexture} is replayed into the fresh handle on
|
|
24
|
+
* `webglcontextrestored` (and re-blanked if no update happened yet).
|
|
25
|
+
*
|
|
26
|
+
* `options.invertY` is ignored here (the blank allocation is flip-invariant);
|
|
27
|
+
* per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.
|
|
28
|
+
*
|
|
29
|
+
* @param engine - The engine to create GL resources on.
|
|
30
|
+
* @param width - Texture width in texels (clamped to ≥ 1).
|
|
31
|
+
* @param height - Texture height in texels (clamped to ≥ 1).
|
|
32
|
+
* @param options - Optional sampling/wrap config (see {@link GLTextureOptions})
|
|
33
|
+
* plus this factory's own `generateMipMaps` flag (mipmaps are built after an
|
|
34
|
+
* update when a source is present; defaults to `false`).
|
|
35
|
+
* @returns The new {@link GLTexture}. */
|
|
36
|
+
export function createDynamicTexture(engine, width, height, options) {
|
|
37
|
+
const gl = engine.gl;
|
|
38
|
+
const handle = gl.createTexture();
|
|
39
|
+
if (handle === null) {
|
|
40
|
+
throw new Error("lite-gl: gl.createTexture returned null");
|
|
26
41
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
handle,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
const w = Math.max(1, width | 0);
|
|
43
|
+
const h = Math.max(1, height | 0);
|
|
44
|
+
const opts = options ?? {};
|
|
45
|
+
const minFilter = opts.minFilter ?? gl.LINEAR;
|
|
46
|
+
const magFilter = opts.magFilter ?? gl.LINEAR;
|
|
47
|
+
const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;
|
|
48
|
+
const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;
|
|
49
|
+
const generateMipMaps = opts.generateMipMaps ?? false;
|
|
50
|
+
// Single `_upload` closure used for both the initial allocation AND every
|
|
51
|
+
// `webglcontextrestored` replay AND every `updateDynamicTexture`. The pixel
|
|
52
|
+
// upload runs every time; the four `texParameteri` calls run ONLY when the
|
|
53
|
+
// handle changed (initial create + restore install a fresh, GL-default
|
|
54
|
+
// handle) — a per-frame pixel update keeps the same handle, whose filter/wrap
|
|
55
|
+
// GL retains, so re-applying them would be a pure redundant cost.
|
|
56
|
+
const upload = (target) => {
|
|
57
|
+
const g = target.gl;
|
|
58
|
+
bindTextureForUpload(target, tex.handle);
|
|
59
|
+
const src = tex._dynSource;
|
|
60
|
+
if (src !== null && src !== undefined) {
|
|
61
|
+
setUnpackState(target, tex._dynInvertY === true, tex._dynPremultiplyAlpha === true);
|
|
62
|
+
g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, src);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
setUnpackState(target, false, false);
|
|
66
|
+
g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);
|
|
67
|
+
}
|
|
68
|
+
if (tex._dynParamsHandle !== tex.handle) {
|
|
69
|
+
g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
|
|
70
|
+
g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
|
|
71
|
+
g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
|
|
72
|
+
g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
|
|
73
|
+
tex._dynParamsHandle = tex.handle;
|
|
74
|
+
}
|
|
75
|
+
if (generateMipMaps && src !== null && src !== undefined) {
|
|
76
|
+
g.generateMipmap(g.TEXTURE_2D);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const tex = {
|
|
80
|
+
handle,
|
|
81
|
+
target: gl.TEXTURE_2D,
|
|
82
|
+
width: w,
|
|
83
|
+
height: h,
|
|
84
|
+
isReady: true,
|
|
85
|
+
_disposed: false,
|
|
86
|
+
_refCount: 1,
|
|
87
|
+
_upload: upload,
|
|
88
|
+
_wasReady: true,
|
|
89
|
+
_dynSource: null,
|
|
90
|
+
_dynInvertY: false,
|
|
91
|
+
_dynPremultiplyAlpha: false,
|
|
92
|
+
};
|
|
93
|
+
upload(engine);
|
|
94
|
+
engine._textures.push(tex);
|
|
95
|
+
return tex;
|
|
55
96
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
tex.
|
|
97
|
+
/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /
|
|
98
|
+
* `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the
|
|
99
|
+
* WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source
|
|
100
|
+
* is retained on the texture so it is replayed on `webglcontextrestored`.
|
|
101
|
+
* No-op when the context is lost/disposed or the texture is disposed.
|
|
102
|
+
*
|
|
103
|
+
* @param engine - The engine that owns the texture.
|
|
104
|
+
* @param tex - A texture created by {@link createDynamicTexture}.
|
|
105
|
+
* @param source - The 2D pixel source to upload.
|
|
106
|
+
* @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.
|
|
107
|
+
* @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).
|
|
108
|
+
* Default `false`, matching Babylon's `updateDynamicTexture` default. */
|
|
109
|
+
export function updateDynamicTexture(engine, tex, source, invertY = false, premultiplyAlpha = false) {
|
|
110
|
+
if (engine._isLost || engine._disposed || tex._disposed) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
tex._dynSource = source;
|
|
114
|
+
tex._dynInvertY = invertY;
|
|
115
|
+
tex._dynPremultiplyAlpha = premultiplyAlpha;
|
|
116
|
+
tex._upload(engine);
|
|
64
117
|
}
|
|
65
|
-
|
|
66
|
-
|
|
118
|
+
/** Forget the source a dynamic texture retained for context-restore replay.
|
|
119
|
+
* The current GPU pixels are kept (no re-upload), but the source reference is
|
|
120
|
+
* dropped so it can be garbage-collected — and a subsequent
|
|
121
|
+
* `webglcontextrestored` will re-blank the texture instead of replaying. Use
|
|
122
|
+
* after the final {@link updateDynamicTexture} once the source (e.g. a large
|
|
123
|
+
* atlas canvas) is no longer needed. No-op on a non-dynamic texture. */
|
|
124
|
+
export function clearDynamicTextureSource(tex) {
|
|
125
|
+
tex._dynSource = null;
|
|
67
126
|
}
|
|
68
|
-
|
|
69
|
-
clearDynamicTextureSource,
|
|
70
|
-
createDynamicTexture,
|
|
71
|
-
updateDynamicTexture
|
|
72
|
-
};
|
|
73
|
-
//# sourceMappingURL=dynamic-texture.js.map
|
|
127
|
+
//# sourceMappingURL=dynamic-texture.js.map
|
package/dynamic-texture.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-texture.js","sources":["../src/dynamic-texture.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"file":"dynamic-texture.js","sourceRoot":"","sources":["../src/dynamic-texture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAyC,MAAM,cAAc,CAAC;AAG3G;;;;;;;;;;;;;;;;;;;0CAmB0C;AAC1C,MAAM,UAAU,oBAAoB,CAAC,MAAuB,EAAE,KAAa,EAAE,MAAc,EAAE,OAA0D;IACnJ,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,IAAI,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,MAAM,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,aAAa,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,aAAa,CAAC;IAC7C,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC;IAEtD,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,uEAAuE;IACvE,8EAA8E;IAC9E,kEAAkE;IAClE,MAAM,MAAM,GAAG,CAAC,MAAuB,EAAQ,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QACpB,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC;QAC3B,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpC,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,KAAK,IAAI,EAAE,GAAG,CAAC,oBAAoB,KAAK,IAAI,CAAC,CAAC;YACpF,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;aAAM,CAAC;YACJ,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,GAAG,CAAC,gBAAgB,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;YACtC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;YAC/D,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;YAC/D,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACvD,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACvD,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,MAAM,CAAC;QACtC,CAAC;QACD,IAAI,eAAe,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACvD,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACnC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,GAAG,GAAc;QACnB,MAAM;QACN,MAAM,EAAE,EAAE,CAAC,UAAU;QACrB,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,MAAM;QACf,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,KAAK;QAClB,oBAAoB,EAAE,KAAK;KAC9B,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,CAAC;IACf,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;;;;;2EAW2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,MAAuB,EAAE,GAAc,EAAE,MAAsB,EAAE,OAAO,GAAG,KAAK,EAAE,gBAAgB,GAAG,KAAK;IAC3I,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QACtD,OAAO;IACX,CAAC;IACD,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;IACxB,GAAG,CAAC,WAAW,GAAG,OAAO,CAAC;IAC1B,GAAG,CAAC,oBAAoB,GAAG,gBAAgB,CAAC;IAC5C,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC;AAED;;;;;yEAKyE;AACzE,MAAM,UAAU,yBAAyB,CAAC,GAAc;IACpD,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Dynamic (canvas-/bitmap-backed) textures.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that never push 2D pixel sources into a\n * texture tree-shake this code out.\n *\n * The WebGL counterpart of Babylon's `ThinEngine.createDynamicTexture` +\n * `updateDynamicTexture`. A dynamic texture is a blank RGBA8 allocation whose\n * pixels are pushed on demand from a canvas / `OffscreenCanvas` / image / video\n * / `ImageBitmap` / `ImageData` source. The most recent source is retained\n * internally and replayed into the fresh handle on `webglcontextrestored` by the\n * engine's standard context-restore protocol.\n */\nimport { bindTextureForUpload, setUnpackState, type GLTexture, type GLTextureOptions } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** Create a texture backed by an empty (blank) `width × height` RGBA8\n * allocation, whose pixels are pushed on demand with\n * {@link updateDynamicTexture} — the WebGL counterpart of Babylon's\n * `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.\n *\n * The texture is immediately sampleable (reads as transparent black until the\n * first update). It is context-restore-safe: the most recent source pushed via\n * {@link updateDynamicTexture} is replayed into the fresh handle on\n * `webglcontextrestored` (and re-blanked if no update happened yet).\n *\n * `options.invertY` is ignored here (the blank allocation is flip-invariant);\n * per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.\n *\n * @param engine - The engine to create GL resources on.\n * @param width - Texture width in texels (clamped to ≥ 1).\n * @param height - Texture height in texels (clamped to ≥ 1).\n * @param options - Optional sampling/wrap config (see {@link GLTextureOptions})\n * plus this factory's own `generateMipMaps` flag (mipmaps are built after an\n * update when a source is present; defaults to `false`).\n * @returns The new {@link GLTexture}. */\nexport function createDynamicTexture(engine: GLEngineContext, width: number, height: number, options?: GLTextureOptions & { generateMipMaps?: boolean }): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const w = Math.max(1, width | 0);\n const h = Math.max(1, height | 0);\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const generateMipMaps = opts.generateMipMaps ?? false;\n\n // Single `_upload` closure used for both the initial allocation AND every\n // `webglcontextrestored` replay AND every `updateDynamicTexture`. The pixel\n // upload runs every time; the four `texParameteri` calls run ONLY when the\n // handle changed (initial create + restore install a fresh, GL-default\n // handle) — a per-frame pixel update keeps the same handle, whose filter/wrap\n // GL retains, so re-applying them would be a pure redundant cost.\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n bindTextureForUpload(target, tex.handle);\n const src = tex._dynSource;\n if (src !== null && src !== undefined) {\n setUnpackState(target, tex._dynInvertY === true, tex._dynPremultiplyAlpha === true);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, src);\n } else {\n setUnpackState(target, false, false);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);\n }\n if (tex._dynParamsHandle !== tex.handle) {\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);\n tex._dynParamsHandle = tex.handle;\n }\n if (generateMipMaps && src !== null && src !== undefined) {\n g.generateMipmap(g.TEXTURE_2D);\n }\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: w,\n height: h,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: true,\n _dynSource: null,\n _dynInvertY: false,\n _dynPremultiplyAlpha: false,\n };\n upload(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /\n * `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the\n * WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source\n * is retained on the texture so it is replayed on `webglcontextrestored`.\n * No-op when the context is lost/disposed or the texture is disposed.\n *\n * @param engine - The engine that owns the texture.\n * @param tex - A texture created by {@link createDynamicTexture}.\n * @param source - The 2D pixel source to upload.\n * @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.\n * @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).\n * Default `false`, matching Babylon's `updateDynamicTexture` default. */\nexport function updateDynamicTexture(engine: GLEngineContext, tex: GLTexture, source: TexImageSource, invertY = false, premultiplyAlpha = false): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n tex._dynSource = source;\n tex._dynInvertY = invertY;\n tex._dynPremultiplyAlpha = premultiplyAlpha;\n tex._upload(engine);\n}\n\n/** Forget the source a dynamic texture retained for context-restore replay.\n * The current GPU pixels are kept (no re-upload), but the source reference is\n * dropped so it can be garbage-collected — and a subsequent\n * `webglcontextrestored` will re-blank the texture instead of replaying. Use\n * after the final {@link updateDynamicTexture} once the source (e.g. a large\n * atlas canvas) is no longer needed. No-op on a non-dynamic texture. */\nexport function clearDynamicTextureSource(tex: GLTexture): void {\n tex._dynSource = null;\n}\n"]}
|