@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 +0,0 @@
1
- {"version":3,"file":"sprites--1oyVtJ3.js","sources":["../src/blend.ts","../src/sprites.ts"],"sourcesContent":["/**\n * Blend-mode state — the WebGL counterpart of Babylon's `Engine.setAlphaMode`\n * (presets) and `AlphaState.setAlphaBlendFunctionParameters` /\n * `setAlphaEquationParameters` (the arbitrary separate func + equation path).\n *\n * The numeric {@link GLBlendMode} values intentionally match Babylon's\n * `Constants.ALPHA_*` (`ALPHA_DISABLE = 0`, `ALPHA_ADD = 1`, `ALPHA_COMBINE = 2`,\n * `ALPHA_PREMULTIPLIED = 7`) so a consumer can forward raw Babylon constants\n * without a translation table.\n *\n * DEFERRED MODEL (matches Babylon's `AlphaState`): these setters do NOT touch\n * `gl.*`. They record only the DESIRED blend config into the `d*` mirror fields\n * of `GLState` and raise `statesDirty`; `applyGLStates` (apply-states.ts) flushes\n * the diff to GL right before each draw / clear. Setting blend A then B then A\n * with no draw in between therefore applies exactly one blend state (A), and a\n * blend left unchanged across frames re-issues nothing.\n *\n * Both {@link setBlendMode} and {@link setBlendState} feed the same desired\n * fields, so the preset and arbitrary paths can never desync.\n */\nimport { type GLEngineContext } from \"./context.js\";\nimport { RS_BLEND_DST_A, RS_BLEND_DST_RGB, RS_BLEND_ENABLED, RS_BLEND_EQ_A, RS_BLEND_EQ_RGB, RS_BLEND_SRC_A, RS_BLEND_SRC_RGB, RS_DESIRED } from \"./state.js\";\n\n/**\n * Supported blend presets. Values mirror Babylon's `Constants.ALPHA_*` so the\n * raw Babylon integers can be passed straight through.\n */\nexport const GLBlendMode = {\n /** No blending — `gl.disable(gl.BLEND)`. (`Constants.ALPHA_DISABLE`) */\n DISABLE: 0,\n /** Additive — `blendFuncSeparate(SRC_ALPHA, ONE, ZERO, ONE)`. (`Constants.ALPHA_ADD`) */\n ADD: 1,\n /** Standard (non-premultiplied) alpha — `blendFuncSeparate(SRC_ALPHA, ONE_MINUS_SRC_ALPHA, ONE, ONE)`. (`Constants.ALPHA_COMBINE`) */\n ALPHA: 2,\n /** Premultiplied alpha — `blendFuncSeparate(ONE, ONE_MINUS_SRC_ALPHA, ONE, ONE)`. (`Constants.ALPHA_PREMULTIPLIED`) */\n PREMULTIPLIED: 7,\n} as const;\n\n/** One of the {@link GLBlendMode} preset values (`0`, `1`, `2` or `7`). */\nexport type GLBlendMode = (typeof GLBlendMode)[keyof typeof GLBlendMode];\n\n/**\n * Blend equation presets — the values WebGL2 accepts for\n * `gl.blendEquationSeparate`. Numeric values equal the GL enums so raw GL\n * integers (or Babylon's identical `Constants.GL_ALPHA_EQUATION_*`) pass\n * straight through.\n */\nexport const GLBlendEquation = {\n /** `src + dst` (the GL default). */\n ADD: 0x8006,\n /** `src - dst`. */\n SUBTRACT: 0x800a,\n /** `dst - src`. */\n REVERSE_SUBTRACT: 0x800b,\n /** `min(src, dst)`. */\n MIN: 0x8007,\n /** `max(src, dst)`. */\n MAX: 0x8008,\n} as const;\n\n/** One of the {@link GLBlendEquation} preset values. */\nexport type GLBlendEquation = (typeof GLBlendEquation)[keyof typeof GLBlendEquation];\n\n/**\n * Arbitrary separate-channel blend configuration — the lite-gl equivalent of\n * Babylon's `AlphaState.setAlphaBlendFunctionParameters` +\n * `setAlphaEquationParameters`. All factor / equation fields are raw WebGL2\n * enums (`gl.ONE`, `gl.SRC_ALPHA`, `gl.MIN`, …); use {@link GLBlendEquation} for\n * the equations if you prefer named presets.\n */\nexport interface GLBlendState {\n /** RGB source factor (`gl.blendFuncSeparate` arg 1). */\n srcRGB: GLenum;\n /** RGB destination factor (`gl.blendFuncSeparate` arg 2). */\n dstRGB: GLenum;\n /** Alpha source factor (`gl.blendFuncSeparate` arg 3). */\n srcAlpha: GLenum;\n /** Alpha destination factor (`gl.blendFuncSeparate` arg 4). */\n dstAlpha: GLenum;\n /** RGB blend equation. Defaults to `FUNC_ADD`. */\n equationRGB?: GLenum;\n /** Alpha blend equation. Defaults to `FUNC_ADD`. */\n equationAlpha?: GLenum;\n}\n\n/** GL `FUNC_ADD` — the implicit equation used by the {@link GLBlendMode}\n * presets (matching Babylon's `setAlphaMode`, which leaves it at the default). */\nconst FUNC_ADD = 0x8006;\n/** GL `gl.BLEND`. */\nconst BLEND = 0x0be2;\n\n/**\n * Set the GL blend state to match Babylon's `setAlphaMode(mode)` exactly.\n *\n * | Mode | `gl.blendFuncSeparate(srcRGB, dstRGB, srcA, dstA)` |\n * |--------------------|------------------------------------------------------------|\n * | `DISABLE` (0) | — (`gl.disable(gl.BLEND)`) |\n * | `ADD` (1) | `SRC_ALPHA, ONE, ZERO, ONE` |\n * | `ALPHA` (2) | `SRC_ALPHA, ONE_MINUS_SRC_ALPHA, ONE, ONE` |\n * | `PREMULTIPLIED` (7)| `ONE, ONE_MINUS_SRC_ALPHA, ONE, ONE` |\n *\n * No-op when the context is lost or disposed.\n *\n * @param engine - The engine whose GL blend state is updated.\n * @param mode - The {@link GLBlendMode} preset to apply.\n */\nexport function setBlendMode(engine: GLEngineContext, mode: GLBlendMode): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n switch (mode) {\n case GLBlendMode.DISABLE:\n disableBlend(engine);\n return;\n case GLBlendMode.ADD:\n applyBlend(engine, gl.SRC_ALPHA, gl.ONE, gl.ZERO, gl.ONE, FUNC_ADD, FUNC_ADD);\n return;\n case GLBlendMode.ALPHA:\n applyBlend(engine, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE, FUNC_ADD, FUNC_ADD);\n return;\n case GLBlendMode.PREMULTIPLIED:\n applyBlend(engine, gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE, FUNC_ADD, FUNC_ADD);\n return;\n }\n}\n\n/**\n * Enable blending with an arbitrary separate-channel function and equation —\n * the lite-gl equivalent of Babylon's `AlphaState` with\n * `setAlphaBlendFunctionParameters` + `setAlphaEquationParameters`.\n *\n * Supports every WebGL2 blend equation, including `MIN`, `MAX`,\n * `FUNC_SUBTRACT` and `FUNC_REVERSE_SUBTRACT` (used by ShapeBuilder's darken /\n * cutout blend modes). Records the desired config (flushed by `applyGLStates`\n * before the next draw); at flush time the enable flag, the equation and the func\n * are each cached independently, so a redundant state is fully elided and only\n * the call whose params changed is re-issued — mirroring Babylon's `AlphaState`\n * dirty flags. Because GL keeps the equation + func across `gl.disable(BLEND)`,\n * re-enabling with unchanged params re-issues neither.\n *\n * No-op when the context is lost or disposed.\n *\n * @param engine - The engine whose desired blend state is updated.\n * @param state - The separate-channel blend factors + equations to apply.\n */\nexport function setBlendState(engine: GLEngineContext, state: GLBlendState): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n applyBlend(engine, state.srcRGB, state.dstRGB, state.srcAlpha, state.dstAlpha, state.equationRGB ?? FUNC_ADD, state.equationAlpha ?? FUNC_ADD);\n}\n\n/**\n * Disable blending — the equivalent of Babylon's `AlphaState.alphaBlend = false`.\n * Records the desired \"blend off\" state (flushed by `applyGLStates` before the\n * next draw); the actual `gl.disable(gl.BLEND)` is elided when blending is\n * already off at flush time. No-op when the context is lost or disposed.\n *\n * @param engine - The engine whose desired blend state is updated.\n */\nexport function disableBlend(engine: GLEngineContext): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const s = engine._state;\n s.rs[RS_BLEND_ENABLED + RS_DESIRED] = 0;\n s._flushBlend = flushBlend;\n s.statesDirty = true;\n}\n\n/* ──────────────────────────── internal apply ──────────────────────────── */\n\n/** Record a granular blend config into the DESIRED (`rs[RS_* + RS_DESIRED]`)\n * slots and mark it dirty. No `gl.*` here — `applyGLStates` reconciles\n * desired→actual at the next flush, caching the enable flag, equation and func\n * independently so each is re-issued only when its params change (and never on a\n * bare re-enable). */\nfunction applyBlend(engine: GLEngineContext, srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number, eqRGB: number, eqAlpha: number): void {\n const rs = engine._state.rs;\n rs[RS_BLEND_ENABLED + RS_DESIRED] = 1;\n rs[RS_BLEND_SRC_RGB + RS_DESIRED] = srcRGB;\n rs[RS_BLEND_DST_RGB + RS_DESIRED] = dstRGB;\n rs[RS_BLEND_SRC_A + RS_DESIRED] = srcAlpha;\n rs[RS_BLEND_DST_A + RS_DESIRED] = dstAlpha;\n rs[RS_BLEND_EQ_RGB + RS_DESIRED] = eqRGB;\n rs[RS_BLEND_EQ_A + RS_DESIRED] = eqAlpha;\n engine._state._flushBlend = flushBlend;\n engine._state.statesDirty = true;\n}\n\n/**\n * Reconcile the deferred blend state DESIRED → ACTUAL — the per-category half of\n * Babylon's `_alphaState.apply`. Installed onto `_state._flushBlend` by the blend\n * setters and dispatched by {@link applyGLStates}; co-located here so a scene that\n * never sets a blend mode tree-shakes both this reconciler and its GL code out of\n * the bundle.\n *\n * The enable flag, the equation and the func are reconciled as THREE independent\n * cached sub-states (mirroring Babylon's `_AlphaState` `_isAlphaBlendDirty` /\n * `_isBlendEquationParametersDirty` / `_isBlendFunctionParametersDirty`). GL\n * retains the blend equation + func across `gl.disable(BLEND)`, so their cached\n * actual values stay valid while blending is off — re-enabling with unchanged\n * params therefore issues ONLY `gl.enable(BLEND)` and re-issues neither\n * `blendEquationSeparate` nor `blendFuncSeparate`. A desired `-1` (never\n * requested) leaves GL untouched. @internal\n */\nfunction flushBlend(engine: GLEngineContext): void {\n const gl = engine.gl;\n const rs = engine._state.rs;\n const dBlend = rs[RS_BLEND_ENABLED + RS_DESIRED]!;\n if (dBlend === -1) {\n return;\n }\n // 1. enable / disable — independent of the func + equation cache below.\n if (dBlend !== rs[RS_BLEND_ENABLED]) {\n rs[RS_BLEND_ENABLED] = dBlend;\n if (dBlend === 1) {\n gl.enable(BLEND);\n } else {\n gl.disable(BLEND);\n }\n }\n // While blending is off the equation/func are not observable and GL keeps the\n // last values, so leave their cache untouched (Babylon does the same) — the\n // next enable with identical params then re-issues nothing.\n if (dBlend !== 1) {\n return;\n }\n // 2. equation — re-issued only when the params actually changed.\n const eqRGB = rs[RS_BLEND_EQ_RGB + RS_DESIRED]!;\n const eqA = rs[RS_BLEND_EQ_A + RS_DESIRED]!;\n if (rs[RS_BLEND_EQ_RGB] !== eqRGB || rs[RS_BLEND_EQ_A] !== eqA) {\n gl.blendEquationSeparate(eqRGB, eqA);\n rs[RS_BLEND_EQ_RGB] = eqRGB;\n rs[RS_BLEND_EQ_A] = eqA;\n }\n // 3. func — re-issued only when the params actually changed.\n const srcRGB = rs[RS_BLEND_SRC_RGB + RS_DESIRED]!;\n const dstRGB = rs[RS_BLEND_DST_RGB + RS_DESIRED]!;\n const srcA = rs[RS_BLEND_SRC_A + RS_DESIRED]!;\n const dstA = rs[RS_BLEND_DST_A + RS_DESIRED]!;\n if (rs[RS_BLEND_SRC_RGB] !== srcRGB || rs[RS_BLEND_DST_RGB] !== dstRGB || rs[RS_BLEND_SRC_A] !== srcA || rs[RS_BLEND_DST_A] !== dstA) {\n gl.blendFuncSeparate(srcRGB, dstRGB, srcA, dstA);\n rs[RS_BLEND_SRC_RGB] = srcRGB;\n rs[RS_BLEND_DST_RGB] = dstRGB;\n rs[RS_BLEND_SRC_A] = srcA;\n rs[RS_BLEND_DST_A] = dstA;\n }\n}\n","/**\n * Sub-entry: sprite / instanced-quad renderer.\n *\n * Dynamic-importable via `import { ... } from \"@babylonjs/lite-gl/sprites\"` so\n * consumers that don't render sprites don't pull it into their bundles.\n *\n * This is the lite-gl equivalent of Babylon's `SpriteRenderer` + `ThinSprite`\n * (`Sprites/spriteRenderer.js`, `Sprites/thinSprite.js`). The vertex layout,\n * per-cell UV math and corner/rotation transform are copied verbatim from the\n * non-instanced path of Babylon's `SpriteRenderer` so a future NeonBrush port\n * renders identically. The shaders are the GLSL ES 3.00 translation of\n * Babylon's `Shaders/sprites.vertex.js` / `sprites.fragment.js`, with the\n * fog / log-depth / pixel-perfect / alpha-test branches removed (lite-gl has\n * no depth attachment by default — see notes on `disableDepthWrite` below).\n */\nimport { offContextRestored, onContextRestored, type GLEngineContext } from \"./context.js\";\nimport { createEffect, disposeEffect, type GLEffect, isEffectReady, setEffectTexture, useEffect } from \"./effect.js\";\nimport { GLBlendMode, setBlendMode } from \"./blend.js\";\nimport { applyGLStates } from \"./apply-states.js\";\nimport { type GLTexture } from \"./texture.js\";\n\n/* ───────────────────────────── shaders (GLSL ES 3.00) ───────────────────── */\n\n/** Vertex shader — GLSL ES 3.00 translation of Babylon's `spritesVertexShader`\n * core path. Attribute locations 0..5 match `createSpriteRenderer`'s\n * `attributeNames` order so the renderer's VAO feeds every program correctly. */\nconst SPRITE_VERTEX_SOURCE = `#version 300 es\nprecision highp float;\nlayout(location = 0) in vec4 position;\nlayout(location = 1) in vec2 options;\nlayout(location = 2) in vec2 offsets;\nlayout(location = 3) in vec2 inverts;\nlayout(location = 4) in vec4 cellInfo;\nlayout(location = 5) in vec4 color;\nuniform mat4 view;\nuniform mat4 projection;\nout vec2 vUV;\nout vec4 vColor;\nvoid main(void) {\n vec3 viewPos = (view * vec4(position.xyz, 1.0)).xyz;\n float angle = position.w;\n vec2 size = vec2(options.x, options.y);\n vec2 offset = offsets.xy;\n vec2 cornerPos = vec2(offset.x - 0.5, offset.y - 0.5) * size;\n vec3 rotatedCorner;\n rotatedCorner.x = cornerPos.x * cos(angle) - cornerPos.y * sin(angle);\n rotatedCorner.y = cornerPos.x * sin(angle) + cornerPos.y * cos(angle);\n rotatedCorner.z = 0.0;\n viewPos += rotatedCorner;\n gl_Position = projection * vec4(viewPos, 1.0);\n vColor = color;\n vec2 uvOffset = vec2(abs(offset.x - inverts.x), abs(1.0 - offset.y - inverts.y));\n vec2 uvPlace = cellInfo.xy;\n vec2 uvSize = cellInfo.zw;\n vUV.x = uvPlace.x + uvSize.x * uvOffset.x;\n vUV.y = uvPlace.y + uvSize.y * uvOffset.y;\n}`;\n\n/** Fragment shader — GLSL ES 3.00 translation of Babylon's `spritesPixelShader`\n * color pass: `texture(diffuseSampler, vUV) * vColor`. The alpha-test/discard\n * branch is dropped because lite-gl never runs the depth pre-pass. */\nconst SPRITE_FRAGMENT_SOURCE = `#version 300 es\nprecision highp float;\nin vec2 vUV;\nin vec4 vColor;\nuniform sampler2D diffuseSampler;\nout vec4 glFragColor;\nvoid main(void) {\n vec4 color = texture(diffuseSampler, vUV);\n color *= vColor;\n glFragColor = color;\n}`;\n\n/* ───────────────────────────── layout constants ─────────────────────────── */\n\n/** Floats per vertex: position.xyz + angle (4), size (2), corner offset (2),\n * inverts (2), cellInfo (4), color (4) = 18. Matches Babylon's non-instanced\n * `_vertexBufferSize`. */\nconst FLOATS_PER_VERTEX = 18;\n/** Four corner vertices per sprite quad (non-instanced, like Babylon). */\nconst VERTS_PER_SPRITE = 4;\n/** Six indices per sprite (two triangles). */\nconst INDICES_PER_SPRITE = 6;\n/** Bytes per float — `Float32Array.BYTES_PER_ELEMENT`. */\nconst BYTES_PER_FLOAT = 4;\n/** Stride between consecutive vertices, in bytes. */\nconst VERTEX_STRIDE_BYTES = FLOATS_PER_VERTEX * BYTES_PER_FLOAT;\n/** UV inset applied to each quad corner, matching Babylon's default\n * `SpriteRenderer` epsilon (0.01) so cell sampling never bleeds neighbours. */\nconst SPRITE_EPSILON = 0.01;\n/** Max sprites: 4 verts/sprite must keep every index within `Uint16` range\n * (`capacity * 4 - 1 <= 65535`). */\nconst MAX_CAPACITY = 16384;\n\n/** Per-corner U offset (pre-epsilon), one entry per quad vertex. Module-scoped\n * literal — pure per bundler convention, allocated once (never per frame). */\nconst CORNER_OFFSET_X = [0, 1, 1, 0];\n/** Per-corner V offset (pre-epsilon), one entry per quad vertex. */\nconst CORNER_OFFSET_Y = [0, 0, 1, 1];\n\n/** Attribute names in location order — index `i` is bound to `location = i` by\n * `createEffect`/`linkProgram`, matching the shader's `layout(location = i)`. */\nconst SPRITE_ATTRIBUTES = [\"position\", \"options\", \"offsets\", \"inverts\", \"cellInfo\", \"color\"] as const;\n\n/* ─────────────────────────────── public types ──────────────────────────── */\n\n/** An RGBA color with each channel in `[0, 1]`, used for per-sprite tint. */\nexport interface GLSpriteColor {\n /** Red, 0..1. */\n r: number;\n /** Green, 0..1. */\n g: number;\n /** Blue, 0..1. */\n b: number;\n /** Alpha, 0..1. */\n a: number;\n}\n\n/** A single sprite — a plain data object mirroring the fields of Babylon's\n * `ThinSprite` that the renderer reads. No animation state: `cellIndex` is set\n * directly by the consumer (lite-gl does not port `ThinSprite.playAnimation`). */\nexport interface GLSprite {\n /** World-space position of the sprite center. */\n position: { x: number; y: number; z: number };\n /** Width in world units. */\n width: number;\n /** Height in world units. */\n height: number;\n /** Rotation angle, in radians. */\n angle: number;\n /** Sprite-sheet cell index (0-based, row-major). Out-of-range / negative\n * values are clamped to 0, matching Babylon's `if (!cellIndex) = 0`. Ignored\n * when a manual UV rect (`uSize`) is set. Optional — defaults to `0`. */\n cellIndex?: number;\n /** Optional tint; defaults to opaque white `{ r: 1, g: 1, b: 1, a: 1 }`. */\n color?: GLSpriteColor;\n /** Flip the cell horizontally. Defaults to `false`. */\n invertU?: boolean;\n /** Flip the cell vertically. Defaults to `false`. */\n invertV?: boolean;\n /** Manual UV rect — normalized left (U) origin in `[0, 1]`, mirroring\n * Babylon's `ThinSprite._xOffset`. Set together with {@link GLSprite.uSize}\n * to address an arbitrary sub-rectangle of the sheet instead of the fixed\n * `cellIndex` grid (used by the lottie atlas, whose cells vary in size). */\n uOffset?: number;\n /** Manual UV rect — normalized top (V) origin in `[0, 1]` (≙ Babylon\n * `ThinSprite._yOffset`). See {@link GLSprite.uSize}. */\n vOffset?: number;\n /** Manual UV rect — cell width in **texels** (≙ Babylon `ThinSprite._xSize`;\n * divided by the texture width when building vertices). Presence of `uSize`\n * switches the sprite into manual-UV mode (the `cellIndex` grid is ignored).\n * `0` samples a single column — the \"solid color\" trick. */\n uSize?: number;\n /** Manual UV rect — cell height in **texels** (≙ Babylon `ThinSprite._ySize`).\n * See {@link GLSprite.uSize}. Defaults to `0` when `uSize` is set but `vSize`\n * is omitted. */\n vSize?: number;\n /** When `false`, the sprite is skipped. Defaults to `true`. */\n isVisible?: boolean;\n}\n\n/** Options for {@link createSpriteRenderer}. */\nexport interface GLSpriteRendererOptions {\n /** Maximum number of sprites drawable in one `renderSprites` call. Must be\n * an integer in `[1, 16384]` (the `Uint16` index-buffer limit). */\n capacity: number;\n /** Cell width in texels within the sprite sheet, for the fixed-grid\n * `cellIndex` path. Optional — defaults to `1`; irrelevant when every\n * sprite supplies a manual UV rect (`uSize`), as the lottie atlas does. */\n cellWidth?: number;\n /** Cell height in texels within the sprite sheet. Optional — defaults to\n * `1`. See {@link GLSpriteRendererOptions.cellWidth}. */\n cellHeight?: number;\n /** Per-corner UV/position inset applied to each quad vertex, in the `[0, 0.5)`\n * range — the `epsilon` constructor argument of Babylon's `SpriteRenderer`.\n * It both insets cell UV sampling (so a cell never bleeds its neighbours) and\n * shrinks the quad by `epsilon * size` per side. Defaults to `0.01` (Babylon's\n * `SpriteRenderer` default). Pass `0` to disable insetting — the lottie atlas\n * does this (it relies on edge-extruded cells + center sampling instead, so a\n * non-zero inset would shrink every sprite by ~`0.01·size` per edge). */\n epsilon?: number;\n /** The sprite-sheet texture. May be swapped later via\n * {@link setSpriteRendererTexture}. */\n texture: GLTexture;\n /** Blend mode for the draw. Defaults to {@link GLBlendMode.ALPHA} (2),\n * matching Babylon's `SpriteRenderer.blendMode` default. */\n blendMode?: GLBlendMode;\n /** When `true` (default), `renderSprites` resets the blend mode to\n * {@link GLBlendMode.DISABLE} after drawing — mirroring Babylon's\n * `SpriteRenderer.autoResetAlpha = true`. Set `false` to leave the\n * renderer's `blendMode` applied after the draw (the lottie player relies\n * on this so its premultiplied alpha mode persists across passes). */\n autoResetAlpha?: boolean;\n /** Accepted for Babylon API parity. lite-gl's default engine has no depth\n * attachment (`depth: false`), so there is no depth pre-pass and this flag\n * has no observable effect; it is stored verbatim for a future depth-aware\n * consumer. Defaults to `false`. */\n disableDepthWrite?: boolean;\n}\n\n/**\n * A sprite renderer owning its own VBO/IBO/VAO and `GLEffect`. Created by\n * {@link createSpriteRenderer}; drive it with {@link renderSprites} and release\n * it with {@link disposeSpriteRenderer}.\n */\nexport interface GLSpriteRenderer {\n /** The sprite-sheet texture sampled by the shader. Swap via\n * {@link setSpriteRendererTexture}. */\n texture: GLTexture;\n /** Cell width in texels (selects the sub-rectangle for `cellIndex`). */\n cellWidth: number;\n /** Cell height in texels. */\n cellHeight: number;\n /** Per-corner UV/position inset (Babylon `SpriteRenderer` `epsilon`). */\n epsilon: number;\n /** Active blend mode applied by `renderSprites` before drawing. */\n blendMode: GLBlendMode;\n /** When `true`, `renderSprites` resets blend to {@link GLBlendMode.DISABLE}\n * after drawing (Babylon `autoResetAlpha`). */\n autoResetAlpha: boolean;\n /** Babylon-parity flag (no effect without a depth attachment). */\n disableDepthWrite: boolean;\n /** Maximum sprites per draw, fixed at creation. */\n readonly capacity: number;\n /** @internal The engine the renderer was created for. */\n _engine: GLEngineContext;\n /** @internal The compiled sprite effect this renderer owns. */\n _effect: GLEffect;\n /** @internal Sprite VAO (attribute pointers + element binding). Null until\n * built and after disposal; rebuilt on `webglcontextrestored`. */\n _vao: WebGLVertexArrayObject | null;\n /** @internal Dynamic vertex buffer, sized for `capacity` at creation. */\n _vbo: WebGLBuffer | null;\n /** @internal Static index buffer (`capacity * 6` `Uint16` indices). */\n _ibo: WebGLBuffer | null;\n /** @internal Preallocated CPU-side vertex scratch — reused every frame\n * (`renderSprites` performs zero allocations). */\n _vertexData: Float32Array;\n /** @internal Preallocated index data, uploaded once. */\n _indices: Uint16Array;\n /** @internal Context-restored handler — rebuilds the GPU buffers. */\n _restore: () => void;\n /** @internal True once disposed; subsequent calls are no-ops. */\n _disposed: boolean;\n}\n\n/* ──────────────────────────────── public API ───────────────────────────── */\n\n/**\n * Create a sprite renderer with its own GPU buffers and compiled effect.\n *\n * Preallocates the CPU vertex scratch and the index buffer at `capacity`, so\n * {@link renderSprites} performs no allocations. The sprite GPU buffers are\n * rebuilt automatically on `webglcontextrestored` (the owned effect is rebuilt\n * by the engine's context-restore protocol).\n *\n * @param engine - The engine to create GL resources on.\n * @param options - See {@link GLSpriteRendererOptions}.\n * @returns The new {@link GLSpriteRenderer}.\n * @throws If `capacity` is not an integer in `[1, 16384]`, or if a provided\n * `cellWidth`/`cellHeight` is not positive.\n */\nexport function createSpriteRenderer(engine: GLEngineContext, options: GLSpriteRendererOptions): GLSpriteRenderer {\n const capacity = options.capacity;\n if (!Number.isInteger(capacity) || capacity < 1 || capacity > MAX_CAPACITY) {\n throw new Error(`lite-gl: sprite renderer capacity must be an integer in [1, ${MAX_CAPACITY}], got ${capacity}`);\n }\n // cellWidth/cellHeight drive only the fixed-grid `cellIndex` path; manual-UV\n // consumers (the lottie atlas) omit them. Default to 1; reject explicit ≤ 0.\n const cellWidth = options.cellWidth ?? 1;\n const cellHeight = options.cellHeight ?? 1;\n if (!(cellWidth > 0) || !(cellHeight > 0)) {\n throw new Error(\"lite-gl: sprite renderer cellWidth/cellHeight must be > 0\");\n }\n\n const effect = createEffect(engine, {\n name: \"sprites\",\n vertexSource: SPRITE_VERTEX_SOURCE,\n fragmentSource: SPRITE_FRAGMENT_SOURCE,\n uniformNames: [\"view\", \"projection\"],\n samplerNames: [\"diffuseSampler\"],\n attributeNames: SPRITE_ATTRIBUTES,\n });\n\n // Build the static index buffer data once: [0,1,2, 0,2,3] per sprite.\n const indices = new Uint16Array(capacity * INDICES_PER_SPRITE);\n for (let i = 0; i < capacity; i++) {\n const v = i * VERTS_PER_SPRITE;\n const o = i * INDICES_PER_SPRITE;\n indices[o] = v;\n indices[o + 1] = v + 1;\n indices[o + 2] = v + 2;\n indices[o + 3] = v;\n indices[o + 4] = v + 2;\n indices[o + 5] = v + 3;\n }\n\n const renderer: GLSpriteRenderer = {\n texture: options.texture,\n cellWidth,\n cellHeight,\n epsilon: options.epsilon ?? SPRITE_EPSILON,\n blendMode: options.blendMode ?? GLBlendMode.ALPHA,\n autoResetAlpha: options.autoResetAlpha ?? true,\n disableDepthWrite: options.disableDepthWrite ?? false,\n capacity,\n _engine: engine,\n _effect: effect,\n _vao: null,\n _vbo: null,\n _ibo: null,\n _vertexData: new Float32Array(capacity * VERTS_PER_SPRITE * FLOATS_PER_VERTEX),\n _indices: indices,\n _restore: () => {},\n _disposed: false,\n };\n\n renderer._restore = (): void => {\n buildSpriteBuffers(renderer);\n };\n onContextRestored(engine, renderer._restore);\n buildSpriteBuffers(renderer);\n return renderer;\n}\n\n/**\n * Build the per-sprite vertex data and draw all visible sprites in one\n * `drawElements` call. Performs no allocations — the vertex scratch is reused\n * and uploaded with `bufferSubData`.\n *\n * No-op when the context is lost/disposed, the renderer is disposed, the\n * texture is not ready, the effect is not ready, or there are no visible\n * sprites. Sets the renderer's blend mode before drawing and resets to\n * {@link GLBlendMode.DISABLE} afterwards (matching Babylon's\n * `autoResetAlpha = true`), so a subsequent `drawEffect` is unaffected.\n *\n * @param renderer - The renderer to draw with.\n * @param sprites - The sprites to draw (only `isVisible !== false` are drawn;\n * excess beyond `capacity` is ignored, matching Babylon).\n * @param deltaTime - Accepted for Babylon API parity; unused (lite-gl `GLSprite`\n * holds no animation state, so `cellIndex` is consumer-driven).\n * @param viewMatrix - Column-major 4x4 view matrix.\n * @param projectionMatrix - Column-major 4x4 projection matrix.\n */\nexport function renderSprites(\n renderer: GLSpriteRenderer,\n sprites: readonly GLSprite[],\n deltaTime: number,\n viewMatrix: Float32Array | number[],\n projectionMatrix: Float32Array | number[]\n): void {\n const engine = renderer._engine;\n if (engine._isLost || engine._disposed || renderer._disposed) {\n return;\n }\n // `deltaTime` is accepted for Babylon `SpriteRenderer.render` parity but\n // unused: `GLSprite` carries no animation state, so `cellIndex` is driven\n // entirely by the consumer. Referenced here to keep the parameter name in\n // the public signature without tripping `noUnusedParameters`.\n void deltaTime;\n const tex = renderer.texture;\n if (!tex.isReady || sprites.length === 0) {\n return;\n }\n const effect = renderer._effect;\n if (!isEffectReady(engine, effect)) {\n return;\n }\n if (renderer._vao === null || renderer._vbo === null) {\n return;\n }\n\n // ── Build vertex data (allocation-free) ──────────────────────────────────\n const vd = renderer._vertexData;\n const eps = renderer.epsilon;\n const texW = tex.width;\n const texH = tex.height;\n const cellW = renderer.cellWidth;\n const cellH = renderer.cellHeight;\n const rowSize = texW / cellW; // cells per sheet row\n const cellWidthN = cellW / texW;\n const cellHeightN = cellH / texH;\n const cap = renderer.capacity;\n const count = sprites.length;\n let visible = 0;\n for (let i = 0; i < count && visible < cap; i++) {\n const sprite = sprites[i];\n if (sprite === undefined || sprite.isVisible === false) {\n continue;\n }\n // UV rect — manual per-sprite rect (Babylon `ThinSprite._xOffset/_xSize`\n // path, selected when `uSize` is set) or the fixed `cellIndex` grid.\n // Both resolve to a normalized `(left, top, widthN, heightN)` rectangle,\n // matching Babylon's `_appendSpriteVertex` vertex layout exactly.\n let cellLeft: number;\n let cellTop: number;\n let cellWN: number;\n let cellHN: number;\n if (sprite.uSize !== undefined) {\n cellLeft = sprite.uOffset ?? 0;\n cellTop = sprite.vOffset ?? 0;\n cellWN = sprite.uSize / texW;\n cellHN = (sprite.vSize ?? 0) / texH;\n } else {\n const cellIndex = (sprite.cellIndex ?? 0) > 0 ? (sprite.cellIndex as number) : 0;\n const row = (cellIndex / rowSize) >> 0;\n cellLeft = ((cellIndex - row * rowSize) * cellW) / texW;\n cellTop = (row * cellH) / texH;\n cellWN = cellWidthN;\n cellHN = cellHeightN;\n }\n\n const px = sprite.position.x;\n const py = sprite.position.y;\n const pz = sprite.position.z;\n const angle = sprite.angle;\n const w = sprite.width;\n const h = sprite.height;\n const invU = sprite.invertU === true ? 1 : 0;\n const invV = sprite.invertV === true ? 1 : 0;\n const color = sprite.color;\n const cr = color !== undefined ? color.r : 1;\n const cg = color !== undefined ? color.g : 1;\n const cb = color !== undefined ? color.b : 1;\n const ca = color !== undefined ? color.a : 1;\n\n let off = visible * VERTS_PER_SPRITE * FLOATS_PER_VERTEX;\n for (let c = 0; c < VERTS_PER_SPRITE; c++) {\n const ox = CORNER_OFFSET_X[c] === 0 ? eps : 1 - eps;\n const oy = CORNER_OFFSET_Y[c] === 0 ? eps : 1 - eps;\n vd[off] = px;\n vd[off + 1] = py;\n vd[off + 2] = pz;\n vd[off + 3] = angle;\n vd[off + 4] = w;\n vd[off + 5] = h;\n vd[off + 6] = ox;\n vd[off + 7] = oy;\n vd[off + 8] = invU;\n vd[off + 9] = invV;\n vd[off + 10] = cellLeft;\n vd[off + 11] = cellTop;\n vd[off + 12] = cellWN;\n vd[off + 13] = cellHN;\n vd[off + 14] = cr;\n vd[off + 15] = cg;\n vd[off + 16] = cb;\n vd[off + 17] = ca;\n off += FLOATS_PER_VERTEX;\n }\n visible++;\n }\n if (visible === 0) {\n return;\n }\n\n // ── Upload + draw ────────────────────────────────────────────────────────\n const gl = engine.gl;\n const s = engine._state;\n const vao = renderer._vao;\n if (s.boundVao !== vao) {\n gl.bindVertexArray(vao);\n s.boundVao = vao;\n // Binding the VAO restores its element-array binding (VAO state).\n s.boundElementBuffer = renderer._ibo;\n }\n const vbo = renderer._vbo;\n if (s.boundArrayBuffer !== vbo) {\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n s.boundArrayBuffer = vbo;\n }\n const floatCount = visible * VERTS_PER_SPRITE * FLOATS_PER_VERTEX;\n gl.bufferSubData(gl.ARRAY_BUFFER, 0, vd, 0, floatCount);\n\n useEffect(engine, effect);\n const viewLoc = effect.uniformLocations[\"view\"];\n if (viewLoc !== null && viewLoc !== undefined) {\n gl.uniformMatrix4fv(viewLoc, false, viewMatrix);\n }\n const projLoc = effect.uniformLocations[\"projection\"];\n if (projLoc !== null && projLoc !== undefined) {\n gl.uniformMatrix4fv(projLoc, false, projectionMatrix);\n }\n setEffectTexture(engine, effect, \"diffuseSampler\", tex);\n\n setBlendMode(engine, renderer.blendMode);\n applyGLStates(engine);\n gl.drawElements(gl.TRIANGLES, visible * INDICES_PER_SPRITE, gl.UNSIGNED_SHORT, 0);\n // Auto-reset (Babylon `autoResetAlpha = true`): leave blend disabled so a\n // subsequent fullscreen `drawEffect` renders with the same state as before.\n // When `autoResetAlpha` is false (lottie), keep `renderer.blendMode` applied\n // so a premultiplied-alpha mode persists across multiple atlas-page passes.\n if (renderer.autoResetAlpha) {\n setBlendMode(engine, GLBlendMode.DISABLE);\n }\n}\n\n/** Swap the sprite-sheet texture (≙ Babylon assigning `SpriteRenderer.texture`\n * after an async load). The cell size is unchanged — adjust `cellWidth` /\n * `cellHeight` on the renderer directly if the new sheet differs. No-op when\n * the renderer is disposed. */\nexport function setSpriteRendererTexture(renderer: GLSpriteRenderer, texture: GLTexture): void {\n if (renderer._disposed) {\n return;\n }\n renderer.texture = texture;\n}\n\n/** Release the renderer's VAO/VBO/IBO and the effect it owns, and unregister\n * its context-restore handler. Idempotent. Does NOT dispose the texture — the\n * consumer that supplied it owns its lifetime. */\nexport function disposeSpriteRenderer(renderer: GLSpriteRenderer): void {\n if (renderer._disposed) {\n return;\n }\n renderer._disposed = true;\n const engine = renderer._engine;\n offContextRestored(engine, renderer._restore);\n disposeEffect(engine, renderer._effect);\n if (!engine._isLost && !engine._disposed) {\n const gl = engine.gl;\n const s = engine._state;\n if (renderer._vao !== null) {\n gl.deleteVertexArray(renderer._vao);\n if (s.boundVao === renderer._vao) {\n s.boundVao = null;\n }\n }\n if (renderer._vbo !== null) {\n gl.deleteBuffer(renderer._vbo);\n if (s.boundArrayBuffer === renderer._vbo) {\n s.boundArrayBuffer = null;\n }\n }\n if (renderer._ibo !== null) {\n gl.deleteBuffer(renderer._ibo);\n if (s.boundElementBuffer === renderer._ibo) {\n s.boundElementBuffer = null;\n }\n }\n }\n renderer._vao = null;\n renderer._vbo = null;\n renderer._ibo = null;\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** (Re)create the VAO + VBO + IBO and configure the six vertex attributes.\n * Called from `createSpriteRenderer` and from the `webglcontextrestored`\n * handler (the prior handles are dead per the WebGL spec — not deleted here).\n * No-op when the context is lost/disposed. */\nfunction buildSpriteBuffers(renderer: GLSpriteRenderer): void {\n const engine = renderer._engine;\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n\n const vao = gl.createVertexArray();\n if (vao === null) {\n throw new Error(\"lite-gl: gl.createVertexArray returned null (sprite VAO)\");\n }\n renderer._vao = vao;\n gl.bindVertexArray(vao);\n s.boundVao = vao;\n\n const vbo = gl.createBuffer();\n if (vbo === null) {\n throw new Error(\"lite-gl: gl.createBuffer returned null (sprite VBO)\");\n }\n renderer._vbo = vbo;\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n s.boundArrayBuffer = vbo;\n // Allocate the dynamic vertex storage at full capacity; filled per frame.\n gl.bufferData(gl.ARRAY_BUFFER, renderer._vertexData.byteLength, gl.DYNAMIC_DRAW);\n\n // Attribute pointers — locations match SPRITE_ATTRIBUTES / shader layout.\n gl.enableVertexAttribArray(0);\n gl.vertexAttribPointer(0, 4, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 0);\n gl.enableVertexAttribArray(1);\n gl.vertexAttribPointer(1, 2, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 4 * BYTES_PER_FLOAT);\n gl.enableVertexAttribArray(2);\n gl.vertexAttribPointer(2, 2, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 6 * BYTES_PER_FLOAT);\n gl.enableVertexAttribArray(3);\n gl.vertexAttribPointer(3, 2, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 8 * BYTES_PER_FLOAT);\n gl.enableVertexAttribArray(4);\n gl.vertexAttribPointer(4, 4, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 10 * BYTES_PER_FLOAT);\n gl.enableVertexAttribArray(5);\n gl.vertexAttribPointer(5, 4, gl.FLOAT, false, VERTEX_STRIDE_BYTES, 14 * BYTES_PER_FLOAT);\n\n const ibo = gl.createBuffer();\n if (ibo === null) {\n throw new Error(\"lite-gl: gl.createBuffer returned null (sprite IBO)\");\n }\n renderer._ibo = ibo;\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);\n s.boundElementBuffer = ibo;\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, renderer._indices, gl.STATIC_DRAW);\n}\n"],"names":[],"mappings":"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"}
package/state--j_ncWIi.js DELETED
@@ -1,155 +0,0 @@
1
- function applyGLStates(engine) {
2
- const s = engine._state;
3
- if (engine._isLost || engine._disposed || !s.statesDirty) {
4
- return;
5
- }
6
- if (s._flushBlend !== void 0) {
7
- s._flushBlend(engine);
8
- }
9
- if (s._flushDepthCull !== void 0) {
10
- s._flushDepthCull(engine);
11
- }
12
- if (s._flushStencil !== void 0) {
13
- s._flushStencil(engine);
14
- }
15
- if (s._flushColorMask !== void 0) {
16
- s._flushColorMask(engine);
17
- }
18
- s.statesDirty = false;
19
- }
20
- const RS_BLEND_ENABLED = 0;
21
- const RS_BLEND_SRC_RGB = 1;
22
- const RS_BLEND_DST_RGB = 2;
23
- const RS_BLEND_SRC_A = 3;
24
- const RS_BLEND_DST_A = 4;
25
- const RS_BLEND_EQ_RGB = 5;
26
- const RS_BLEND_EQ_A = 6;
27
- const RS_DEPTH_TEST = 7;
28
- const RS_DEPTH_MASK = 8;
29
- const RS_DEPTH_FUNC = 9;
30
- const RS_CULL_ENABLED = 10;
31
- const RS_CULL_FACE = 11;
32
- const RS_STENCIL_TEST = 12;
33
- const RS_STENCIL_MASK = 13;
34
- const RS_STENCIL_FUNC_FUNC = 14;
35
- const RS_STENCIL_FUNC_REF = 15;
36
- const RS_STENCIL_FUNC_MASK = 16;
37
- const RS_STENCIL_OP_FAIL = 17;
38
- const RS_STENCIL_OP_ZFAIL = 18;
39
- const RS_STENCIL_OP_ZPASS = 19;
40
- const RS_COLOR_MASK = 20;
41
- const RS_DESIRED = 21;
42
- const RS_CLEAR_R = 42;
43
- const RS_CLEAR_G = 43;
44
- const RS_CLEAR_B = 44;
45
- const RS_CLEAR_A = 45;
46
- function applyRenderStateSentinels(rs) {
47
- for (const i of [RS_BLEND_ENABLED, RS_DEPTH_TEST, RS_DEPTH_MASK, RS_CULL_ENABLED, RS_STENCIL_TEST, RS_STENCIL_MASK, RS_COLOR_MASK]) {
48
- rs[i] = -1;
49
- rs[i + RS_DESIRED] = -1;
50
- }
51
- rs[RS_CLEAR_R] = rs[RS_CLEAR_G] = rs[RS_CLEAR_B] = rs[RS_CLEAR_A] = -1;
52
- }
53
- function createRenderStateArray() {
54
- const rs = new Float64Array(46);
55
- applyRenderStateSentinels(rs);
56
- return rs;
57
- }
58
- function resetRenderStateArray(rs) {
59
- rs.fill(0);
60
- applyRenderStateSentinels(rs);
61
- }
62
- function createGLState(maxTextureUnits) {
63
- return {
64
- currentProgram: null,
65
- activeTextureUnit: 0,
66
- boundTextures: new Array(maxTextureUnits).fill(null),
67
- boundArrayBuffer: null,
68
- boundElementBuffer: null,
69
- boundVao: null,
70
- viewportX: 0,
71
- viewportY: 0,
72
- viewportW: 0,
73
- viewportH: 0,
74
- boundFramebuffer: null,
75
- rs: createRenderStateArray(),
76
- statesDirty: false,
77
- scissorEnabled: -1,
78
- scissorX: 0,
79
- scissorY: 0,
80
- scissorW: 0,
81
- scissorH: 0,
82
- unpackAlignment: -1,
83
- unpackFlipY: -1,
84
- unpackPremultiplyAlpha: -1,
85
- enabledAttribs: [],
86
- instanceLocations: [],
87
- quadVbo: null,
88
- quadIbo: null,
89
- quadVao: null
90
- };
91
- }
92
- function resetGLStateCache(state) {
93
- state.currentProgram = null;
94
- state.activeTextureUnit = 0;
95
- state.boundTextures.fill(null);
96
- state.boundArrayBuffer = null;
97
- state.boundElementBuffer = null;
98
- state.boundVao = null;
99
- state.viewportX = 0;
100
- state.viewportY = 0;
101
- state.viewportW = 0;
102
- state.viewportH = 0;
103
- state.boundFramebuffer = null;
104
- resetRenderStateArray(state.rs);
105
- state.statesDirty = false;
106
- state.scissorEnabled = -1;
107
- state.scissorX = 0;
108
- state.scissorY = 0;
109
- state.scissorW = 0;
110
- state.scissorH = 0;
111
- state.unpackAlignment = -1;
112
- state.unpackFlipY = -1;
113
- state.unpackPremultiplyAlpha = -1;
114
- state.enabledAttribs.length = 0;
115
- state.instanceLocations.length = 0;
116
- }
117
- function resetGLState(state) {
118
- resetGLStateCache(state);
119
- state.quadVbo = null;
120
- state.quadIbo = null;
121
- state.quadVao = null;
122
- }
123
- export {
124
- createGLState as A,
125
- resetGLState as B,
126
- resetGLStateCache as C,
127
- RS_DEPTH_TEST as R,
128
- applyGLStates as a,
129
- RS_DESIRED as b,
130
- RS_DEPTH_MASK as c,
131
- RS_DEPTH_FUNC as d,
132
- RS_CULL_ENABLED as e,
133
- RS_CULL_FACE as f,
134
- RS_STENCIL_TEST as g,
135
- RS_STENCIL_MASK as h,
136
- RS_STENCIL_FUNC_FUNC as i,
137
- RS_STENCIL_FUNC_REF as j,
138
- RS_STENCIL_FUNC_MASK as k,
139
- RS_STENCIL_OP_FAIL as l,
140
- RS_STENCIL_OP_ZFAIL as m,
141
- RS_STENCIL_OP_ZPASS as n,
142
- RS_COLOR_MASK as o,
143
- RS_CLEAR_R as p,
144
- RS_CLEAR_G as q,
145
- RS_CLEAR_B as r,
146
- RS_CLEAR_A as s,
147
- RS_BLEND_ENABLED as t,
148
- RS_BLEND_EQ_RGB as u,
149
- RS_BLEND_EQ_A as v,
150
- RS_BLEND_SRC_RGB as w,
151
- RS_BLEND_DST_RGB as x,
152
- RS_BLEND_SRC_A as y,
153
- RS_BLEND_DST_A as z
154
- };
155
- //# sourceMappingURL=state--j_ncWIi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state--j_ncWIi.js","sources":["../src/apply-states.ts","../src/state.ts"],"sourcesContent":["/**\n * Deferred render-state flush dispatcher — the lite-gl counterpart of Babylon's\n * `Engine.applyStates()` (`_depthCullingState.apply` / `_alphaState.apply` /\n * `_stencilState.apply`).\n *\n * blend.ts and depth-stencil.ts setters record only the DESIRED state (the\n * `rs[RS_X + RS_DESIRED]` slots of {@link GLState.rs}), raise `statesDirty`, and\n * INSTALL their per-category reconciler onto a `_state._flush*` slot the first\n * time they run. {@link applyGLStates} then simply dispatches through whichever\n * slots are populated — it owns NO reconciliation code itself.\n *\n * Why a dispatcher (not a monolith): the reconcilers (`flushBlend` in blend.ts;\n * `flushDepthCull` / `flushStencil` / `flushColorMask` in depth-stencil.ts) are\n * reachable ONLY through the engine-state slots their setters populate, so a\n * category whose setter is absent from a scene tree-shakes its reconciler — and\n * its GL code — out of the bundle. A clear-only scene (e.g. `gl-scissor`) that\n * never touches blend/depth/stencil/color-mask therefore ships none of them;\n * `applyGLStates` collapses to four cheap \"is it installed?\" checks. The fixed\n * dispatch order (blend → depth+cull → stencil → color-mask) reproduces the\n * former monolith's GL call order exactly.\n *\n * Each reconciler still issues only the `gl.*` calls that actually change and\n * updates the actual slots in lock-step, so intra-frame churn collapses and\n * cross-frame elision is preserved, matching Babylon exactly.\n *\n * Flush sites (call `applyGLStates` immediately before the GPU op):\n * - effect-renderer.ts `drawEffect`\n * - sprites.ts `renderSprites`\n * - mesh.ts `drawIndexed`\n * - depth-stencil.ts `clearEngine` (clear respects the depth/stencil/color\n * write masks, so they must be current first — Babylon parity)\n *\n * Kept dependency-light (type-only import of {@link GLEngineContext}) so it never\n * introduces an import cycle.\n */\nimport type { GLEngineContext } from \"./context.js\";\n\n/**\n * Flush the deferred blend / depth+cull / stencil / color-mask state to GL by\n * invoking each installed per-category reconciler in order. No-op on a\n * lost/disposed context or when nothing has been marked dirty since the last\n * flush. Reconcilers are installed lazily by their setters, so an uninstalled\n * category is skipped at zero cost.\n *\n * @param engine - The engine whose deferred state is flushed.\n * @internal\n */\nexport function applyGLStates(engine: GLEngineContext): void {\n const s = engine._state;\n if (engine._isLost || engine._disposed || !s.statesDirty) {\n return;\n }\n if (s._flushBlend !== undefined) {\n s._flushBlend(engine);\n }\n if (s._flushDepthCull !== undefined) {\n s._flushDepthCull(engine);\n }\n if (s._flushStencil !== undefined) {\n s._flushStencil(engine);\n }\n if (s._flushColorMask !== undefined) {\n s._flushColorMask(engine);\n }\n s.statesDirty = false;\n}\n","import type { GLEngineContext } from \"./context.js\";\n\n/* ─── Deferred render-state index-array layout ────────────────────────────────\n * The deferred render-state (blend / depth / cull / stencil / color-mask) lives\n * in a single flat `Float64Array(46)` on `GLState.rs`: slots `0..20` hold the\n * ACTUAL applied GL state, slots `21..41` (`RS_X + RS_DESIRED`) the DESIRED twin,\n * and slots `42..45` the standalone (no-desired-twin) cached `gl.clearColor` RGBA.\n *\n * These `@internal` index consts are imported by blend.ts / depth-stencil.ts /\n * apply-states.ts. Because they are plain `const` integers, esbuild inlines each\n * to a 1–2 char literal (`rs[RS_BLEND_SRC_RGB + RS_DESIRED]` → `rs[22]`) when\n * bundling a scene — far smaller than the old cross-module `.dBlendSrcRGB` named\n * props, which could not be mangled and shipped verbatim in every bundle.\n *\n * Float64Array (NOT Int32Array) is required: `RS_STENCIL_MASK` /\n * `RS_STENCIL_FUNC_MASK` can be `0xFFFFFFFF`, which Int32 would store as `-1` and\n * collide with the `-1` \"unset\" sentinel; Float64 keeps `4294967295` distinct. */\n/** @internal */ export const RS_BLEND_ENABLED = 0;\n/** @internal */ export const RS_BLEND_SRC_RGB = 1;\n/** @internal */ export const RS_BLEND_DST_RGB = 2;\n/** @internal */ export const RS_BLEND_SRC_A = 3;\n/** @internal */ export const RS_BLEND_DST_A = 4;\n/** @internal */ export const RS_BLEND_EQ_RGB = 5;\n/** @internal */ export const RS_BLEND_EQ_A = 6;\n/** @internal */ export const RS_DEPTH_TEST = 7;\n/** @internal */ export const RS_DEPTH_MASK = 8;\n/** @internal */ export const RS_DEPTH_FUNC = 9;\n/** @internal */ export const RS_CULL_ENABLED = 10;\n/** @internal */ export const RS_CULL_FACE = 11;\n/** @internal */ export const RS_STENCIL_TEST = 12;\n/** @internal */ export const RS_STENCIL_MASK = 13;\n/** @internal */ export const RS_STENCIL_FUNC_FUNC = 14;\n/** @internal */ export const RS_STENCIL_FUNC_REF = 15;\n/** @internal */ export const RS_STENCIL_FUNC_MASK = 16;\n/** @internal */ export const RS_STENCIL_OP_FAIL = 17;\n/** @internal */ export const RS_STENCIL_OP_ZFAIL = 18;\n/** @internal */ export const RS_STENCIL_OP_ZPASS = 19;\n/** @internal */ export const RS_COLOR_MASK = 20;\n/** @internal Offset from an ACTUAL slot (`0..20`) to its DESIRED twin (`21..41`). */\nexport const RS_DESIRED = 21;\n/* Standalone cached gl.clearColor RGBA slots (`42..45`) — NO desired twin; a\n * simple apply-on-clear cache like viewport/scissor, stored in `rs` (not as named\n * GLState fields) so the index access mangles small instead of shipping\n * `.clearColorR` verbatim in every bundle. */\n/** @internal */ export const RS_CLEAR_R = 42;\n/** @internal */ export const RS_CLEAR_G = 43;\n/** @internal */ export const RS_CLEAR_B = 44;\n/** @internal */ export const RS_CLEAR_A = 45;\n\n/**\n * GL-state cache type. Owned by `GLEngineContext._state`.\n *\n * Two flavours of cached state coexist here:\n *\n * - **Eager bindings** (program / buffers / textures / VAO / framebuffer /\n * viewport / scissor / unpack). Each binding setter issues its `gl.*` call\n * immediately and updates the matching field in lock-step, eliding the call\n * when the cache already matches.\n * - **Deferred render-state** (blend / depth / cull / stencil / color-mask),\n * stored in the {@link GLState.rs} index-array. These follow Babylon's\n * `applyStates()` model: each setter records only the DESIRED slot\n * (`rs[RS_X + RS_DESIRED]`) and sets `statesDirty`; the real `gl.*` calls are\n * flushed by {@link applyGLStates} (apply-states.ts) immediately before each\n * draw / clear, reconciling DESIRED → ACTUAL and writing the actual slots\n * (`rs[RS_X]`) in lock-step. Both halves keep their `-1`/`0` unset sentinels.\n *\n * See `00-lite-gl.md` §4 for the full table of cached operations and the\n * deferred-state flush sites.\n *\n * INVARIANTS:\n * - The cache is the source of truth. If consumers poke `engine.gl.*` directly\n * they will silently corrupt this state.\n * - On `webglcontextlost` the whole `rs` array (both the actual and desired\n * halves) is reset to its initial sentinels (handles are dead anyway;\n * subsequent setters bail out on `engine._isLost`, and a post-restore setter\n * re-marks `statesDirty`).\n */\nexport interface GLState {\n currentProgram: WebGLProgram | null;\n activeTextureUnit: number;\n /** Per-unit binding; length === caps.maxTextureUnits. */\n boundTextures: (WebGLTexture | null)[];\n boundArrayBuffer: WebGLBuffer | null;\n boundElementBuffer: WebGLBuffer | null;\n boundVao: WebGLVertexArrayObject | null;\n viewportX: number;\n viewportY: number;\n viewportW: number;\n viewportH: number;\n /**\n * Currently-bound draw framebuffer, or `null` for the default (canvas)\n * framebuffer. Owned by the render-target module's `bindRenderTarget`\n * (binding `null` returns to the canvas). Reset to `null` on context-lost.\n */\n boundFramebuffer: WebGLFramebuffer | null;\n /**\n * Deferred render-state (blend / depth / cull / stencil / color-mask) packed\n * into ONE flat `Float64Array(46)`. Slots `0..20` (indexed by the `RS_*`\n * consts) are the ACTUAL applied GL state — what {@link applyGLStates} last\n * wrote to the context; slots `21..41` (`rs[RS_X + RS_DESIRED]`) are the\n * DESIRED twin the setters record. The setters write ONLY the desired half\n * (never `gl.*`, never the actual half) and raise `statesDirty`;\n * `applyGLStates` reconciles each desired → its actual twin right before a\n * draw / clear, issuing only the GL calls that changed and updating the\n * actual half in lock-step. Both preset and arbitrary blend paths feed the\n * same desired slots, so they can never desync.\n *\n * Sentinels (identical for both halves): `-1` for the tri-state enables\n * (`RS_BLEND_ENABLED` / `RS_DEPTH_TEST` / `RS_DEPTH_MASK` / `RS_CULL_ENABLED`\n * / `RS_STENCIL_TEST`) and the mask caches (`RS_STENCIL_MASK` /\n * `RS_COLOR_MASK`); `0` for every func / equation / op / ref slot (no GL enum\n * is `0`). An unset desired equals its unset actual and is never flushed; the\n * `-1` blend/test sentinels guarantee the first applied state is never elided.\n * The blend func/equation slots are only trusted while `RS_BLEND_ENABLED` is\n * `1` — the disabled→enabled transition re-issues both (matching Babylon's\n * `AlphaState`, which does not track them while blending is off).\n *\n * Float64 (not Int32): `RS_STENCIL_MASK` / `RS_STENCIL_FUNC_MASK` can be\n * `0xFFFFFFFF`, which Int32 stores as `-1` — colliding with the `-1` unset\n * sentinel. Reset on context-lost. */\n rs: Float64Array;\n /** `true` when at least one deferred-state setter ran since the last\n * {@link applyGLStates}. Gates the flush so an unchanged frame issues no\n * reconciliation work. */\n statesDirty: boolean;\n /* ─── Deferred render-state appliers (per-category, lazily installed) ──────\n * Each category's reconciler (blend / depth+cull / stencil / color-mask) is\n * installed onto its slot the first time the matching setter runs — a runtime\n * assignment, NOT a module-level side effect. `applyGLStates` dispatches ONLY\n * through these slots, so the reconcilers (and their GL reconciliation code)\n * are reachable only when their setter is in the bundle: a scene that never\n * touches a category tree-shakes its reconciler out entirely (e.g. a clear-\n * only scene drops all four). Left undefined until installed; never cleared on\n * context-lost (a post-restore setter re-installs idempotently). */\n /** @internal Blend reconciler (Babylon's `_alphaState`). */\n _flushBlend?: (engine: GLEngineContext) => void;\n /** @internal Depth + cull reconciler (Babylon's `_depthCullingState`). */\n _flushDepthCull?: (engine: GLEngineContext) => void;\n /** @internal Stencil reconciler (Babylon's `_stencilState`). */\n _flushStencil?: (engine: GLEngineContext) => void;\n /** @internal Color-write-mask reconciler (Babylon's `setColorWrite`). */\n _flushColorMask?: (engine: GLEngineContext) => void;\n /** Scissor-test enable tri-state (`-1` unset, `0` off, `1` on). */\n scissorEnabled: number;\n scissorX: number;\n scissorY: number;\n scissorW: number;\n scissorH: number;\n /** Cached `gl.pixelStorei(UNPACK_ALIGNMENT)`, or `-1` when unset. */\n unpackAlignment: number;\n /** Cached `gl.pixelStorei(UNPACK_FLIP_Y_WEBGL)`, or `-1` when unset. */\n unpackFlipY: number;\n /** Cached `gl.pixelStorei(UNPACK_PREMULTIPLY_ALPHA_WEBGL)`, or `-1` unset. */\n unpackPremultiplyAlpha: number;\n /**\n * Per-location vertex-attribute enable flags for the DEFAULT (null) VAO —\n * the mesh / instancing path (mirrors Babylon's `_vertexAttribArraysEnabled`).\n * Index is the attribute location. lite-gl's quad / sprite paths use their\n * own VAOs and do not touch this. Cleared on context-lost.\n */\n enabledAttribs: boolean[];\n /**\n * Attribute locations currently configured with a non-default vertex divisor\n * (instanced attributes), mirroring Babylon's `_currentInstanceLocations`.\n * `unbindInstanceAttributes` resets each back to divisor 0 and clears this.\n */\n instanceLocations: number[];\n /** Shared fullscreen quad — lazily created on first `applyEffectWrapper`. */\n quadVbo: WebGLBuffer | null;\n quadIbo: WebGLBuffer | null;\n quadVao: WebGLVertexArrayObject | null;\n}\n\n/** Indices in `rs` whose unset sentinel is `-1` (the tri-state enables + the\n * `stencilMask` / `colorMask` caches). Every other slot defaults to `0`. The\n * sentinel is written to BOTH the actual (`i`) and desired (`i + RS_DESIRED`)\n * halves. Kept as a function-local literal so it stays a runtime value (no\n * module-level allocation / side effect). */\nfunction applyRenderStateSentinels(rs: Float64Array): void {\n for (const i of [RS_BLEND_ENABLED, RS_DEPTH_TEST, RS_DEPTH_MASK, RS_CULL_ENABLED, RS_STENCIL_TEST, RS_STENCIL_MASK, RS_COLOR_MASK]) {\n rs[i] = -1;\n rs[i + RS_DESIRED] = -1;\n }\n // clearColor RGBA (standalone, no DESIRED twin) — `-1` forces the first clear\n // to issue gl.clearColor (valid components are 0..1).\n rs[RS_CLEAR_R] = rs[RS_CLEAR_G] = rs[RS_CLEAR_B] = rs[RS_CLEAR_A] = -1;\n}\n\n/** Allocate the 46-slot deferred render-state array (21 actual + 21 desired + 4\n * standalone clearColor) initialised to its unset sentinels — a fresh\n * `Float64Array` is already all `0`, so only the `-1` slots need writing. */\nfunction createRenderStateArray(): Float64Array {\n const rs = new Float64Array(46);\n applyRenderStateSentinels(rs);\n return rs;\n}\n\n/** Re-initialise a live render-state array in place: zero every slot, then\n * restore the `-1` sentinels. */\nfunction resetRenderStateArray(rs: Float64Array): void {\n rs.fill(0);\n applyRenderStateSentinels(rs);\n}\n\n/** Allocate a fresh, fully-null GLState sized for `maxTextureUnits`. */\nexport function createGLState(maxTextureUnits: number): GLState {\n return {\n currentProgram: null,\n activeTextureUnit: 0,\n boundTextures: new Array<WebGLTexture | null>(maxTextureUnits).fill(null),\n boundArrayBuffer: null,\n boundElementBuffer: null,\n boundVao: null,\n viewportX: 0,\n viewportY: 0,\n viewportW: 0,\n viewportH: 0,\n boundFramebuffer: null,\n rs: createRenderStateArray(),\n statesDirty: false,\n scissorEnabled: -1,\n scissorX: 0,\n scissorY: 0,\n scissorW: 0,\n scissorH: 0,\n unpackAlignment: -1,\n unpackFlipY: -1,\n unpackPremultiplyAlpha: -1,\n enabledAttribs: [],\n instanceLocations: [],\n quadVbo: null,\n quadIbo: null,\n quadVao: null,\n };\n}\n\n/** Reset only the cached \"current GL state\" — every binding (program / buffers /\n * textures / VAO / framebuffer) and render-state (blend / depth / stencil /\n * scissor / color-mask / viewport / unpack) field, including the whole `rs`\n * deferred render-state array (BOTH the actual applied values and the DESIRED\n * twins) plus `statesDirty` — to its unset sentinel, WITHOUT discarding owned\n * GPU resources (the shared quad). After this, the next setter in each category\n * is re-issued rather than elided.\n *\n * Used by `resetGLState` (context-lost) and by `wipeGLStateCache` (a host that\n * shares the GL context calling in after mutating raw `gl.*` state). The shared\n * quad's GL objects are still alive in the latter case, so they are preserved\n * here to avoid leaking + needlessly rebuilding them every render scope. */\nexport function resetGLStateCache(state: GLState): void {\n state.currentProgram = null;\n state.activeTextureUnit = 0;\n state.boundTextures.fill(null);\n state.boundArrayBuffer = null;\n state.boundElementBuffer = null;\n state.boundVao = null;\n state.viewportX = 0;\n state.viewportY = 0;\n state.viewportW = 0;\n state.viewportH = 0;\n state.boundFramebuffer = null;\n resetRenderStateArray(state.rs);\n state.statesDirty = false;\n state.scissorEnabled = -1;\n state.scissorX = 0;\n state.scissorY = 0;\n state.scissorW = 0;\n state.scissorH = 0;\n state.unpackAlignment = -1;\n state.unpackFlipY = -1;\n state.unpackPremultiplyAlpha = -1;\n state.enabledAttribs.length = 0;\n state.instanceLocations.length = 0;\n}\n\n/** Zero the cache in-place. Used by the context-lost handler — GL handles are\n * already dead per WebGL spec; we forget what we knew about them (including the\n * shared quad, whose GL objects are gone and must be rebuilt) so the next\n * bind/use after restore is NOT incorrectly elided. */\nexport function resetGLState(state: GLState): void {\n resetGLStateCache(state);\n state.quadVbo = null;\n state.quadIbo = null;\n state.quadVao = null;\n}\n"],"names":[],"mappings":"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"}
@@ -1,329 +0,0 @@
1
- function setUnpackState(engine, flipY, premultiplyAlpha, alignment = 4) {
2
- const gl = engine.gl;
3
- const s = engine._state;
4
- const fy = flipY ? 1 : 0;
5
- if (s.unpackFlipY !== fy) {
6
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, fy);
7
- s.unpackFlipY = fy;
8
- }
9
- const pm = premultiplyAlpha ? 1 : 0;
10
- if (s.unpackPremultiplyAlpha !== pm) {
11
- gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, pm);
12
- s.unpackPremultiplyAlpha = pm;
13
- }
14
- if (s.unpackAlignment !== alignment) {
15
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);
16
- s.unpackAlignment = alignment;
17
- }
18
- }
19
- function createRawTexture(engine, data, width, height, format, type, options) {
20
- const gl = engine.gl;
21
- const handle = gl.createTexture();
22
- if (handle === null) {
23
- throw new Error("lite-gl: gl.createTexture returned null");
24
- }
25
- const opts = options ?? {};
26
- const minFilter = opts.minFilter ?? gl.LINEAR;
27
- const magFilter = opts.magFilter ?? gl.LINEAR;
28
- const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;
29
- const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;
30
- const invertY = opts.invertY ?? false;
31
- const premultiply = opts.premultiplyAlpha ?? false;
32
- const internalFormat = opts.internalFormat ?? resolveLdrInternalFormat(gl, format, type);
33
- let curData = data;
34
- let curWidth = width;
35
- let curHeight = height;
36
- let curAlign = opts.unpackAlignment ?? 4;
37
- const upload = (target) => {
38
- const g = target.gl;
39
- setUnpackState(target, invertY, premultiply, curAlign);
40
- bindTextureForUpload(target, tex.handle);
41
- g.texImage2D(g.TEXTURE_2D, 0, internalFormat, curWidth, curHeight, 0, format, type, curData);
42
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
43
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
44
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
45
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
46
- };
47
- const tex = {
48
- handle,
49
- target: gl.TEXTURE_2D,
50
- width,
51
- height,
52
- isReady: true,
53
- _disposed: false,
54
- _refCount: 1,
55
- _upload: upload,
56
- _wasReady: true
57
- };
58
- tex._updateRaw = (target, newData, newWidth, newHeight, unpackAlignment) => {
59
- curData = newData;
60
- curWidth = newWidth;
61
- curHeight = newHeight;
62
- curAlign = unpackAlignment;
63
- tex.width = newWidth;
64
- tex.height = newHeight;
65
- upload(target);
66
- };
67
- upload(engine);
68
- engine._textures.push(tex);
69
- return tex;
70
- }
71
- function createFloatTexture(engine, data, width, height, options) {
72
- const gl = engine.gl;
73
- const o = options ?? {};
74
- const format = o.format ?? gl.RGBA;
75
- const type = o.type ?? gl.HALF_FLOAT;
76
- const internalFormat = pickSizedInternalFormat(gl, format, type);
77
- return createRawTexture(engine, data, width, height, format, type, { ...o, internalFormat });
78
- }
79
- function generateTextureMipMaps(engine, tex) {
80
- if (engine._isLost || engine._disposed || tex._disposed || tex.handle === null) {
81
- return;
82
- }
83
- bindTextureForUpload(engine, tex.handle);
84
- engine.gl.generateMipmap(engine.gl.TEXTURE_2D);
85
- }
86
- function updateRawTexture(engine, tex, data, options) {
87
- if (engine._isLost || engine._disposed || tex._disposed || tex._updateRaw === void 0) {
88
- return;
89
- }
90
- const o = options ?? {};
91
- tex._updateRaw(engine, data, o.width ?? tex.width, o.height ?? tex.height, o.unpackAlignment ?? 4);
92
- }
93
- function updateTextureSamplingMode(engine, tex, minFilter, magFilter) {
94
- if (engine._isLost || engine._disposed || tex._disposed) {
95
- return;
96
- }
97
- const gl = engine.gl;
98
- bindTextureForUpload(engine, tex.handle);
99
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
100
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
101
- }
102
- function updateTextureWrapMode(engine, tex, wrapS, wrapT) {
103
- if (engine._isLost || engine._disposed || tex._disposed) {
104
- return;
105
- }
106
- const gl = engine.gl;
107
- bindTextureForUpload(engine, tex.handle);
108
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
109
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
110
- }
111
- function createTextureFromHandle(engine, handle, width, height, options) {
112
- const tex = {
113
- handle,
114
- target: engine.gl.TEXTURE_2D,
115
- width,
116
- height,
117
- isReady: true,
118
- _disposed: false,
119
- _refCount: 1,
120
- // External handle — restore replay is the external owner's job.
121
- _upload: () => {
122
- },
123
- _wasReady: true
124
- };
125
- if (options !== void 0) {
126
- const gl = engine.gl;
127
- bindTextureForUpload(engine, handle);
128
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, options.minFilter ?? gl.LINEAR);
129
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, options.magFilter ?? gl.LINEAR);
130
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, options.wrapS ?? gl.CLAMP_TO_EDGE);
131
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, options.wrapT ?? gl.CLAMP_TO_EDGE);
132
- }
133
- return tex;
134
- }
135
- function loadTexture2D(engine, url, options, onLoad, onError) {
136
- const gl = engine.gl;
137
- const handle = gl.createTexture();
138
- if (handle === null) {
139
- throw new Error("lite-gl: gl.createTexture returned null");
140
- }
141
- const opts = options ?? {};
142
- const minFilter = opts.minFilter ?? gl.LINEAR;
143
- const magFilter = opts.magFilter ?? gl.LINEAR;
144
- const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;
145
- const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;
146
- const invertY = opts.invertY ?? false;
147
- let bitmap = null;
148
- const placeholderPixels = new Uint8Array([0, 0, 0, 0]);
149
- const upload = (target) => {
150
- const g = target.gl;
151
- setUnpackState(target, false, false);
152
- bindTextureForUpload(target, tex.handle);
153
- if (bitmap !== null) {
154
- g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, bitmap);
155
- tex.width = bitmap.width;
156
- tex.height = bitmap.height;
157
- } else {
158
- g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, 1, 1, 0, g.RGBA, g.UNSIGNED_BYTE, placeholderPixels);
159
- }
160
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
161
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
162
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
163
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
164
- };
165
- const tex = {
166
- handle,
167
- target: gl.TEXTURE_2D,
168
- width: 1,
169
- height: 1,
170
- isReady: false,
171
- _disposed: false,
172
- _refCount: 1,
173
- _upload: upload,
174
- _wasReady: false
175
- };
176
- upload(engine);
177
- engine._textures.push(tex);
178
- fetch(url).then((r) => {
179
- if (!r.ok) {
180
- throw new Error(`lite-gl: fetch ${url} -> HTTP ${r.status}`);
181
- }
182
- return r.blob();
183
- }).then((blob) => createImageBitmap(blob, { premultiplyAlpha: "none", imageOrientation: invertY ? "flipY" : "none" })).then((bm) => {
184
- if (tex._disposed) {
185
- bm.close();
186
- return;
187
- }
188
- bitmap = bm;
189
- if (!engine._isLost) {
190
- upload(engine);
191
- tex.isReady = true;
192
- }
193
- tex._wasReady = true;
194
- if (onLoad !== void 0) {
195
- onLoad(tex);
196
- }
197
- }).catch((err) => {
198
- const e = err instanceof Error ? err : new Error(String(err));
199
- if (onError !== void 0) {
200
- onError(e);
201
- } else {
202
- console.error("lite-gl: loadTexture2D failed", e);
203
- }
204
- });
205
- return tex;
206
- }
207
- function bindTexture(engine, unit, tex) {
208
- if (engine._isLost || engine._disposed) {
209
- return;
210
- }
211
- if (tex !== null && tex._disposed) {
212
- return;
213
- }
214
- bindTextureRaw(engine, unit, tex === null ? null : tex.handle);
215
- }
216
- function bindTextureRaw(engine, unit, handle) {
217
- const s = engine._state;
218
- const gl = engine.gl;
219
- if (s.boundTextures[unit] === handle) {
220
- return;
221
- }
222
- if (s.activeTextureUnit !== unit) {
223
- gl.activeTexture(gl.TEXTURE0 + unit);
224
- s.activeTextureUnit = unit;
225
- }
226
- gl.bindTexture(gl.TEXTURE_2D, handle);
227
- s.boundTextures[unit] = handle;
228
- }
229
- function bindTextureForUpload(engine, handle) {
230
- const s = engine._state;
231
- const gl = engine.gl;
232
- if (s.activeTextureUnit !== 0) {
233
- gl.activeTexture(gl.TEXTURE0);
234
- s.activeTextureUnit = 0;
235
- }
236
- if (s.boundTextures[0] !== handle) {
237
- gl.bindTexture(gl.TEXTURE_2D, handle);
238
- s.boundTextures[0] = handle;
239
- }
240
- }
241
- function disposeTexture(engine, tex) {
242
- if (tex._disposed) {
243
- return;
244
- }
245
- if (tex._refCount > 1) {
246
- tex._refCount--;
247
- return;
248
- }
249
- tex._disposed = true;
250
- const i = engine._textures.indexOf(tex);
251
- if (i !== -1) {
252
- engine._textures.splice(i, 1);
253
- }
254
- if (!engine._isLost && !engine._disposed) {
255
- engine.gl.deleteTexture(tex.handle);
256
- }
257
- const bound = engine._state.boundTextures;
258
- for (let u = 0; u < bound.length; u++) {
259
- if (bound[u] === tex.handle) {
260
- bound[u] = null;
261
- }
262
- }
263
- }
264
- function resolveLdrInternalFormat(gl, format, type) {
265
- if (type === gl.UNSIGNED_BYTE) {
266
- if (format === gl.RGBA) {
267
- return gl.RGBA8;
268
- }
269
- if (format === gl.RGB) {
270
- return gl.RGB8;
271
- }
272
- if (format === gl.RG) {
273
- return gl.RG8;
274
- }
275
- if (format === gl.RED) {
276
- return gl.R8;
277
- }
278
- if (format === gl.LUMINANCE) {
279
- return gl.LUMINANCE;
280
- }
281
- }
282
- return format;
283
- }
284
- function pickSizedInternalFormat(gl, format, type) {
285
- if (type === gl.UNSIGNED_BYTE) {
286
- if (format === gl.RGBA) {
287
- return gl.RGBA8;
288
- }
289
- if (format === gl.RGB) {
290
- return gl.RGB8;
291
- }
292
- if (format === gl.LUMINANCE) {
293
- return gl.LUMINANCE;
294
- }
295
- }
296
- if (type === gl.FLOAT) {
297
- if (format === gl.RGBA) {
298
- return gl.RGBA32F;
299
- }
300
- if (format === gl.RGB) {
301
- return gl.RGB32F;
302
- }
303
- }
304
- if (type === gl.HALF_FLOAT) {
305
- if (format === gl.RGBA) {
306
- return gl.RGBA16F;
307
- }
308
- if (format === gl.RGB) {
309
- return gl.RGB16F;
310
- }
311
- }
312
- return format;
313
- }
314
- export {
315
- createRawTexture as a,
316
- bindTexture as b,
317
- createFloatTexture as c,
318
- createTextureFromHandle as d,
319
- disposeTexture as e,
320
- updateTextureSamplingMode as f,
321
- generateTextureMipMaps as g,
322
- updateTextureWrapMode as h,
323
- bindTextureForUpload as i,
324
- loadTexture2D as l,
325
- pickSizedInternalFormat as p,
326
- setUnpackState as s,
327
- updateRawTexture as u
328
- };
329
- //# sourceMappingURL=texture-DaMd1gGm.js.map