@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.
Files changed (61) hide show
  1. package/README.md +10 -34
  2. package/apply-states.d.ts +1 -0
  3. package/apply-states.js +30 -0
  4. package/apply-states.js.map +1 -0
  5. package/blend.d.ts +123 -0
  6. package/blend.js +194 -0
  7. package/blend.js.map +1 -0
  8. package/context.d.ts +130 -0
  9. package/context.js +354 -0
  10. package/context.js.map +1 -0
  11. package/depth-stencil.d.ts +155 -231
  12. package/depth-stencil.js +399 -262
  13. package/depth-stencil.js.map +1 -1
  14. package/dynamic-texture.d.ts +59 -149
  15. package/dynamic-texture.js +123 -69
  16. package/dynamic-texture.js.map +1 -1
  17. package/effect-renderer.d.ts +65 -0
  18. package/effect-renderer.js +132 -0
  19. package/effect-renderer.js.map +1 -0
  20. package/effect.d.ts +142 -0
  21. package/effect.js +465 -0
  22. package/effect.js.map +1 -0
  23. package/html-texture.d.ts +44 -143
  24. package/html-texture.js +87 -81
  25. package/html-texture.js.map +1 -1
  26. package/index.d.ts +23 -1482
  27. package/index.js +42 -263
  28. package/index.js.map +1 -1
  29. package/mesh.d.ts +210 -307
  30. package/mesh.js +436 -311
  31. package/mesh.js.map +1 -1
  32. package/package.json +5 -29
  33. package/render-loop.d.ts +8 -0
  34. package/render-loop.js +62 -0
  35. package/render-loop.js.map +1 -0
  36. package/render-target.d.ts +233 -290
  37. package/render-target.js +534 -335
  38. package/render-target.js.map +1 -1
  39. package/scissor.d.ts +30 -72
  40. package/scissor.js +47 -33
  41. package/scissor.js.map +1 -1
  42. package/shader.d.ts +22 -0
  43. package/shader.js +65 -0
  44. package/shader.js.map +1 -0
  45. package/sprites.d.ts +182 -263
  46. package/sprites.js +426 -10
  47. package/sprites.js.map +1 -1
  48. package/state.d.ts +126 -0
  49. package/state.js +153 -0
  50. package/state.js.map +1 -0
  51. package/texture.d.ts +142 -0
  52. package/texture.js +433 -0
  53. package/texture.js.map +1 -0
  54. package/effect-BxxwfB_O.js +0 -737
  55. package/effect-BxxwfB_O.js.map +0 -1
  56. package/sprites--1oyVtJ3.js +0 -437
  57. package/sprites--1oyVtJ3.js.map +0 -1
  58. package/state--j_ncWIi.js +0 -155
  59. package/state--j_ncWIi.js.map +0 -1
  60. package/texture-DaMd1gGm.js +0 -329
  61. package/texture-DaMd1gGm.js.map +0 -1
