@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
package/state.js ADDED
@@ -0,0 +1,153 @@
1
+ /* ─── Deferred render-state index-array layout ────────────────────────────────
2
+ * The deferred render-state (blend / depth / cull / stencil / color-mask) lives
3
+ * in a single flat `Float64Array(46)` on `GLState.rs`: slots `0..20` hold the
4
+ * ACTUAL applied GL state, slots `21..41` (`RS_X + RS_DESIRED`) the DESIRED twin,
5
+ * and slots `42..45` the standalone (no-desired-twin) cached `gl.clearColor` RGBA.
6
+ *
7
+ * These `@internal` index consts are imported by blend.ts / depth-stencil.ts /
8
+ * apply-states.ts. Because they are plain `const` integers, esbuild inlines each
9
+ * to a 1–2 char literal (`rs[RS_BLEND_SRC_RGB + RS_DESIRED]` → `rs[22]`) when
10
+ * bundling a scene — far smaller than the old cross-module `.dBlendSrcRGB` named
11
+ * props, which could not be mangled and shipped verbatim in every bundle.
12
+ *
13
+ * Float64Array (NOT Int32Array) is required: `RS_STENCIL_MASK` /
14
+ * `RS_STENCIL_FUNC_MASK` can be `0xFFFFFFFF`, which Int32 would store as `-1` and
15
+ * collide with the `-1` "unset" sentinel; Float64 keeps `4294967295` distinct. */
16
+ /** @internal */ export const RS_BLEND_ENABLED = 0;
17
+ /** @internal */ export const RS_BLEND_SRC_RGB = 1;
18
+ /** @internal */ export const RS_BLEND_DST_RGB = 2;
19
+ /** @internal */ export const RS_BLEND_SRC_A = 3;
20
+ /** @internal */ export const RS_BLEND_DST_A = 4;
21
+ /** @internal */ export const RS_BLEND_EQ_RGB = 5;
22
+ /** @internal */ export const RS_BLEND_EQ_A = 6;
23
+ /** @internal */ export const RS_DEPTH_TEST = 7;
24
+ /** @internal */ export const RS_DEPTH_MASK = 8;
25
+ /** @internal */ export const RS_DEPTH_FUNC = 9;
26
+ /** @internal */ export const RS_CULL_ENABLED = 10;
27
+ /** @internal */ export const RS_CULL_FACE = 11;
28
+ /** @internal */ export const RS_STENCIL_TEST = 12;
29
+ /** @internal */ export const RS_STENCIL_MASK = 13;
30
+ /** @internal */ export const RS_STENCIL_FUNC_FUNC = 14;
31
+ /** @internal */ export const RS_STENCIL_FUNC_REF = 15;
32
+ /** @internal */ export const RS_STENCIL_FUNC_MASK = 16;
33
+ /** @internal */ export const RS_STENCIL_OP_FAIL = 17;
34
+ /** @internal */ export const RS_STENCIL_OP_ZFAIL = 18;
35
+ /** @internal */ export const RS_STENCIL_OP_ZPASS = 19;
36
+ /** @internal */ export const RS_COLOR_MASK = 20;
37
+ /** @internal Offset from an ACTUAL slot (`0..20`) to its DESIRED twin (`21..41`). */
38
+ export const RS_DESIRED = 21;
39
+ /* Standalone cached gl.clearColor RGBA slots (`42..45`) — NO desired twin; a
40
+ * simple apply-on-clear cache like viewport/scissor, stored in `rs` (not as named
41
+ * GLState fields) so the index access mangles small instead of shipping
42
+ * `.clearColorR` verbatim in every bundle. */
43
+ /** @internal */ export const RS_CLEAR_R = 42;
44
+ /** @internal */ export const RS_CLEAR_G = 43;
45
+ /** @internal */ export const RS_CLEAR_B = 44;
46
+ /** @internal */ export const RS_CLEAR_A = 45;
47
+ /** Indices in `rs` whose unset sentinel is `-1` (the tri-state enables + the
48
+ * `stencilMask` / `colorMask` caches). Every other slot defaults to `0`. The
49
+ * sentinel is written to BOTH the actual (`i`) and desired (`i + RS_DESIRED`)
50
+ * halves. Kept as a function-local literal so it stays a runtime value (no
51
+ * module-level allocation / side effect). */
52
+ function applyRenderStateSentinels(rs) {
53
+ 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]) {
54
+ rs[i] = -1;
55
+ rs[i + RS_DESIRED] = -1;
56
+ }
57
+ // clearColor RGBA (standalone, no DESIRED twin) — `-1` forces the first clear
58
+ // to issue gl.clearColor (valid components are 0..1).
59
+ rs[RS_CLEAR_R] = rs[RS_CLEAR_G] = rs[RS_CLEAR_B] = rs[RS_CLEAR_A] = -1;
60
+ }
61
+ /** Allocate the 46-slot deferred render-state array (21 actual + 21 desired + 4
62
+ * standalone clearColor) initialised to its unset sentinels — a fresh
63
+ * `Float64Array` is already all `0`, so only the `-1` slots need writing. */
64
+ function createRenderStateArray() {
65
+ const rs = new Float64Array(46);
66
+ applyRenderStateSentinels(rs);
67
+ return rs;
68
+ }
69
+ /** Re-initialise a live render-state array in place: zero every slot, then
70
+ * restore the `-1` sentinels. */
71
+ function resetRenderStateArray(rs) {
72
+ rs.fill(0);
73
+ applyRenderStateSentinels(rs);
74
+ }
75
+ /** Allocate a fresh, fully-null GLState sized for `maxTextureUnits`. */
76
+ export function createGLState(maxTextureUnits) {
77
+ return {
78
+ currentProgram: null,
79
+ activeTextureUnit: 0,
80
+ boundTextures: new Array(maxTextureUnits).fill(null),
81
+ boundArrayBuffer: null,
82
+ boundElementBuffer: null,
83
+ boundVao: null,
84
+ viewportX: 0,
85
+ viewportY: 0,
86
+ viewportW: 0,
87
+ viewportH: 0,
88
+ boundFramebuffer: null,
89
+ rs: createRenderStateArray(),
90
+ statesDirty: false,
91
+ scissorEnabled: -1,
92
+ scissorX: 0,
93
+ scissorY: 0,
94
+ scissorW: 0,
95
+ scissorH: 0,
96
+ unpackAlignment: -1,
97
+ unpackFlipY: -1,
98
+ unpackPremultiplyAlpha: -1,
99
+ enabledAttribs: [],
100
+ instanceLocations: [],
101
+ quadVbo: null,
102
+ quadIbo: null,
103
+ quadVao: null,
104
+ };
105
+ }
106
+ /** Reset only the cached "current GL state" — every binding (program / buffers /
107
+ * textures / VAO / framebuffer) and render-state (blend / depth / stencil /
108
+ * scissor / color-mask / viewport / unpack) field, including the whole `rs`
109
+ * deferred render-state array (BOTH the actual applied values and the DESIRED
110
+ * twins) plus `statesDirty` — to its unset sentinel, WITHOUT discarding owned
111
+ * GPU resources (the shared quad). After this, the next setter in each category
112
+ * is re-issued rather than elided.
113
+ *
114
+ * Used by `resetGLState` (context-lost) and by `wipeGLStateCache` (a host that
115
+ * shares the GL context calling in after mutating raw `gl.*` state). The shared
116
+ * quad's GL objects are still alive in the latter case, so they are preserved
117
+ * here to avoid leaking + needlessly rebuilding them every render scope. */
118
+ export function resetGLStateCache(state) {
119
+ state.currentProgram = null;
120
+ state.activeTextureUnit = 0;
121
+ state.boundTextures.fill(null);
122
+ state.boundArrayBuffer = null;
123
+ state.boundElementBuffer = null;
124
+ state.boundVao = null;
125
+ state.viewportX = 0;
126
+ state.viewportY = 0;
127
+ state.viewportW = 0;
128
+ state.viewportH = 0;
129
+ state.boundFramebuffer = null;
130
+ resetRenderStateArray(state.rs);
131
+ state.statesDirty = false;
132
+ state.scissorEnabled = -1;
133
+ state.scissorX = 0;
134
+ state.scissorY = 0;
135
+ state.scissorW = 0;
136
+ state.scissorH = 0;
137
+ state.unpackAlignment = -1;
138
+ state.unpackFlipY = -1;
139
+ state.unpackPremultiplyAlpha = -1;
140
+ state.enabledAttribs.length = 0;
141
+ state.instanceLocations.length = 0;
142
+ }
143
+ /** Zero the cache in-place. Used by the context-lost handler — GL handles are
144
+ * already dead per WebGL spec; we forget what we knew about them (including the
145
+ * shared quad, whose GL objects are gone and must be rebuilt) so the next
146
+ * bind/use after restore is NOT incorrectly elided. */
147
+ export function resetGLState(state) {
148
+ resetGLStateCache(state);
149
+ state.quadVbo = null;
150
+ state.quadIbo = null;
151
+ state.quadVao = null;
152
+ }
153
+ //# sourceMappingURL=state.js.map
package/state.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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","sourcesContent":["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"]}
package/texture.d.ts ADDED
@@ -0,0 +1,142 @@
1
+ import type { GLEngineContext } from "./context.js";
2
+ /** Texture sampling / wrap options. All have GL-spec defaults. Mipmaps are NOT
3
+ * a create option — generate the chain explicitly via {@link generateTextureMipMaps}. */
4
+ export interface GLTextureOptions {
5
+ /** Default: false (matches Babylon's default raw-texture behaviour). */
6
+ invertY?: boolean;
7
+ /** Default: gl.LINEAR. */
8
+ minFilter?: GLenum;
9
+ /** Default: gl.LINEAR. */
10
+ magFilter?: GLenum;
11
+ /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`
12
+ * (NPOT-safe in WebGL2). */
13
+ wrapS?: GLenum;
14
+ /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`. */
15
+ wrapT?: GLenum;
16
+ /** `gl.pixelStorei(UNPACK_ALIGNMENT)` for the upload (1/2/4/8). Default 4.
17
+ * Use 1 for tightly-packed non-RGBA rows. */
18
+ unpackAlignment?: number;
19
+ /** Premultiply alpha at upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`). Default
20
+ * false. */
21
+ premultiplyAlpha?: boolean;
22
+ /** Explicit sized internalFormat for `texImage2D`. When provided it is used
23
+ * verbatim and the inline LDR resolver is bypassed — this is how
24
+ * {@link createFloatTexture} injects its `RGBA16F` / `RGBA32F` choice
25
+ * without the byte path ever referencing the float-format table (keeping it
26
+ * tree-shakeable out of RGBA8-only bundles). Default: derived from
27
+ * `format`/`type` via the LDR resolver. */
28
+ internalFormat?: GLenum;
29
+ }
30
+ /**
31
+ * Pure-state texture handle. The `handle` field is MUTABLE so the same logical
32
+ * texture survives a `webglcontextrestored` event — every consumer keeps the
33
+ * same `GLTexture` reference; only the internal `WebGLTexture` is swapped.
34
+ *
35
+ * `loadTexture2D` also uses the same handle for the 1×1 placeholder upload AND
36
+ * the final image upload — so a `bindTexture(engine, unit, tex)` made before the
37
+ * image has decoded remains valid once the image arrives.
38
+ */
39
+ export interface GLTexture {
40
+ /** The live `WebGLTexture`. MUTABLE — swapped for a fresh handle on
41
+ * `webglcontextrestored` while consumers keep the same `GLTexture` reference. */
42
+ handle: WebGLTexture;
43
+ /** GL texture target (always `gl.TEXTURE_2D` for this package). */
44
+ readonly target: GLenum;
45
+ /** Texture width in texels. Updated once an async upload resolves. */
46
+ width: number;
47
+ /** Texture height in texels. Updated once an async upload resolves. */
48
+ height: number;
49
+ /** True when the texture is safe to sample with final content (placeholders
50
+ * read as not-ready until their image/upload completes). */
51
+ isReady: boolean;
52
+ }
53
+ /** Uint8 / float raw texture upload. The pixel data can be replaced later via
54
+ * {@link updateRawTexture}; the sampling and wrap can be changed via
55
+ * {@link updateTextureSamplingMode} / {@link updateTextureWrapMode}. */
56
+ export declare function createRawTexture(engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, format: GLenum, type: GLenum, options?: GLTextureOptions): GLTexture;
57
+ /** Options for {@link createFloatTexture} — the shared {@link GLTextureOptions}
58
+ * plus the float-specific `type` / `format`. */
59
+ export interface GLFloatTextureOptions extends GLTextureOptions {
60
+ /** Float texel type — `gl.HALF_FLOAT` (default) or `gl.FLOAT`. */
61
+ type?: GLenum;
62
+ /** Color format. Default `gl.RGBA`. */
63
+ format?: GLenum;
64
+ }
65
+ /**
66
+ * Create a float / half-float raw texture — the HDR counterpart of
67
+ * {@link createRawTexture}. This is the ONLY texture factory that carries the
68
+ * `RGBA16F` / `RGBA32F` sized-format knowledge (via {@link pickSizedInternalFormat}),
69
+ * so byte-only consumers calling {@link createRawTexture} ship none of it.
70
+ * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.
71
+ * The caller is responsible for the matching engine cap (e.g.
72
+ * `caps.textureFloatLinearFiltering`) when sampling these with `LINEAR`.
73
+ *
74
+ * @param engine - The engine.
75
+ * @param data - Initial pixels (`Float32Array` for FLOAT, `Uint16Array` for
76
+ * HALF_FLOAT), or `null` for an uninitialised allocation.
77
+ * @param width - Texture width in texels (≥ 1).
78
+ * @param height - Texture height in texels (≥ 1).
79
+ * @param options - See {@link GLFloatTextureOptions}.
80
+ * @returns The new {@link GLTexture}.
81
+ */
82
+ export declare function createFloatTexture(engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, options?: GLFloatTextureOptions): GLTexture;
83
+ /** Generate the mip chain for a texture from its level-0 contents — mipmaps as
84
+ * an explicit opt-in function rather than baked into the create path. Binds for
85
+ * upload (unit 0). No-op on a lost/disposed context or a handle-less texture. */
86
+ export declare function generateTextureMipMaps(engine: GLEngineContext, tex: GLTexture): void;
87
+ /**
88
+ * Re-upload the pixel data (and optionally resize) of a texture created by
89
+ * {@link createRawTexture} — the lite-gl equivalent of Babylon's
90
+ * `updateRawTexture` / `_uploadDataToTextureDirectly`. Goes through the same
91
+ * upload closure used by context-restore, so the new contents survive a context
92
+ * loss. No-op on a lost/disposed/non-raw texture.
93
+ *
94
+ * @param engine - The engine.
95
+ * @param tex - The raw texture to update.
96
+ * @param data - New pixel data (must match the original `format`/`type`).
97
+ * @param options - Optional new `width`/`height` (default: unchanged) and
98
+ * `unpackAlignment` (default 4).
99
+ */
100
+ export declare function updateRawTexture(engine: GLEngineContext, tex: GLTexture, data: ArrayBufferView | null, options?: {
101
+ width?: number;
102
+ height?: number;
103
+ unpackAlignment?: number;
104
+ }): void;
105
+ /** Update a texture's min/mag sampling filters — the lite-gl equivalent of
106
+ * Babylon's `updateTextureSamplingMode`. Binds for upload (unit 0) so the
107
+ * `texParameteri` lands on this texture. No-op on a lost/disposed context. */
108
+ export declare function updateTextureSamplingMode(engine: GLEngineContext, tex: GLTexture, minFilter: GLenum, magFilter: GLenum): void;
109
+ /** Update a texture's S/T wrap modes (`gl.CLAMP_TO_EDGE` / `gl.REPEAT` /
110
+ * `gl.MIRRORED_REPEAT`) — the lite-gl equivalent of Babylon's
111
+ * `updateTextureWrappingMode`. No-op on a lost/disposed context. */
112
+ export declare function updateTextureWrapMode(engine: GLEngineContext, tex: GLTexture, wrapS: GLenum, wrapT: GLenum): void;
113
+ /**
114
+ * Wrap an existing raw `WebGLTexture` (e.g. one created by a host renderer or a
115
+ * previous engine) as a {@link GLTexture} — the lite-gl equivalent of
116
+ * ShapeBuilder's `createTextureGraphicsResourceFromExternalWebGLTexture`.
117
+ *
118
+ * The wrapper does NOT own the underlying handle's upload — it is NOT registered
119
+ * for context-restore replay (the external owner is responsible for that) and is
120
+ * marked ready immediately. `disposeTexture` will still `gl.deleteTexture` it, so
121
+ * only wrap a handle whose deletion you intend lite-gl to manage.
122
+ *
123
+ * @param engine - The engine.
124
+ * @param handle - The external `WebGLTexture`.
125
+ * @param width - Texture width in texels.
126
+ * @param height - Texture height in texels.
127
+ * @param options - Optional sampling/wrap to apply once (min/mag/wrapS/wrapT).
128
+ * @returns A {@link GLTexture} wrapping the handle.
129
+ */
130
+ export declare function createTextureFromHandle(engine: GLEngineContext, handle: WebGLTexture, width: number, height: number, options?: GLTextureOptions): GLTexture;
131
+ /** Asynchronous image upload.The returned texture is immediately usable (1×1
132
+ * transparent placeholder); `isReady` flips true once the image has been
133
+ * decoded and uploaded. The decoded `ImageBitmap` is retained on the texture
134
+ * for offline-safe `webglcontextrestored` replay. */
135
+ export declare function loadTexture2D(engine: GLEngineContext, url: string, options?: GLTextureOptions, onLoad?: (tex: GLTexture) => void, onError?: (err: Error) => void): GLTexture;
136
+ /** Cached bind. Skips `gl.activeTexture` and/or `gl.bindTexture` when nothing
137
+ * changes. No-op when `tex._disposed` or `engine._isLost`. */
138
+ export declare function bindTexture(engine: GLEngineContext, unit: number, tex: GLTexture | null): void;
139
+ /** Disposes the texture. Walks `_state.boundTextures` and clears every slot
140
+ * that still references the handle — otherwise a later `bindTexture(unit, B)`
141
+ * to the same unit would be wrongly elided when slot still showed handle A. */
142
+ export declare function disposeTexture(engine: GLEngineContext, tex: GLTexture): void;