@babylonjs/lite-gl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,263 @@
1
+ import { u as useEffect, c as createEffect, d as disposeEffect } from "./effect-BxxwfB_O.js";
2
+ import { a, b, e, g, f, h, i, j, o, k, l, m, r, s, n, p, q, t, v, w, x, y, z, A, B, C, D, E, F, G, H } from "./effect-BxxwfB_O.js";
3
+ import { a as applyGLStates } from "./state--j_ncWIi.js";
4
+ import { b as b2, c, a as a2, d, e as e2, g as g2, l as l2, u, f as f2, h as h2 } from "./texture-DaMd1gGm.js";
5
+ import { clearDynamicTextureSource, createDynamicTexture, updateDynamicTexture } from "./dynamic-texture.js";
6
+ import { bindRenderTarget, createFloatRenderTarget, createPingPong, createRenderTarget, disposePingPong, disposeRenderTarget, generateRenderTargetMipMaps, readRenderTargetPixels, resizePingPong, resizeRenderTarget } from "./render-target.js";
7
+ import { bindAttributes, bindIndexBuffer, bindMeshVao, createIndexBuffer, createMeshVao, createVertexBuffer, disposeBuffer, disposeMeshVao, drawIndexed, drawMesh, unbindInstanceAttributes, updateVertexBuffer } from "./mesh.js";
8
+ import { G as G2, a as a3, c as c2, d as d2, b as b3, r as r2, s as s2, e as e3, f as f3 } from "./sprites--1oyVtJ3.js";
9
+ import { clearEngine, generateRenderTargetStencil, setColorMask, setCullState, setDepthState, setStencilState } from "./depth-stencil.js";
10
+ import { disableScissor, setScissor } from "./scissor.js";
11
+ import { GLSamplingMode, createHtmlElementTexture, updateHtmlElementTexture } from "./html-texture.js";
12
+ function runRenderLoop(engine, fn) {
13
+ if (engine._disposed) {
14
+ return;
15
+ }
16
+ if (engine._scheduleFrame === null) {
17
+ engine._scheduleFrame = scheduleFrame;
18
+ }
19
+ if (engine._loops.indexOf(fn) !== -1) {
20
+ return;
21
+ }
22
+ engine._loops.push(fn);
23
+ if (engine._rafId === 0 && !engine._isLost) {
24
+ scheduleFrame(engine);
25
+ }
26
+ }
27
+ function stopRenderLoop(engine, fn) {
28
+ if (fn === void 0) {
29
+ engine._loops.length = 0;
30
+ } else {
31
+ const i2 = engine._loops.indexOf(fn);
32
+ if (i2 !== -1) {
33
+ engine._loops.splice(i2, 1);
34
+ }
35
+ }
36
+ if (engine._loops.length === 0 && engine._rafId !== 0) {
37
+ cancelAnimationFrame(engine._rafId);
38
+ engine._rafId = 0;
39
+ }
40
+ }
41
+ function scheduleFrame(engine) {
42
+ engine._prevNow = performance.now();
43
+ engine._rafId = requestAnimationFrame((now) => tick(engine, now));
44
+ }
45
+ function tick(engine, now) {
46
+ engine._rafId = 0;
47
+ if (engine._disposed || engine._isLost || engine._loops.length === 0) {
48
+ return;
49
+ }
50
+ const dt = now - engine._prevNow;
51
+ engine._prevNow = now;
52
+ const loops = engine._loops.slice();
53
+ for (const cb of loops) {
54
+ try {
55
+ cb(dt);
56
+ } catch (err) {
57
+ console.error("lite-gl: render loop callback threw", err);
58
+ }
59
+ }
60
+ if (engine._loops.length > 0 && !engine._disposed && !engine._isLost) {
61
+ engine._rafId = requestAnimationFrame((nextNow) => tick(engine, nextNow));
62
+ }
63
+ }
64
+ const DEFAULT_FULLSCREEN_VERTEX_SOURCE = `#version 300 es
65
+ layout(location = 0) in vec2 position;
66
+ out vec2 vUv;
67
+ void main() {
68
+ vUv = position * 0.5 + 0.5;
69
+ gl_Position = vec4(position, 0.0, 1.0);
70
+ }`;
71
+ function createEffectWrapper(engine, options) {
72
+ const name = options.name ?? "effect-wrapper";
73
+ const effect = createEffect(engine, {
74
+ name,
75
+ vertexSource: options.vertexSource ?? DEFAULT_FULLSCREEN_VERTEX_SOURCE,
76
+ fragmentSource: options.fragmentSource,
77
+ uniformNames: options.uniformNames ?? [],
78
+ samplerNames: options.samplerNames ?? [],
79
+ attributeNames: options.attributeNames,
80
+ defines: options.defines
81
+ });
82
+ return { name, effect, _engine: engine, _disposed: false };
83
+ }
84
+ function disposeEffectWrapper(wrapper) {
85
+ if (wrapper._disposed) {
86
+ return;
87
+ }
88
+ wrapper._disposed = true;
89
+ disposeEffect(wrapper._engine, wrapper.effect);
90
+ }
91
+ function setViewport(engine, viewport) {
92
+ if (engine._isLost || engine._disposed) {
93
+ return;
94
+ }
95
+ const x2 = (viewport == null ? void 0 : viewport.x) ?? 0;
96
+ const y2 = (viewport == null ? void 0 : viewport.y) ?? 0;
97
+ const w2 = (viewport == null ? void 0 : viewport.w) ?? engine.canvas.width;
98
+ const h3 = (viewport == null ? void 0 : viewport.h) ?? engine.canvas.height;
99
+ const s3 = engine._state;
100
+ if (s3.viewportX === x2 && s3.viewportY === y2 && s3.viewportW === w2 && s3.viewportH === h3) {
101
+ return;
102
+ }
103
+ s3.viewportX = x2;
104
+ s3.viewportY = y2;
105
+ s3.viewportW = w2;
106
+ s3.viewportH = h3;
107
+ engine.gl.viewport(x2, y2, w2, h3);
108
+ }
109
+ function applyEffectWrapper(wrapper) {
110
+ const engine = wrapper._engine;
111
+ if (engine._isLost || engine._disposed || wrapper._disposed) {
112
+ return;
113
+ }
114
+ ensureQuad(engine);
115
+ useEffect(engine, wrapper.effect);
116
+ }
117
+ function drawEffect(engine) {
118
+ if (engine._isLost || engine._disposed) {
119
+ return;
120
+ }
121
+ if (engine._state.currentProgram === null) {
122
+ return;
123
+ }
124
+ applyGLStates(engine);
125
+ engine.gl.drawElements(engine.gl.TRIANGLES, 6, engine.gl.UNSIGNED_SHORT, 0);
126
+ }
127
+ function ensureQuad(engine) {
128
+ const s3 = engine._state;
129
+ const gl = engine.gl;
130
+ if (s3.quadVao !== null) {
131
+ if (s3.boundVao !== s3.quadVao) {
132
+ gl.bindVertexArray(s3.quadVao);
133
+ s3.boundVao = s3.quadVao;
134
+ }
135
+ return;
136
+ }
137
+ const vao = gl.createVertexArray();
138
+ if (vao === null) {
139
+ throw new Error("lite-gl: gl.createVertexArray returned null");
140
+ }
141
+ s3.quadVao = vao;
142
+ gl.bindVertexArray(vao);
143
+ s3.boundVao = vao;
144
+ const vbo = gl.createBuffer();
145
+ if (vbo === null) {
146
+ throw new Error("lite-gl: gl.createBuffer returned null (VBO)");
147
+ }
148
+ s3.quadVbo = vbo;
149
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
150
+ s3.boundArrayBuffer = vbo;
151
+ gl.bufferData(gl.ARRAY_BUFFER, QUAD_POSITIONS, gl.STATIC_DRAW);
152
+ const ibo = gl.createBuffer();
153
+ if (ibo === null) {
154
+ throw new Error("lite-gl: gl.createBuffer returned null (IBO)");
155
+ }
156
+ s3.quadIbo = ibo;
157
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
158
+ s3.boundElementBuffer = ibo;
159
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, QUAD_INDICES, gl.STATIC_DRAW);
160
+ gl.enableVertexAttribArray(0);
161
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
162
+ }
163
+ const QUAD_POSITIONS = new Float32Array([1, 1, -1, 1, -1, -1, 1, -1]);
164
+ const QUAD_INDICES = new Uint16Array([0, 1, 2, 0, 2, 3]);
165
+ export {
166
+ G2 as GLBlendEquation,
167
+ a3 as GLBlendMode,
168
+ GLSamplingMode,
169
+ applyEffectWrapper,
170
+ bindAttributes,
171
+ bindIndexBuffer,
172
+ bindMeshVao,
173
+ bindRenderTarget,
174
+ b2 as bindTexture,
175
+ clearDynamicTextureSource,
176
+ clearEngine,
177
+ createDynamicTexture,
178
+ createEffect,
179
+ createEffectWrapper,
180
+ createFloatRenderTarget,
181
+ c as createFloatTexture,
182
+ a as createGLEngine,
183
+ createHtmlElementTexture,
184
+ createIndexBuffer,
185
+ createMeshVao,
186
+ createPingPong,
187
+ a2 as createRawTexture,
188
+ createRenderTarget,
189
+ c2 as createSpriteRenderer,
190
+ d as createTextureFromHandle,
191
+ createVertexBuffer,
192
+ d2 as disableBlend,
193
+ disableScissor,
194
+ disposeBuffer,
195
+ disposeEffect,
196
+ disposeEffectWrapper,
197
+ b as disposeGLEngine,
198
+ disposeMeshVao,
199
+ disposePingPong,
200
+ disposeRenderTarget,
201
+ b3 as disposeSpriteRenderer,
202
+ e2 as disposeTexture,
203
+ drawEffect,
204
+ drawIndexed,
205
+ drawMesh,
206
+ e as executeWhenCompiled,
207
+ generateRenderTargetMipMaps,
208
+ generateRenderTargetStencil,
209
+ g2 as generateTextureMipMaps,
210
+ g as getHardwareScalingLevel,
211
+ f as getRenderHeight,
212
+ h as getRenderWidth,
213
+ i as getRenderingCanvas,
214
+ j as isEffectReady,
215
+ l2 as loadTexture2D,
216
+ o as offContextLost,
217
+ k as offContextRestored,
218
+ l as onContextLost,
219
+ m as onContextRestored,
220
+ readRenderTargetPixels,
221
+ r2 as renderSprites,
222
+ r as resizeGLEngine,
223
+ resizePingPong,
224
+ resizeRenderTarget,
225
+ runRenderLoop,
226
+ s2 as setBlendMode,
227
+ e3 as setBlendState,
228
+ setColorMask,
229
+ setCullState,
230
+ setDepthState,
231
+ s as setEffectColor3,
232
+ n as setEffectColor4,
233
+ p as setEffectDirectColor4,
234
+ q as setEffectFloat,
235
+ t as setEffectFloat2,
236
+ v as setEffectFloat3,
237
+ w as setEffectFloat4,
238
+ x as setEffectFloatArray,
239
+ y as setEffectFloatArray4,
240
+ z as setEffectInt,
241
+ A as setEffectIntArray,
242
+ B as setEffectMatrix,
243
+ C as setEffectMatrix3x3,
244
+ D as setEffectTexture,
245
+ E as setEffectVector2,
246
+ F as setGLEngineSize,
247
+ G as setHardwareScalingLevel,
248
+ setScissor,
249
+ f3 as setSpriteRendererTexture,
250
+ setStencilState,
251
+ setViewport,
252
+ stopRenderLoop,
253
+ unbindInstanceAttributes,
254
+ updateDynamicTexture,
255
+ updateHtmlElementTexture,
256
+ u as updateRawTexture,
257
+ f2 as updateTextureSamplingMode,
258
+ h2 as updateTextureWrapMode,
259
+ updateVertexBuffer,
260
+ useEffect,
261
+ H as wipeGLStateCache
262
+ };
263
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/render-loop.ts","../src/effect-renderer.ts"],"sourcesContent":["import { type GLEngineContext } from \"./context.js\";\n\n/** Register a per-frame callback. **No-op if `fn` is already registered**\n * (matches Babylon `AbstractEngine.runRenderLoop`). Starts the rAF if this is\n * the first registration. */\nexport function runRenderLoop(engine: GLEngineContext, fn: (dt: number) => void): void {\n if (engine._disposed) {\n return;\n }\n // Install the resume hook on the context (no module-level side effects).\n if (engine._scheduleFrame === null) {\n engine._scheduleFrame = scheduleFrame;\n }\n if (engine._loops.indexOf(fn) !== -1) {\n return;\n }\n engine._loops.push(fn);\n if (engine._rafId === 0 && !engine._isLost) {\n scheduleFrame(engine);\n }\n}\n\n/** Stop one (or all when omitted) registered callbacks. Cancels the rAF if\n * no callbacks remain. */\nexport function stopRenderLoop(engine: GLEngineContext, fn?: (dt: number) => void): void {\n if (fn === undefined) {\n engine._loops.length = 0;\n } else {\n const i = engine._loops.indexOf(fn);\n if (i !== -1) {\n engine._loops.splice(i, 1);\n }\n }\n if (engine._loops.length === 0 && engine._rafId !== 0) {\n cancelAnimationFrame(engine._rafId);\n engine._rafId = 0;\n }\n}\n\nfunction scheduleFrame(engine: GLEngineContext): void {\n engine._prevNow = performance.now();\n engine._rafId = requestAnimationFrame((now) => tick(engine, now));\n}\n\nfunction tick(engine: GLEngineContext, now: number): void {\n engine._rafId = 0;\n if (engine._disposed || engine._isLost || engine._loops.length === 0) {\n return;\n }\n const dt = now - engine._prevNow;\n engine._prevNow = now;\n // Snapshot — a callback may call stopRenderLoop on itself or others.\n const loops = engine._loops.slice();\n for (const cb of loops) {\n try {\n cb(dt);\n } catch (err) {\n console.error(\"lite-gl: render loop callback threw\", err);\n }\n }\n if (engine._loops.length > 0 && !engine._disposed && !engine._isLost) {\n engine._rafId = requestAnimationFrame((nextNow) => tick(engine, nextNow));\n }\n}\n","import type { GLEngineContext } from \"./context.js\";\nimport { createEffect, disposeEffect, type GLEffect, useEffect } from \"./effect.js\";\nimport { applyGLStates } from \"./apply-states.js\";\n\n/** Built-in fullscreen-quad vertex shader, used when `GLEffectWrapperOptions`\n * omits `vertexSource`. Maps the package's fullscreen-quad positions\n * (attribute location 0) to clip space and forwards a 0..1 `vUv` varying —\n * the WebGL counterpart of lite's default `vertexWGSL`, so callers can pass\n * only `fragmentSource`. */\nconst DEFAULT_FULLSCREEN_VERTEX_SOURCE = `#version 300 es\nlayout(location = 0) in vec2 position;\nout vec2 vUv;\nvoid main() {\n vUv = position * 0.5 + 0.5;\n gl_Position = vec4(position, 0.0, 1.0);\n}`;\n\n/** Inputs to `createEffectWrapper`. Mirrors lite's `EffectWrapperOptions`: the\n * wrapper compiles and OWNS the effect built from this shader source. */\nexport interface GLEffectWrapperOptions {\n /** Human-readable label for the wrapper and its effect. Defaults to\n * `\"effect-wrapper\"`. */\n name?: string;\n /** GLSL ES 3.00 vertex source. Defaults to a built-in fullscreen-quad\n * vertex shader (exposing a `vUv` varying), mirroring lite's default\n * `vertexWGSL`. */\n vertexSource?: string;\n /** GLSL ES 3.00 fragment source (≙ lite's `fragmentWGSL`). Required. */\n fragmentSource: string;\n /** Declared uniform names. Defaults to none. */\n uniformNames?: readonly string[];\n /** Declared sampler names, in unit-assignment order. Defaults to none. */\n samplerNames?: readonly string[];\n /** Attribute names; the first is bound to location 0. Defaults to\n * `[\"position\"]`. */\n attributeNames?: readonly string[];\n /** Optional `#define` block prepended to both shader stages. */\n defines?: string;\n}\n\n/** A reusable fullscreen effect that compiles and OWNS its `GLEffect` — the\n * WebGL counterpart of lite's `EffectWrapper`. The wrapper retains the engine\n * it was created for, so `disposeEffectWrapper` / `applyEffectWrapper` take\n * only the wrapper. */\nexport interface GLEffectWrapper {\n /** Name alias for the wrapper (and its effect). */\n readonly name: string;\n /** The compiled effect this wrapper owns. Exposed so the per-uniform\n * setters (`setEffectFloat`/`setEffectTexture`/…) can target it — the\n * WebGL divergence from lite's UBO-based `setEffectUniforms(wrapper, …)`. */\n readonly effect: GLEffect;\n /** @internal The engine the wrapper was created for. */\n _engine: GLEngineContext;\n /** @internal */\n _disposed: boolean;\n}\n\n/** Compile a fullscreen effect from shader source and wrap it; the wrapper OWNS\n * the resulting `GLEffect`. Mirrors lite's `createEffectWrapper(engine, options)`.\n * When `vertexSource` is omitted, a built-in fullscreen-quad vertex shader is\n * used, so callers can supply only `fragmentSource`. */\nexport function createEffectWrapper(engine: GLEngineContext, options: GLEffectWrapperOptions): GLEffectWrapper {\n const name = options.name ?? \"effect-wrapper\";\n const effect = createEffect(engine, {\n name,\n vertexSource: options.vertexSource ?? DEFAULT_FULLSCREEN_VERTEX_SOURCE,\n fragmentSource: options.fragmentSource,\n uniformNames: options.uniformNames ?? [],\n samplerNames: options.samplerNames ?? [],\n attributeNames: options.attributeNames,\n defines: options.defines,\n });\n return { name, effect, _engine: engine, _disposed: false };\n}\n\n/** Dispose the wrapper and the effect it owns (idempotent). Mirrors lite's\n * `disposeEffectWrapper(wrapper)`. */\nexport function disposeEffectWrapper(wrapper: GLEffectWrapper): void {\n if (wrapper._disposed) {\n return;\n }\n wrapper._disposed = true;\n disposeEffect(wrapper._engine, wrapper.effect);\n}\n\n/** Pixel-space viewport rectangle passed to `setViewport`. */\nexport interface GLViewport {\n /** Lower-left X origin in physical pixels. */\n x: number;\n /** Lower-left Y origin in physical pixels. */\n y: number;\n /** Width in physical pixels. */\n w: number;\n /** Height in physical pixels. */\n h: number;\n}\n\n/** Cached `gl.viewport`. Defaults to the full canvas in pixel coordinates. */\nexport function setViewport(engine: GLEngineContext, viewport?: GLViewport): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const x = viewport?.x ?? 0;\n const y = viewport?.y ?? 0;\n const w = viewport?.w ?? engine.canvas.width;\n const h = viewport?.h ?? engine.canvas.height;\n const s = engine._state;\n if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {\n return;\n }\n s.viewportX = x;\n s.viewportY = y;\n s.viewportW = w;\n s.viewportH = h;\n engine.gl.viewport(x, y, w, h);\n}\n\n/** Make `wrapper.effect` current and ensure the shared fullscreen quad VAO\n * is bound. This MUST be called BEFORE any `setEffect*` call for the same\n * effect in the current frame (uniform setters write to the currently bound\n * program). */\nexport function applyEffectWrapper(wrapper: GLEffectWrapper): void {\n const engine = wrapper._engine;\n if (engine._isLost || engine._disposed || wrapper._disposed) {\n return;\n }\n ensureQuad(engine);\n useEffect(engine, wrapper.effect);\n}\n\n/** `gl.drawElements(TRIANGLES, 6, UNSIGNED_SHORT, 0)`. No-op when the\n * context is lost or there is no current program. */\nexport function drawEffect(engine: GLEngineContext): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (engine._state.currentProgram === null) {\n return;\n }\n applyGLStates(engine);\n engine.gl.drawElements(engine.gl.TRIANGLES, 6, engine.gl.UNSIGNED_SHORT, 0);\n}\n\n/** Lazy fullscreen quad. Built on first call; thereafter the VAO is cached on\n * `_state.quadVao` and rebinding is a single cached call. Cleared by\n * `webglcontextlost` and transparently rebuilt by the next\n * `applyEffectWrapper` after restore.\n *\n * Position attribute is enabled at location 0 — every effect's\n * `createEffect` calls `gl.bindAttribLocation(program, 0, attributeNames[0])`\n * BEFORE link, so the shared VAO is correct across all programs. */\nfunction ensureQuad(engine: GLEngineContext): void {\n const s = engine._state;\n const gl = engine.gl;\n if (s.quadVao !== null) {\n if (s.boundVao !== s.quadVao) {\n gl.bindVertexArray(s.quadVao);\n s.boundVao = s.quadVao;\n }\n return;\n }\n const vao = gl.createVertexArray();\n if (vao === null) {\n throw new Error(\"lite-gl: gl.createVertexArray returned null\");\n }\n s.quadVao = 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 (VBO)\");\n }\n s.quadVbo = vbo;\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n s.boundArrayBuffer = vbo;\n gl.bufferData(gl.ARRAY_BUFFER, QUAD_POSITIONS, gl.STATIC_DRAW);\n\n const ibo = gl.createBuffer();\n if (ibo === null) {\n throw new Error(\"lite-gl: gl.createBuffer returned null (IBO)\");\n }\n s.quadIbo = ibo;\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);\n s.boundElementBuffer = ibo;\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, QUAD_INDICES, gl.STATIC_DRAW);\n\n gl.enableVertexAttribArray(0);\n gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);\n}\n\n/** Typed-array literal — pure per bundler convention. Matches Babylon's\n * `EffectRenderer` default geometry exactly. */\nconst QUAD_POSITIONS = new Float32Array([1, 1, -1, 1, -1, -1, 1, -1]);\nconst QUAD_INDICES = new Uint16Array([0, 1, 2, 0, 2, 3]);\n"],"names":["i","x","y","w","h","s"],"mappings":"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"}
package/mesh.d.ts ADDED
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Configure vertex attributes from `vb`, reproducing Babylon's
3
+ * `bindInstancesBuffer` exactly. For each descriptor: resolves the location
4
+ * (explicit `index` or via the effect), enables the attribute array, issues
5
+ * `vertexAttribPointer`, and sets the vertex divisor (`undefined → 1`). Every
6
+ * touched location is tracked so {@link unbindInstanceAttributes} can reset its
7
+ * divisor afterwards.
8
+ *
9
+ * `computeStride` controls the GL stride passed to `vertexAttribPointer`:
10
+ * - `false` (default) → stride `0`: each attribute is independently tightly
11
+ * packed. Combined with overlapping `offset`s this yields the "sliding window"
12
+ * ShapeBuilder uses for distance-field tape buffers.
13
+ * - `true` → stride = Σ(`size`·4 bytes): interleaved per-vertex/per-instance.
14
+ *
15
+ * Runs on the default (null) VAO — never corrupts the quad / sprite VAOs.
16
+ * No-op on a lost/disposed context or before the effect is ready.
17
+ *
18
+ * @param engine - The engine.
19
+ * @param vb - The buffer supplying the attribute data.
20
+ * @param descriptors - The attribute layout.
21
+ * @param effect - The effect whose attribute locations resolve unnamed indices.
22
+ * @param computeStride - See above. Default `false`.
23
+ */
24
+ export declare function bindAttributes(engine: GLEngineContext, vb: GLVertexBuffer, descriptors: readonly GLAttributeDescriptor[], effect: GLEffect, computeStride?: boolean): void;
25
+
26
+ /**
27
+ * Bind an index buffer as the current element-array buffer (on the default
28
+ * VAO). Cached. The lite-gl equivalent of Babylon's `_bindIndexBufferWithCache`.
29
+ *
30
+ * @param engine - The engine.
31
+ * @param ib - The index buffer to bind.
32
+ */
33
+ export declare function bindIndexBuffer(engine: GLEngineContext, ib: GLIndexBuffer): void;
34
+
35
+ /**
36
+ * Bind a {@link GLMeshVao} (cached `gl.bindVertexArray`). Rarely called directly —
37
+ * {@link drawMesh} binds it for you. Binding restores the VAO's recorded element
38
+ * binding, so the element-buffer cache is updated in lock-step.
39
+ *
40
+ * @param engine - The engine.
41
+ * @param vao - The mesh VAO to bind.
42
+ */
43
+ export declare function bindMeshVao(engine: GLEngineContext, vao: GLMeshVao): void;
44
+
45
+ /**
46
+ * Create a GPU index buffer. `Uint16Array` → 16-bit indices, `Uint32Array` →
47
+ * 32-bit. Binds the default VAO first so it never corrupts the quad / sprite
48
+ * VAO element bindings.
49
+ *
50
+ * @param engine - The engine.
51
+ * @param data - The index data. Retained by reference for context-restore.
52
+ * @returns The new {@link GLIndexBuffer}.
53
+ */
54
+ export declare function createIndexBuffer(engine: GLEngineContext, data: Uint16Array | Uint32Array): GLIndexBuffer;
55
+
56
+ /**
57
+ * Record a static mesh's attribute layout + index binding into a new VAO. The
58
+ * effect MUST be ready (its attribute locations are resolved here, once). Returns
59
+ * a {@link GLMeshVao} to draw with {@link drawMesh}.
60
+ *
61
+ * @param engine - The engine.
62
+ * @param vertexBuffers - One or more buffers + their attribute layouts.
63
+ * @param indexBuffer - The index buffer recorded into the VAO.
64
+ * @param effect - The effect whose attribute locations resolve unnamed indices.
65
+ * @returns The recorded {@link GLMeshVao}.
66
+ */
67
+ export declare function createMeshVao(engine: GLEngineContext, vertexBuffers: readonly GLMeshVertexBuffer[], indexBuffer: GLIndexBuffer, effect: GLEffect): GLMeshVao;
68
+
69
+ /**
70
+ * Create a GPU vertex buffer from interleaved float data.
71
+ *
72
+ * @param engine - The engine.
73
+ * @param data - The vertex data. Retained by reference for context-restore — do
74
+ * not mutate it in place; use {@link updateVertexBuffer} to change contents.
75
+ * @param dynamic - Hint that the buffer will be updated frequently
76
+ * (`DYNAMIC_DRAW`). Default `false` (`STATIC_DRAW`).
77
+ * @returns The new {@link GLVertexBuffer}.
78
+ */
79
+ export declare function createVertexBuffer(engine: GLEngineContext, data: Float32Array, dynamic?: boolean): GLVertexBuffer;
80
+
81
+ /** Dispose a vertex or index buffer (delete the GL buffer + unregister). Clears
82
+ * the array/element-buffer cache slot if it pointed at this buffer. Idempotent. */
83
+ export declare function disposeBuffer(engine: GLEngineContext, buffer: GLVertexBuffer | GLIndexBuffer): void;
84
+
85
+ /** Dispose a {@link GLMeshVao}: delete the VAO and unregister its restore hook.
86
+ * Does NOT dispose the vertex/index buffers (the caller owns those). Idempotent. */
87
+ export declare function disposeMeshVao(engine: GLEngineContext, vao: GLMeshVao): void;
88
+
89
+ /**
90
+ * Draw indexed triangles from `ib` — the lite-gl equivalent of Babylon's
91
+ * `drawElementsType` (triangle fill mode). When `instanceCount > 0` issues
92
+ * `drawElementsInstanced`, otherwise `drawElements`. No-op on a lost/disposed
93
+ * context or when no program is current.
94
+ *
95
+ * @param engine - The engine.
96
+ * @param ib - The index buffer (also bound as a side-effect, cached).
97
+ * @param indexCount - Number of indices to draw.
98
+ * @param indexStart - First index offset (in indices, not bytes). Default 0.
99
+ * @param instanceCount - Instance count for instanced draws. Default 0
100
+ * (non-instanced).
101
+ */
102
+ export declare function drawIndexed(engine: GLEngineContext, ib: GLIndexBuffer, indexCount: number, indexStart?: number, instanceCount?: number): void;
103
+
104
+ /**
105
+ * Draw a static mesh recorded with {@link createMeshVao}: binds its VAO (cached),
106
+ * flushes deferred GL state, and issues ONE `drawElements` (or
107
+ * `drawElementsInstanced` when `instanceCount > 0`) over the VAO's full index
108
+ * buffer. No per-draw attribute (re)binding. No-op on a lost/disposed context, a
109
+ * disposed VAO, or when no program is current.
110
+ *
111
+ * @param engine - The engine.
112
+ * @param vao - The mesh VAO to draw.
113
+ * @param instanceCount - Instance count for instanced draws. Default 0 (non-instanced).
114
+ */
115
+ export declare function drawMesh(engine: GLEngineContext, vao: GLMeshVao, instanceCount?: number): void;
116
+
117
+ /**
118
+ * Describes one vertex attribute fed from a buffer — the lite-gl equivalent of
119
+ * Babylon's `InstancingAttributeInfo`. Pass an array of these to
120
+ * {@link bindAttributes}.
121
+ */
122
+ export declare interface GLAttributeDescriptor {
123
+ /** Attribute name; resolved to a location via the effect when `index` is
124
+ * omitted (`Effect.getAttributeLocationByName`). */
125
+ name?: string;
126
+ /** Explicit attribute location. When set, overrides the `name` lookup. */
127
+ index?: number;
128
+ /** Number of components, 1–4. */
129
+ size: number;
130
+ /** Byte offset of this attribute's first element within the buffer. Default 0. */
131
+ offset?: number;
132
+ /**
133
+ * Per-instance vertex divisor. **Omitted/`undefined` → `1` (instanced)**,
134
+ * matching Babylon's `bindInstancesBuffer`. Pass `0` explicitly for a
135
+ * per-vertex attribute (e.g. the base mesh position).
136
+ */
137
+ divisor?: number;
138
+ /** GL component type. Default `gl.FLOAT`. */
139
+ type?: GLenum;
140
+ /** Normalize fixed-point integer data to `[0,1]`/`[-1,1]`. Default `false`. */
141
+ normalized?: boolean;
142
+ }
143
+
144
+ /** A compiled + linked shader program with cached uniform, sampler and
145
+ * attribute locations. Created by `createEffect`; most fields are managed
146
+ * internally — drive it via `isEffectReady` / `useEffect` / the `setEffect*`
147
+ * setters rather than mutating it directly. */
148
+ declare interface GLEffect {
149
+ /** The `name` from the originating `GLEffectOptions`. */
150
+ readonly name: string;
151
+ /** The options this effect was created from (retained for context-restore). */
152
+ readonly options: GLEffectOptions;
153
+ /** The live `WebGLProgram`. Swapped for a fresh handle after context-restore. */
154
+ program: WebGLProgram;
155
  /** Resolved during readiness finalization. Missing names map to `null` —
156
+ * setters with a `null` location are silent no-ops (matches Babylon). */
157
+ uniformLocations: {
158
+ [name: string]: WebGLUniformLocation | null;
159
+ };
160
+ /** Fixed unit assignment for declared samplers, index into
161
+ * `_state.boundTextures`. */
162
+ samplerUnits: {
163
+ [name: string]: number;
164
+ };
1
165
  /** Resolved attribute locations, keyed by attribute name. */
166
+ attributeLocations: {
167
+ [name: string]: number;
168
+ };
2
169
  /** True once the program has linked and finalization has run; the
170
+ * `setEffect*` setters are no-ops until then. Poll `isEffectReady` to advance it. */
171
+ isReady: boolean;
172
+
173
+ /** Inputs to `createEffect`: shader sources plus the uniform, sampler and
174
+ * attribute names whose locations are resolved during readiness finalization. */
175
+ declare interface GLEffectOptions {
176
+ /** Human-readable label, surfaced in compile/link error messages. */
177
+ name: string;
178
+ /** GLSL ES 3.00 source, ready for `gl.shaderSource`. */
179
+ vertexSource: string;
180
+ /** GLSL ES 3.00 source, ready for `gl.shaderSource`. */
181
+ fragmentSource: string;
182
+ /** Declared uniform names. Locations are resolved during readiness
183
+ * finalization. Names not declared here are legal but allocate cache
184
+ * slots lazily on first setter use. */
185
+ uniformNames: readonly string[];
186
+ /** Declared sampler names, in unit-assignment order. Each gets a fixed
187
+ * texture unit assigned during readiness finalization, and
188
+ * `gl.uniform1i(loc, unit)` is called exactly once per program lifetime
189
+ * (re-run after `webglcontextrestored`). */
190
+ samplerNames: readonly string[];
191
+ /** Default `["position"]`. The first attribute is bound to location 0 via
192
+ * `gl.bindAttribLocation(program, 0, name)` BEFORE link, so the shared
193
+ * fullscreen-quad VAO always feeds the same location. */
194
+ attributeNames?: readonly string[];
195
+ /** Optional `#define` block. Each unique `defines` string must be paired
196
+ * with the same vertex/fragment source via a separate `createEffect` call —
197
+ * the package does NOT cache compiled variants. */
198
+ defines?: string;
199
+ }
200
+
201
+ /** Read-only WebGL2 capability limits, queried once at context creation. */
202
+ declare interface GLEngineCaps {
203
+ /** `gl.MAX_TEXTURE_SIZE` — largest supported texture dimension, in texels. */
204
+ readonly maxTextureSize: number;
205
+ /** `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` — number of sampler binding slots. */
206
+ readonly maxTextureUnits: number;
207
+ /** The `KHR_parallel_shader_compile` extension used for async link polling,
208
+ * or null when unsupported — linking is then treated as synchronous. */
209
+ readonly parallelShaderCompile: {
210
+ COMPLETION_STATUS_KHR: number;
211
+ } | null;
212
+ /** True when 32-bit float color attachments are renderable
213
+ * (`EXT_color_buffer_float`). Mirrors Babylon's `caps.textureFloatRender`. */
214
+ readonly textureFloatRender: boolean;
215
+ /** True when 32-bit float textures support linear filtering
216
+ * (`OES_texture_float_linear`). Mirrors `caps.textureFloatLinearFiltering`. */
217
+ readonly textureFloatLinearFiltering: boolean;
218
+ /** True when 16-bit half-float color attachments are renderable
219
+ * (`EXT_color_buffer_float` or `EXT_color_buffer_half_float`). Mirrors
220
+ * `caps.textureHalfFloatRender`. */
221
+ readonly textureHalfFloatRender: boolean;
222
+ /** Half-float linear filtering — always `true` in WebGL2 (it is core).
223
+ * Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */
224
+ readonly textureHalfFloatLinearFiltering: boolean;
225
+ /** Whether non-power-of-two textures need POT dimensions for mips / wrap.
226
+ * Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */
227
+ readonly needPOTTextures: boolean;
228
+ }
229
+
230
+ /**
231
+ * Pure-state handle for a WebGL2 canvas + its cached GL state.
232
+ *
233
+ * INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.
234
+ * Doing so silently corrupts the cache in `_state`. The package owns every
235
+ * GL call. (`engine.gl` is exposed only so downstream code that already has the
236
+ * pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT
237
+ * call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)
238
+ */
239
+ declare interface GLEngineContext {
240
+ /** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is
241
+ * supported for worker render paths (e.g. the Lottie player); it has no CSS
242
+ * box, so it must be sized explicitly via `setGLEngineSize` rather than the
243
+ * CSS-derived `resizeGLEngine`. */
244
+ readonly canvas: HTMLCanvasElement | OffscreenCanvas;
245
+ /** The raw WebGL2 context. Do NOT mutate GL state through it — see the
246
+ * type-level invariant above; the package owns every state-changing call. */
247
+ readonly gl: WebGL2RenderingContext;
248
+ /** Queried capability limits for this context. */
249
+ readonly caps: GLEngineCaps;
250
+
251
+ /** A GPU index buffer. The lite-gl counterpart of Babylon's `DataBuffer` for
252
+ * index data. */
253
+ export declare interface GLIndexBuffer {
254
+ /** The live `WebGLBuffer`. Swapped on `webglcontextrestored`. */
255
+ handle: WebGLBuffer;
256
+ /** Number of indices. */
257
+ count: number;
258
+ /** `true` for 32-bit (`Uint32Array`) indices, `false` for 16-bit. */
259
+ is32Bits: boolean;
260
+
261
+ /** A recorded Vertex Array Object capturing a static mesh's attribute layout +
262
+ * index binding. Bind + draw it with {@link drawMesh} each frame — the GPU
263
+ * replays the entire attribute setup from one `bindVertexArray`. Re-recorded
264
+ * automatically on `webglcontextrestored`. */
265
+ export declare interface GLMeshVao {
266
+ /** The live `WebGLVertexArrayObject`. Swapped on `webglcontextrestored`. */
267
+ handle: WebGLVertexArrayObject;
268
+
269
+ /** One vertex buffer + its attribute layout, for {@link createMeshVao}. */
270
+ export declare interface GLMeshVertexBuffer {
271
+ /** The buffer supplying this group's attributes. */
272
+ buffer: GLVertexBuffer;
273
+ /** The attributes read from `buffer` (same shape as {@link bindAttributes}). */
274
+ attributes: readonly GLAttributeDescriptor[];
275
+ /** Stride mode (see {@link bindAttributes}): `false` (default) → stride `0`
276
+ * per attribute; `true` → interleaved stride = Σ(`size`·4). */
277
+ computeStride?: boolean;
278
+ }
279
+
280
+ /** A GPU vertex buffer holding interleaved float vertex data. The lite-gl
281
+ * counterpart of Babylon's `DataBuffer` for vertex data. */
282
+ export declare interface GLVertexBuffer {
283
+ /** The live `WebGLBuffer`. Swapped on `webglcontextrestored`. */
284
+ handle: WebGLBuffer;
285
+ /** Size of the GL buffer in bytes. */
286
+ byteLength: number;
287
+
288
+ /**
289
+ * Reset the vertex divisor of every attribute touched by {@link bindAttributes}
290
+ * back to 0 — the lite-gl equivalent of Babylon's `unbindInstanceAttributes`.
291
+ * Call after an instanced draw so a following non-instanced draw is not skewed.
292
+ * No-op on a lost/disposed context.
293
+ *
294
+ * @param engine - The engine.
295
+ */
296
+ export declare function unbindInstanceAttributes(engine: GLEngineContext): void;
297
+
298
+ /**
299
+ * Upload new contents into (part of) a vertex buffer via `bufferSubData`. A
300
+ * full-buffer update from offset 0 also refreshes the retained CPU data used
301
+ * for context-restore.
302
+ *
303
+ * @param engine - The engine.
304
+ * @param vb - The vertex buffer to update.
305
+ * @param data - The new float data.
306
+ * @param dstByteOffset - Destination byte offset within the buffer. Default 0.
307
+ */
308
+ export declare function updateVertexBuffer(engine: GLEngineContext, vb: GLVertexBuffer, data: Float32Array, dstByteOffset?: number): void;
309
+
310
+ export { }