@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
@@ -0,0 +1,65 @@
1
+ import type { GLEngineContext } from "./context.js";
2
+ import { type GLEffect } from "./effect.js";
3
+ /** Inputs to `createEffectWrapper`. Mirrors lite's `EffectWrapperOptions`: the
4
+ * wrapper compiles and OWNS the effect built from this shader source. */
5
+ export interface GLEffectWrapperOptions {
6
+ /** Human-readable label for the wrapper and its effect. Defaults to
7
+ * `"effect-wrapper"`. */
8
+ name?: string;
9
+ /** GLSL ES 3.00 vertex source. Defaults to a built-in fullscreen-quad
10
+ * vertex shader (exposing a `vUv` varying), mirroring lite's default
11
+ * `vertexWGSL`. */
12
+ vertexSource?: string;
13
+ /** GLSL ES 3.00 fragment source (≙ lite's `fragmentWGSL`). Required. */
14
+ fragmentSource: string;
15
+ /** Declared uniform names. Defaults to none. */
16
+ uniformNames?: readonly string[];
17
+ /** Declared sampler names, in unit-assignment order. Defaults to none. */
18
+ samplerNames?: readonly string[];
19
+ /** Attribute names; the first is bound to location 0. Defaults to
20
+ * `["position"]`. */
21
+ attributeNames?: readonly string[];
22
+ /** Optional `#define` block prepended to both shader stages. */
23
+ defines?: string;
24
+ }
25
+ /** A reusable fullscreen effect that compiles and OWNS its `GLEffect` — the
26
+ * WebGL counterpart of lite's `EffectWrapper`. The wrapper retains the engine
27
+ * it was created for, so `disposeEffectWrapper` / `applyEffectWrapper` take
28
+ * only the wrapper. */
29
+ export interface GLEffectWrapper {
30
+ /** Name alias for the wrapper (and its effect). */
31
+ readonly name: string;
32
+ /** The compiled effect this wrapper owns. Exposed so the per-uniform
33
+ * setters (`setEffectFloat`/`setEffectTexture`/…) can target it — the
34
+ * WebGL divergence from lite's UBO-based `setEffectUniforms(wrapper, …)`. */
35
+ readonly effect: GLEffect;
36
+ }
37
+ /** Compile a fullscreen effect from shader source and wrap it; the wrapper OWNS
38
+ * the resulting `GLEffect`. Mirrors lite's `createEffectWrapper(engine, options)`.
39
+ * When `vertexSource` is omitted, a built-in fullscreen-quad vertex shader is
40
+ * used, so callers can supply only `fragmentSource`. */
41
+ export declare function createEffectWrapper(engine: GLEngineContext, options: GLEffectWrapperOptions): GLEffectWrapper;
42
+ /** Dispose the wrapper and the effect it owns (idempotent). Mirrors lite's
43
+ * `disposeEffectWrapper(wrapper)`. */
44
+ export declare function disposeEffectWrapper(wrapper: GLEffectWrapper): void;
45
+ /** Pixel-space viewport rectangle passed to `setViewport`. */
46
+ export interface GLViewport {
47
+ /** Lower-left X origin in physical pixels. */
48
+ x: number;
49
+ /** Lower-left Y origin in physical pixels. */
50
+ y: number;
51
+ /** Width in physical pixels. */
52
+ w: number;
53
+ /** Height in physical pixels. */
54
+ h: number;
55
+ }
56
+ /** Cached `gl.viewport`. Defaults to the full canvas in pixel coordinates. */
57
+ export declare function setViewport(engine: GLEngineContext, viewport?: GLViewport): void;
58
+ /** Make `wrapper.effect` current and ensure the shared fullscreen quad VAO
59
+ * is bound. This MUST be called BEFORE any `setEffect*` call for the same
60
+ * effect in the current frame (uniform setters write to the currently bound
61
+ * program). */
62
+ export declare function applyEffectWrapper(wrapper: GLEffectWrapper): void;
63
+ /** `gl.drawElements(TRIANGLES, 6, UNSIGNED_SHORT, 0)`. No-op when the
64
+ * context is lost or there is no current program. */
65
+ export declare function drawEffect(engine: GLEngineContext): void;
@@ -0,0 +1,132 @@
1
+ import { createEffect, disposeEffect, useEffect } from "./effect.js";
2
+ import { applyGLStates } from "./apply-states.js";
3
+ /** Built-in fullscreen-quad vertex shader, used when `GLEffectWrapperOptions`
4
+ * omits `vertexSource`. Maps the package's fullscreen-quad positions
5
+ * (attribute location 0) to clip space and forwards a 0..1 `vUv` varying —
6
+ * the WebGL counterpart of lite's default `vertexWGSL`, so callers can pass
7
+ * only `fragmentSource`. */
8
+ const DEFAULT_FULLSCREEN_VERTEX_SOURCE = `#version 300 es
9
+ layout(location = 0) in vec2 position;
10
+ out vec2 vUv;
11
+ void main() {
12
+ vUv = position * 0.5 + 0.5;
13
+ gl_Position = vec4(position, 0.0, 1.0);
14
+ }`;
15
+ /** Compile a fullscreen effect from shader source and wrap it; the wrapper OWNS
16
+ * the resulting `GLEffect`. Mirrors lite's `createEffectWrapper(engine, options)`.
17
+ * When `vertexSource` is omitted, a built-in fullscreen-quad vertex shader is
18
+ * used, so callers can supply only `fragmentSource`. */
19
+ export function createEffectWrapper(engine, options) {
20
+ const name = options.name ?? "effect-wrapper";
21
+ const effect = createEffect(engine, {
22
+ name,
23
+ vertexSource: options.vertexSource ?? DEFAULT_FULLSCREEN_VERTEX_SOURCE,
24
+ fragmentSource: options.fragmentSource,
25
+ uniformNames: options.uniformNames ?? [],
26
+ samplerNames: options.samplerNames ?? [],
27
+ attributeNames: options.attributeNames,
28
+ defines: options.defines,
29
+ });
30
+ return { name, effect, _engine: engine, _disposed: false };
31
+ }
32
+ /** Dispose the wrapper and the effect it owns (idempotent). Mirrors lite's
33
+ * `disposeEffectWrapper(wrapper)`. */
34
+ export function disposeEffectWrapper(wrapper) {
35
+ if (wrapper._disposed) {
36
+ return;
37
+ }
38
+ wrapper._disposed = true;
39
+ disposeEffect(wrapper._engine, wrapper.effect);
40
+ }
41
+ /** Cached `gl.viewport`. Defaults to the full canvas in pixel coordinates. */
42
+ export function setViewport(engine, viewport) {
43
+ if (engine._isLost || engine._disposed) {
44
+ return;
45
+ }
46
+ const x = viewport?.x ?? 0;
47
+ const y = viewport?.y ?? 0;
48
+ const w = viewport?.w ?? engine.canvas.width;
49
+ const h = viewport?.h ?? engine.canvas.height;
50
+ const s = engine._state;
51
+ if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {
52
+ return;
53
+ }
54
+ s.viewportX = x;
55
+ s.viewportY = y;
56
+ s.viewportW = w;
57
+ s.viewportH = h;
58
+ engine.gl.viewport(x, y, w, h);
59
+ }
60
+ /** Make `wrapper.effect` current and ensure the shared fullscreen quad VAO
61
+ * is bound. This MUST be called BEFORE any `setEffect*` call for the same
62
+ * effect in the current frame (uniform setters write to the currently bound
63
+ * program). */
64
+ export function applyEffectWrapper(wrapper) {
65
+ const engine = wrapper._engine;
66
+ if (engine._isLost || engine._disposed || wrapper._disposed) {
67
+ return;
68
+ }
69
+ ensureQuad(engine);
70
+ useEffect(engine, wrapper.effect);
71
+ }
72
+ /** `gl.drawElements(TRIANGLES, 6, UNSIGNED_SHORT, 0)`. No-op when the
73
+ * context is lost or there is no current program. */
74
+ export function drawEffect(engine) {
75
+ if (engine._isLost || engine._disposed) {
76
+ return;
77
+ }
78
+ if (engine._state.currentProgram === null) {
79
+ return;
80
+ }
81
+ applyGLStates(engine);
82
+ engine.gl.drawElements(engine.gl.TRIANGLES, 6, engine.gl.UNSIGNED_SHORT, 0);
83
+ }
84
+ /** Lazy fullscreen quad. Built on first call; thereafter the VAO is cached on
85
+ * `_state.quadVao` and rebinding is a single cached call. Cleared by
86
+ * `webglcontextlost` and transparently rebuilt by the next
87
+ * `applyEffectWrapper` after restore.
88
+ *
89
+ * Position attribute is enabled at location 0 — every effect's
90
+ * `createEffect` calls `gl.bindAttribLocation(program, 0, attributeNames[0])`
91
+ * BEFORE link, so the shared VAO is correct across all programs. */
92
+ function ensureQuad(engine) {
93
+ const s = engine._state;
94
+ const gl = engine.gl;
95
+ if (s.quadVao !== null) {
96
+ if (s.boundVao !== s.quadVao) {
97
+ gl.bindVertexArray(s.quadVao);
98
+ s.boundVao = s.quadVao;
99
+ }
100
+ return;
101
+ }
102
+ const vao = gl.createVertexArray();
103
+ if (vao === null) {
104
+ throw new Error("lite-gl: gl.createVertexArray returned null");
105
+ }
106
+ s.quadVao = vao;
107
+ gl.bindVertexArray(vao);
108
+ s.boundVao = vao;
109
+ const vbo = gl.createBuffer();
110
+ if (vbo === null) {
111
+ throw new Error("lite-gl: gl.createBuffer returned null (VBO)");
112
+ }
113
+ s.quadVbo = vbo;
114
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
115
+ s.boundArrayBuffer = vbo;
116
+ gl.bufferData(gl.ARRAY_BUFFER, QUAD_POSITIONS, gl.STATIC_DRAW);
117
+ const ibo = gl.createBuffer();
118
+ if (ibo === null) {
119
+ throw new Error("lite-gl: gl.createBuffer returned null (IBO)");
120
+ }
121
+ s.quadIbo = ibo;
122
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
123
+ s.boundElementBuffer = ibo;
124
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, QUAD_INDICES, gl.STATIC_DRAW);
125
+ gl.enableVertexAttribArray(0);
126
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
127
+ }
128
+ /** Typed-array literal — pure per bundler convention. Matches Babylon's
129
+ * `EffectRenderer` default geometry exactly. */
130
+ const QUAD_POSITIONS = new Float32Array([1, 1, -1, 1, -1, -1, 1, -1]);
131
+ const QUAD_INDICES = new Uint16Array([0, 1, 2, 0, 2, 3]);
132
+ //# sourceMappingURL=effect-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect-renderer.js","sourceRoot":"","sources":["../src/effect-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["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"]}
package/effect.d.ts ADDED
@@ -0,0 +1,142 @@
1
+ import type { GLEngineContext } from "./context.js";
2
+ import { type GLTexture } from "./texture.js";
3
+ /** Inputs to `createEffect`: shader sources plus the uniform, sampler and
4
+ * attribute names whose locations are resolved during readiness finalization. */
5
+ export interface GLEffectOptions {
6
+ /** Human-readable label, surfaced in compile/link error messages. */
7
+ name: string;
8
+ /** GLSL ES 3.00 source, ready for `gl.shaderSource`. */
9
+ vertexSource: string;
10
+ /** GLSL ES 3.00 source, ready for `gl.shaderSource`. */
11
+ fragmentSource: string;
12
+ /** Declared uniform names. Locations are resolved during readiness
13
+ * finalization. Names not declared here are legal but allocate cache
14
+ * slots lazily on first setter use. */
15
+ uniformNames: readonly string[];
16
+ /** Declared sampler names, in unit-assignment order. Each gets a fixed
17
+ * texture unit assigned during readiness finalization, and
18
+ * `gl.uniform1i(loc, unit)` is called exactly once per program lifetime
19
+ * (re-run after `webglcontextrestored`). */
20
+ samplerNames: readonly string[];
21
+ /** Default `["position"]`. The first attribute is bound to location 0 via
22
+ * `gl.bindAttribLocation(program, 0, name)` BEFORE link, so the shared
23
+ * fullscreen-quad VAO always feeds the same location. */
24
+ attributeNames?: readonly string[];
25
+ /** Optional `#define` block. Each unique `defines` string must be paired
26
+ * with the same vertex/fragment source via a separate `createEffect` call —
27
+ * the package does NOT cache compiled variants. */
28
+ defines?: string;
29
+ }
30
+ /** A compiled + linked shader program with cached uniform, sampler and
31
+ * attribute locations. Created by `createEffect`; most fields are managed
32
+ * internally — drive it via `isEffectReady` / `useEffect` / the `setEffect*`
33
+ * setters rather than mutating it directly. */
34
+ export interface GLEffect {
35
+ /** The `name` from the originating `GLEffectOptions`. */
36
+ readonly name: string;
37
+ /** The options this effect was created from (retained for context-restore). */
38
+ readonly options: GLEffectOptions;
39
+ /** The live `WebGLProgram`. Swapped for a fresh handle after context-restore. */
40
+ program: WebGLProgram;
41
+ /** Resolved during readiness finalization. Missing names map to `null` —
42
+ * setters with a `null` location are silent no-ops (matches Babylon). */
43
+ uniformLocations: {
44
+ [name: string]: WebGLUniformLocation | null;
45
+ };
46
+ /** Fixed unit assignment for declared samplers, index into
47
+ * `_state.boundTextures`. */
48
+ samplerUnits: {
49
+ [name: string]: number;
50
+ };
51
+ /** Resolved attribute locations, keyed by attribute name. */
52
+ attributeLocations: {
53
+ [name: string]: number;
54
+ };
55
+ /** True once the program has linked and finalization has run; the
56
+ * `setEffect*` setters are no-ops until then. Poll `isEffectReady` to advance it. */
57
+ isReady: boolean;
58
+ }
59
+ /** Compile + link a new effect. Does NOT block on link completion — `isReady`
60
+ * starts false; consumers poll `isEffectReady` (typically from their render
61
+ * callback) to drive finalization. */
62
+ export declare function createEffect(engine: GLEngineContext, options: GLEffectOptions): GLEffect;
63
+ /** Poll the link state and, on first success, run finalization (uniform-
64
+ * location resolution + one-shot sampler-unit `uniform1i` assignment +
65
+ * `_onCompiled` callbacks). Returns `true` once the effect is usable. */
66
+ export declare function isEffectReady(engine: GLEngineContext, effect: GLEffect): boolean;
67
+ /** Fires `cb` synchronously if the effect is already ready; otherwise queues
68
+ * it for the next finalization. */
69
+ export declare function executeWhenCompiled(engine: GLEngineContext, effect: GLEffect, cb: (e: GLEffect) => void): void;
70
+ /** Decrement the share count and, on the last release, delete the effect's
71
+ * program + shaders, unregister it from the context + cache, and clear the
72
+ * cached current-program if it pointed at this effect. A shared effect (still
73
+ * referenced by another `createEffect` caller) is kept alive. Call exactly ONCE
74
+ * per `createEffect` (each call decrements the ref count); safe (no-op) once the
75
+ * effect is fully torn down. */
76
+ export declare function disposeEffect(engine: GLEngineContext, effect: GLEffect): void;
77
+ /** Cached `gl.useProgram`. No-op when the effect is not ready or already current. */
78
+ export declare function useEffect(engine: GLEngineContext, effect: GLEffect): void;
79
+ /** Cached `gl.uniform1f`. No-op when context-lost, the effect isn't ready, the
80
+ * uniform is absent, or the value is unchanged since last upload. */
81
+ export declare function setEffectFloat(engine: GLEngineContext, effect: GLEffect, name: string, x: number): void;
82
+ /** Cached `gl.uniform2f`. No-op when context-lost, the effect isn't ready, the
83
+ * uniform is absent, or the value is unchanged since last upload. */
84
+ export declare function setEffectFloat2(engine: GLEngineContext, effect: GLEffect, name: string, x: number, y: number): void;
85
+ /** Cached `gl.uniform3f`. No-op when context-lost, the effect isn't ready, the
86
+ * uniform is absent, or the value is unchanged since last upload. */
87
+ export declare function setEffectFloat3(engine: GLEngineContext, effect: GLEffect, name: string, x: number, y: number, z: number): void;
88
+ /** Cached `gl.uniform4f`. No-op when context-lost, the effect isn't ready, the
89
+ * uniform is absent, or the value is unchanged since last upload. */
90
+ export declare function setEffectFloat4(engine: GLEngineContext, effect: GLEffect, name: string, x: number, y: number, z: number, w: number): void;
91
+ /** Cached `gl.uniform3f` from an r/g/b color object. Delegates to `setEffectFloat3`. */
92
+ export declare function setEffectColor3(engine: GLEngineContext, effect: GLEffect, name: string, c: {
93
+ r: number;
94
+ g: number;
95
+ b: number;
96
+ }): void;
97
+ /** Cached `gl.uniform4f` from an r/g/b/a color object. Delegates to `setEffectFloat4`. */
98
+ export declare function setEffectColor4(engine: GLEngineContext, effect: GLEffect, name: string, c: {
99
+ r: number;
100
+ g: number;
101
+ b: number;
102
+ a: number;
103
+ }): void;
104
+ /** Cached `gl.uniform2f` from an `{x,y}` vector object — the lite-gl equivalent
105
+ * of Babylon's `Effect.setVector2`. Delegates to `setEffectFloat2`. */
106
+ export declare function setEffectVector2(engine: GLEngineContext, effect: GLEffect, name: string, v: {
107
+ x: number;
108
+ y: number;
109
+ }): void;
110
+ /** Cached `gl.uniform4f` from an r/g/b/a color WITHOUT premultiplication — the
111
+ * lite-gl equivalent of Babylon's `Effect.setDirectColor4`. Delegates to
112
+ * `setEffectFloat4` (lite-gl never premultiplies in the uniform setters, so
113
+ * this matches `setEffectColor4`; the distinct name eases the ShapeBuilder
114
+ * port). */
115
+ export declare function setEffectDirectColor4(engine: GLEngineContext, effect: GLEffect, name: string, c: {
116
+ r: number;
117
+ g: number;
118
+ b: number;
119
+ a: number;
120
+ }): void;
121
+ /** Cached `gl.uniform1i`. No-op when context-lost, the effect isn't ready, the
122
+ * uniform is absent, or the value is unchanged since last upload. */
123
+ export declare function setEffectInt(engine: GLEngineContext, effect: GLEffect, name: string, x: number): void;
124
+ /** `gl.uniformMatrix4fv` from a column-major 4×4 matrix — the lite-gl
125
+ * equivalent of Babylon's `Effect.setMatrix`. Not value-cached. */
126
+ export declare function setEffectMatrix(engine: GLEngineContext, effect: GLEffect, name: string, matrix: Float32Array | number[]): void;
127
+ /** `gl.uniformMatrix3fv` from a column-major 3×3 matrix — the lite-gl
128
+ * equivalent of Babylon's `Effect.setMatrix3x3`. Not value-cached. */
129
+ export declare function setEffectMatrix3x3(engine: GLEngineContext, effect: GLEffect, name: string, matrix: Float32Array | number[]): void;
130
+ /** `gl.uniform1fv` — a flat float array (`Effect.setFloatArray` / `setArray`).
131
+ * Not value-cached. */
132
+ export declare function setEffectFloatArray(engine: GLEngineContext, effect: GLEffect, name: string, array: Float32Array | number[]): void;
133
+ /** `gl.uniform4fv` — an array of `vec4`s (`Effect.setFloatArray4` / `setArray4`).
134
+ * Not value-cached. */
135
+ export declare function setEffectFloatArray4(engine: GLEngineContext, effect: GLEffect, name: string, array: Float32Array | number[]): void;
136
+ /** `gl.uniform1iv` — a flat int array (`Effect.setIntArray`). Not value-cached. */
137
+ export declare function setEffectIntArray(engine: GLEngineContext, effect: GLEffect, name: string, array: Int32Array | number[]): void;
138
+ /** Bind a texture to the sampler's pre-assigned unit (§4.4). NO `gl.uniform1i`
139
+ * is issued — that was done exactly once per program lifetime during
140
+ * finalization. This is the key win over Babylon's `Effect.setTexture` which
141
+ * re-issues the sampler binding on every call. */
142
+ export declare function setEffectTexture(engine: GLEngineContext, effect: GLEffect, samplerName: string, tex: GLTexture): void;