@@ -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"]}
@@ -1,149 +1,59 @@
1
- /** Forget the source a dynamic texture retained for context-restore replay.
2
- * The current GPU pixels are kept (no re-upload), but the source reference is
3
- * dropped so it can be garbage-collected — and a subsequent
4
- * `webglcontextrestored` will re-blank the texture instead of replaying. Use
5
- * after the final {@link updateDynamicTexture} once the source (e.g. a large
6
- * atlas canvas) is no longer needed. No-op on a non-dynamic texture. */
7
- export declare function clearDynamicTextureSource(tex: GLTexture): void;
8
-
9
- /** Create a texture backed by an empty (blank) `width × height` RGBA8
10
- * allocation, whose pixels are pushed on demand with
11
- * {@link updateDynamicTexture} the WebGL counterpart of Babylon's
12
- * `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.
13
- *
14
- * The texture is immediately sampleable (reads as transparent black until the
15
- * first update). It is context-restore-safe: the most recent source pushed via
16
- * {@link updateDynamicTexture} is replayed into the fresh handle on
17
- * `webglcontextrestored` (and re-blanked if no update happened yet).
18
- *
19
- * `options.invertY` is ignored here (the blank allocation is flip-invariant);
20
- * per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.
21
- *
22
- * @param engine - The engine to create GL resources on.
23
- * @param width - Texture width in texels (clamped to 1).
24
- * @param height - Texture height in texels (clamped to ≥ 1).
25
- * @param options - Optional sampling/wrap config (see {@link GLTextureOptions})
26
- * plus this factory's own `generateMipMaps` flag (mipmaps are built after an
27
- * update when a source is present; defaults to `false`).
28
- * @returns The new {@link GLTexture}. */
29
- export declare function createDynamicTexture(engine: GLEngineContext, width: number, height: number, options?: GLTextureOptions & {
30
- generateMipMaps?: boolean;
31
- }): GLTexture;
32
-
33
- /** Read-only WebGL2 capability limits, queried once at context creation. */
34
- declare interface GLEngineCaps {
35
- /** `gl.MAX_TEXTURE_SIZE` largest supported texture dimension, in texels. */
36
- readonly maxTextureSize: number;
37
- /** `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` number of sampler binding slots. */
38
- readonly maxTextureUnits: number;
39
- /** The `KHR_parallel_shader_compile` extension used for async link polling,
40
- * or null when unsupported linking is then treated as synchronous. */
41
- readonly parallelShaderCompile: {
42
- COMPLETION_STATUS_KHR: number;
43
- } | null;
44
- /** True when 32-bit float color attachments are renderable
45
- * (`EXT_color_buffer_float`). Mirrors Babylon's `caps.textureFloatRender`. */
46
- readonly textureFloatRender: boolean;
47
- /** True when 32-bit float textures support linear filtering
48
- * (`OES_texture_float_linear`). Mirrors `caps.textureFloatLinearFiltering`. */
49
- readonly textureFloatLinearFiltering: boolean;
50
- /** True when 16-bit half-float color attachments are renderable
51
- * (`EXT_color_buffer_float` or `EXT_color_buffer_half_float`). Mirrors
52
- * `caps.textureHalfFloatRender`. */
53
- readonly textureHalfFloatRender: boolean;
54
- /** Half-float linear filtering always `true` in WebGL2 (it is core).
55
- * Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */
56
- readonly textureHalfFloatLinearFiltering: boolean;
57
- /** Whether non-power-of-two textures need POT dimensions for mips / wrap.
58
- * Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */
59
- readonly needPOTTextures: boolean;
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;
@@ -1,73 +1,127 @@
1
- import { i as bindTextureForUpload, s as setUnpackState } from "./texture-DaMd1gGm.js";
2
- function createDynamicTexture(engine, width, height, options) {
3
- const gl = engine.gl;
4
- const handle = gl.createTexture();
5
- if (handle === null) {
6
- throw new Error("lite-gl: gl.createTexture returned null");
7
- }
8
- const w = Math.max(1, width | 0);
9
- const h = Math.max(1, height | 0);
10
- const opts = options ?? {};
11
- const minFilter = opts.minFilter ?? gl.LINEAR;
12
- const magFilter = opts.magFilter ?? gl.LINEAR;
13
- const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;
14
- const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;
15
- const generateMipMaps = opts.generateMipMaps ?? false;
16
- const upload = (target) => {
17
- const g = target.gl;
18
- bindTextureForUpload(target, tex.handle);
19
- const src = tex._dynSource;
20
- if (src !== null && src !== void 0) {
21
- setUnpackState(target, tex._dynInvertY === true, tex._dynPremultiplyAlpha === true);
22
- g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, src);
23
- } else {
24
- setUnpackState(target, false, false);
25
- g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);
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
- if (tex._dynParamsHandle !== tex.handle) {
28
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
29
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
30
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
31
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
32
- tex._dynParamsHandle = tex.handle;
33
- }
34
- if (generateMipMaps && src !== null && src !== void 0) {
35
- g.generateMipmap(g.TEXTURE_2D);
36
- }
37
- };
38
- const tex = {
39
- handle,
40
- target: gl.TEXTURE_2D,
41
- width: w,
42
- height: h,
43
- isReady: true,
44
- _disposed: false,
45
- _refCount: 1,
46
- _upload: upload,
47
- _wasReady: true,
48
- _dynSource: null,
49
- _dynInvertY: false,
50
- _dynPremultiplyAlpha: false
51
- };
52
- upload(engine);
53
- engine._textures.push(tex);
54
- return tex;
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
- function updateDynamicTexture(engine, tex, source, invertY = false, premultiplyAlpha = false) {
57
- if (engine._isLost || engine._disposed || tex._disposed) {
58
- return;
59
- }
60
- tex._dynSource = source;
61
- tex._dynInvertY = invertY;
62
- tex._dynPremultiplyAlpha = premultiplyAlpha;
63
- tex._upload(engine);
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
- function clearDynamicTextureSource(tex) {
66
- tex._dynSource = null;
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
- export {
69
- clearDynamicTextureSource,
70
- createDynamicTexture,
71
- updateDynamicTexture
72
- };
73
- //# sourceMappingURL=dynamic-texture.js.map
127
+ //# sourceMappingURL=dynamic-texture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-texture.js","sources":["../src/dynamic-texture.ts"],"sourcesContent":["/**\n * Sub-entry: dynamic (canvas-/bitmap-backed) textures.\n *\n * Dynamic-importable via `import { ... } from \"@babylonjs/lite-gl/dynamic-texture\"`\n * so consumers that never push 2D pixel sources into a texture don't pull this\n * code into their bundles.\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"],"names":[],"mappings":";AAqCO,SAAS,qBAAqB,QAAyB,OAAe,QAAgB,SAAuE;AAChK,QAAM,KAAK,OAAO;AAClB,QAAM,SAAS,GAAG,cAAA;AAClB,MAAI,WAAW,MAAM;AACjB,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC7D;AACA,QAAM,IAAI,KAAK,IAAI,GAAG,QAAQ,CAAC;AAC/B,QAAM,IAAI,KAAK,IAAI,GAAG,SAAS,CAAC;AAChC,QAAM,OAAO,WAAW,CAAA;AACxB,QAAM,YAAY,KAAK,aAAa,GAAG;AACvC,QAAM,YAAY,KAAK,aAAa,GAAG;AACvC,QAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,QAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,QAAM,kBAAkB,KAAK,mBAAmB;AAQhD,QAAM,SAAS,CAAC,WAAkC;AAC9C,UAAM,IAAI,OAAO;AACjB,yBAAqB,QAAQ,IAAI,MAAM;AACvC,UAAM,MAAM,IAAI;AAChB,QAAI,QAAQ,QAAQ,QAAQ,QAAW;AACnC,qBAAe,QAAQ,IAAI,gBAAgB,MAAM,IAAI,yBAAyB,IAAI;AAClF,QAAE,WAAW,EAAE,YAAY,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG;AAAA,IACtE,OAAO;AACH,qBAAe,QAAQ,OAAO,KAAK;AACnC,QAAE,WAAW,EAAE,YAAY,GAAG,EAAE,OAAO,GAAG,GAAG,GAAG,EAAE,MAAM,EAAE,eAAe,IAAI;AAAA,IACjF;AACA,QAAI,IAAI,qBAAqB,IAAI,QAAQ;AACrC,QAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,SAAS;AAC7D,QAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,SAAS;AAC7D,QAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,KAAK;AACrD,QAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,KAAK;AACrD,UAAI,mBAAmB,IAAI;AAAA,IAC/B;AACA,QAAI,mBAAmB,QAAQ,QAAQ,QAAQ,QAAW;AACtD,QAAE,eAAe,EAAE,UAAU;AAAA,IACjC;AAAA,EACJ;AAEA,QAAM,MAAiB;AAAA,IACnB;AAAA,IACA,QAAQ,GAAG;AAAA,IACX,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,sBAAsB;AAAA,EAAA;AAE1B,SAAO,MAAM;AACb,SAAO,UAAU,KAAK,GAAG;AACzB,SAAO;AACX;AAcO,SAAS,qBAAqB,QAAyB,KAAgB,QAAwB,UAAU,OAAO,mBAAmB,OAAa;AACnJ,MAAI,OAAO,WAAW,OAAO,aAAa,IAAI,WAAW;AACrD;AAAA,EACJ;AACA,MAAI,aAAa;AACjB,MAAI,cAAc;AAClB,MAAI,uBAAuB;AAC3B,MAAI,QAAQ,MAAM;AACtB;AAQO,SAAS,0BAA0B,KAAsB;AAC5D,MAAI,aAAa;AACrB;"}
1
+ {"version":3,"file":"dynamic-texture.js","sourceRoot":"","sources":["../src/dynamic-texture.ts"],"names":[],"mappings":"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","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"]}