@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/README.md +135 -0
- package/depth-stencil.d.ts +231 -0
- package/depth-stencil.js +277 -0
- package/depth-stencil.js.map +1 -0
- package/dynamic-texture.d.ts +149 -0
- package/dynamic-texture.js +73 -0
- package/dynamic-texture.js.map +1 -0
- package/effect-BxxwfB_O.js +737 -0
- package/effect-BxxwfB_O.js.map +1 -0
- package/html-texture.d.ts +143 -0
- package/html-texture.js +89 -0
- package/html-texture.js.map +1 -0
- package/index.d.ts +1482 -0
- package/index.js +263 -0
- package/index.js.map +1 -0
- package/mesh.d.ts +307 -0
- package/mesh.js +334 -0
- package/mesh.js.map +1 -0
- package/package.json +62 -0
- package/render-target.d.ts +290 -0
- package/render-target.js +355 -0
- package/render-target.js.map +1 -0
- package/scissor.d.ts +72 -0
- package/scissor.js +35 -0
- package/scissor.js.map +1 -0
- package/sprites--1oyVtJ3.js +437 -0
- package/sprites--1oyVtJ3.js.map +1 -0
- package/sprites.d.ts +263 -0
- package/sprites.js +10 -0
- package/sprites.js.map +1 -0
- package/state--j_ncWIi.js +155 -0
- package/state--j_ncWIi.js.map +1 -0
- package/texture-DaMd1gGm.js +329 -0
- package/texture-DaMd1gGm.js.map +1 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind the render target's framebuffer as the draw target and set the viewport
|
|
3
|
+
* to cover it. `rt = null` binds the default (canvas) framebuffer and resets the
|
|
4
|
+
* viewport to the full canvas — the counterpart of Babylon's
|
|
5
|
+
* `restoreDefaultFramebuffer`. Subsequent `drawEffect` / `drawIndexed` /
|
|
6
|
+
* `clearEngine` calls write into the bound target.
|
|
7
|
+
*
|
|
8
|
+
* Cached. No-op on a lost/disposed context or a disposed `rt`. Mipmaps are NOT
|
|
9
|
+
* regenerated here — refresh a target's mip chain explicitly via
|
|
10
|
+
* {@link generateRenderTargetMipMaps} after rendering into it.
|
|
11
|
+
*
|
|
12
|
+
* @param engine - The engine.
|
|
13
|
+
* @param rt - The render target to draw into, or `null` for the canvas.
|
|
14
|
+
*/
|
|
15
|
+
export declare function bindRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null): void;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create an offscreen **float / half-float** render target — the HDR opt-in
|
|
19
|
+
* counterpart of {@link createRenderTarget}. This is the only render-target
|
|
20
|
+
* factory that references the `RGBA16F` / `RGBA32F` sized-format table, so RGBA8
|
|
21
|
+
* consumers ship none of it.
|
|
22
|
+
*
|
|
23
|
+
* Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.
|
|
24
|
+
* The requested type is downgraded to the best renderable type the engine
|
|
25
|
+
* supports (mirroring Babylon's `getTextureType`).
|
|
26
|
+
*
|
|
27
|
+
* @param engine - The engine to allocate GL resources on.
|
|
28
|
+
* @param options - See {@link GLFloatRenderTargetOptions}.
|
|
29
|
+
* @returns The new {@link GLRenderTarget}.
|
|
30
|
+
* @throws As {@link createRenderTarget}.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createFloatRenderTarget(engine: GLEngineContext, options: GLFloatRenderTargetOptions): GLRenderTarget;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a {@link GLPingPong}: two same-sized {@link GLRenderTarget}s for
|
|
36
|
+
* self-feedback effects. `read` starts as the first target and `write` the
|
|
37
|
+
* second; {@link GLPingPong.swap} exchanges them allocation-free.
|
|
38
|
+
*
|
|
39
|
+
* @param engine - The engine to create GL resources on.
|
|
40
|
+
* @param options - Applied identically to both targets.
|
|
41
|
+
* @returns The new {@link GLPingPong}.
|
|
42
|
+
* @throws As {@link createRenderTarget}. If the second target fails to build the
|
|
43
|
+
* first is disposed before rethrowing (no leak).
|
|
44
|
+
*/
|
|
45
|
+
export declare function createPingPong(engine: GLEngineContext, options: GLRenderTargetOptions): GLPingPong;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create an offscreen **RGBA8** render target.
|
|
49
|
+
*
|
|
50
|
+
* The color attachment is an owned {@link GLTexture} (rebuilt by this target's
|
|
51
|
+
* own restore hook), unless {@link GLRenderTargetOptions.colorTexture} supplies a
|
|
52
|
+
* caller-managed (BYO) one. Mirrors Babylon's `createRenderTargetTexture`.
|
|
53
|
+
*
|
|
54
|
+
* @param engine - The engine to allocate GL resources on.
|
|
55
|
+
* @param options - See {@link GLRenderTargetOptions} (`width`/`height` required).
|
|
56
|
+
* @returns The new {@link GLRenderTarget}.
|
|
57
|
+
* @throws If `width`/`height` are not positive integers, a GL handle could not
|
|
58
|
+
* be allocated, or the resulting framebuffer is not complete. On failure every
|
|
59
|
+
* partial GPU object (including an owned color texture) is released first.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createRenderTarget(engine: GLEngineContext, options: GLRenderTargetOptions): GLRenderTarget;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Release both targets of a {@link GLPingPong}. Idempotent, and a no-op for
|
|
65
|
+
* `null`/`undefined` (matching {@link disposeRenderTarget}).
|
|
66
|
+
*
|
|
67
|
+
* @param engine - The engine that owns `pp`.
|
|
68
|
+
* @param pp - The ping-pong pair to release, or `null`/`undefined` for a no-op.
|
|
69
|
+
*/
|
|
70
|
+
export declare function disposePingPong(engine: GLEngineContext, pp: GLPingPong | null | undefined): void;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Release the render target's framebuffer, depth/stencil renderbuffer and (iff
|
|
74
|
+
* owned) color texture, and unregister it from the engine. Idempotent, and a
|
|
75
|
+
* no-op for `null`/`undefined` (so an optional target can be released
|
|
76
|
+
* unconditionally). Clears the bound-framebuffer cache if it pointed at this
|
|
77
|
+
* target, and any sampler slot that held the color texture handle.
|
|
78
|
+
*
|
|
79
|
+
* A BYO {@link GLRenderTargetOptions.colorTexture} is NOT disposed here — it is
|
|
80
|
+
* engine-managed and the caller owns its lifetime.
|
|
81
|
+
*
|
|
82
|
+
* @param engine - The engine.
|
|
83
|
+
* @param rt - The render target to dispose, or `null`/`undefined` for a no-op.
|
|
84
|
+
*/
|
|
85
|
+
export declare function disposeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null | undefined): void;
|
|
86
|
+
|
|
87
|
+
/** Regenerate a render target's color-attachment mip chain from its (freshly
|
|
88
|
+
* rendered) level-0 — mipmaps for render targets are a pure manual opt-in
|
|
89
|
+
* (call this after rendering into the target). No-op for a disposed target, a
|
|
90
|
+
* handle-less color attachment, or a lost/disposed context. */
|
|
91
|
+
export declare function generateRenderTargetMipMaps(engine: GLEngineContext, rt: GLRenderTarget): void;
|
|
92
|
+
|
|
93
|
+
/** Read-only WebGL2 capability limits, queried once at context creation. */
|
|
94
|
+
declare interface GLEngineCaps {
|
|
95
|
+
/** `gl.MAX_TEXTURE_SIZE` — largest supported texture dimension, in texels. */
|
|
96
|
+
readonly maxTextureSize: number;
|
|
97
|
+
/** `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` — number of sampler binding slots. */
|
|
98
|
+
readonly maxTextureUnits: number;
|
|
99
|
+
/** The `KHR_parallel_shader_compile` extension used for async link polling,
|
|
100
|
+
* or null when unsupported — linking is then treated as synchronous. */
|
|
101
|
+
readonly parallelShaderCompile: {
|
|
102
|
+
COMPLETION_STATUS_KHR: number;
|
|
103
|
+
} | null;
|
|
104
|
+
/** True when 32-bit float color attachments are renderable
|
|
105
|
+
* (`EXT_color_buffer_float`). Mirrors Babylon's `caps.textureFloatRender`. */
|
|
106
|
+
readonly textureFloatRender: boolean;
|
|
107
|
+
/** True when 32-bit float textures support linear filtering
|
|
108
|
+
* (`OES_texture_float_linear`). Mirrors `caps.textureFloatLinearFiltering`. */
|
|
109
|
+
readonly textureFloatLinearFiltering: boolean;
|
|
110
|
+
/** True when 16-bit half-float color attachments are renderable
|
|
111
|
+
* (`EXT_color_buffer_float` or `EXT_color_buffer_half_float`). Mirrors
|
|
112
|
+
* `caps.textureHalfFloatRender`. */
|
|
113
|
+
readonly textureHalfFloatRender: boolean;
|
|
114
|
+
/** Half-float linear filtering — always `true` in WebGL2 (it is core).
|
|
115
|
+
* Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */
|
|
116
|
+
readonly textureHalfFloatLinearFiltering: boolean;
|
|
117
|
+
/** Whether non-power-of-two textures need POT dimensions for mips / wrap.
|
|
118
|
+
* Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */
|
|
119
|
+
readonly needPOTTextures: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Pure-state handle for a WebGL2 canvas + its cached GL state.
|
|
124
|
+
*
|
|
125
|
+
* INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.
|
|
126
|
+
* Doing so silently corrupts the cache in `_state`. The package owns every
|
|
127
|
+
* GL call. (`engine.gl` is exposed only so downstream code that already has the
|
|
128
|
+
* pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT
|
|
129
|
+
* call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)
|
|
130
|
+
*/
|
|
131
|
+
declare interface GLEngineContext {
|
|
132
|
+
/** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is
|
|
133
|
+
* supported for worker render paths (e.g. the Lottie player); it has no CSS
|
|
134
|
+
* box, so it must be sized explicitly via `setGLEngineSize` rather than the
|
|
135
|
+
* CSS-derived `resizeGLEngine`. */
|
|
136
|
+
readonly canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
137
|
+
/** The raw WebGL2 context. Do NOT mutate GL state through it — see the
|
|
138
|
+
* type-level invariant above; the package owns every state-changing call. */
|
|
139
|
+
readonly gl: WebGL2RenderingContext;
|
|
140
|
+
/** Queried capability limits for this context. */
|
|
141
|
+
readonly caps: GLEngineCaps;
|
|
142
|
+
|
|
143
|
+
/** Options for {@link createFloatRenderTarget} — {@link GLRenderTargetOptions}
|
|
144
|
+
* plus the float color `type`. */
|
|
145
|
+
export declare interface GLFloatRenderTargetOptions extends GLRenderTargetOptions {
|
|
146
|
+
/** Float color attachment type. Default `gl.HALF_FLOAT`. Pass `gl.FLOAT` for
|
|
147
|
+
* full 32-bit. Downgraded to the best renderable type the engine supports
|
|
148
|
+
* (`caps.textureFloatRender` / `caps.textureHalfFloatRender`), mirroring
|
|
149
|
+
* Babylon's `getTextureType`. */
|
|
150
|
+
type?: GLenum;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* A pair of {@link GLRenderTarget}s for self-feedback effects: SAMPLE the
|
|
155
|
+
* {@link GLPingPong.read | read} target (last frame's output) while RENDERING
|
|
156
|
+
* into the {@link GLPingPong.write | write} target, then {@link GLPingPong.swap}.
|
|
157
|
+
*/
|
|
158
|
+
export declare interface GLPingPong {
|
|
159
|
+
/** The target to SAMPLE this frame (the previous frame's output). */
|
|
160
|
+
readonly read: GLRenderTarget;
|
|
161
|
+
/** The target to RENDER into this frame. */
|
|
162
|
+
readonly write: GLRenderTarget;
|
|
163
|
+
/** Exchange `read` and `write`. Call after rendering the `write` target each
|
|
164
|
+
* frame. Allocation-free — flips an internal index, no objects created. */
|
|
165
|
+
swap(): void;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* An offscreen render target — a `WebGLFramebuffer` wrapping a color
|
|
169
|
+
* {@link GLTexture} and an optional depth / stencil renderbuffer. The lite-gl
|
|
170
|
+
* counterpart of Babylon's `RenderTargetWrapper`.
|
|
171
|
+
*/
|
|
172
|
+
export declare interface GLRenderTarget {
|
|
173
|
+
/** The color attachment, sampleable like any other {@link GLTexture}
|
|
174
|
+
* (`setEffectTexture` / `bindTexture`). For an owned attachment its handle
|
|
175
|
+
* is swapped on `webglcontextrestored` while consumers keep this same
|
|
176
|
+
* reference. */
|
|
177
|
+
texture: GLTexture;
|
|
178
|
+
/** Color attachment width in texels. */
|
|
179
|
+
width: number;
|
|
180
|
+
/** Color attachment height in texels. */
|
|
181
|
+
height: number;
|
|
182
|
+
/** True once the color attachment + framebuffer are allocated. */
|
|
183
|
+
isReady: boolean;
|
|
184
|
+
|
|
185
|
+
/** Options for {@link createRenderTarget}. `width`/`height` are required; every
|
|
186
|
+
* other field has a Babylon-matching default. The bare
|
|
187
|
+
* `createRenderTarget(engine, { width, height })` makes an RGBA8 color-only
|
|
188
|
+
* target with linear filtering and clamp wrapping. */
|
|
189
|
+
export declare interface GLRenderTargetOptions {
|
|
190
|
+
/** Color attachment width in texels. Must be a positive integer. */
|
|
191
|
+
width: number;
|
|
192
|
+
/** Color attachment height in texels. Must be a positive integer. */
|
|
193
|
+
height: number;
|
|
194
|
+
/** Allocate a depth renderbuffer (`DEPTH_COMPONENT16`). Default `false`.
|
|
195
|
+
* Stencil is NOT a create option — opt in (packed depth+stencil, or
|
|
196
|
+
* stencil-only) via `generateRenderTargetStencil`
|
|
197
|
+
* (`@babylonjs/lite-gl/depth-stencil`), which keeps the stencil/packed
|
|
198
|
+
* renderbuffer code out of the render-target core bundle. */
|
|
199
|
+
generateDepthBuffer?: boolean;
|
|
200
|
+
/** Color texture minification filter. Default `gl.LINEAR`. */
|
|
201
|
+
minFilter?: GLenum;
|
|
202
|
+
/** Color texture magnification filter. Default `gl.LINEAR`. */
|
|
203
|
+
magFilter?: GLenum;
|
|
204
|
+
/** Color texture S wrap. Default `gl.CLAMP_TO_EDGE`. */
|
|
205
|
+
wrapS?: GLenum;
|
|
206
|
+
/** Color texture T wrap. Default `gl.CLAMP_TO_EDGE`. */
|
|
207
|
+
wrapT?: GLenum;
|
|
208
|
+
/** Attach a caller-supplied (BYO) color {@link GLTexture} instead of creating
|
|
209
|
+
* one. When supplied the render target does NOT own or restore it — the
|
|
210
|
+
* texture is engine-managed (restored by the standard texture-restore path
|
|
211
|
+
* first) and the RT re-attaches its swapped handle afterwards. The caller is
|
|
212
|
+
* responsible for sizing it to `width`×`height` and for disposing it. */
|
|
213
|
+
colorTexture?: GLTexture;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Pure-state texture handle. The `handle` field is MUTABLE so the same logical
|
|
218
|
+
* texture survives a `webglcontextrestored` event — every consumer keeps the
|
|
219
|
+
* same `GLTexture` reference; only the internal `WebGLTexture` is swapped.
|
|
220
|
+
*
|
|
221
|
+
* `loadTexture2D` also uses the same handle for the 1×1 placeholder upload AND
|
|
222
|
+
* the final image upload — so a `bindTexture(engine, unit, tex)` made before the
|
|
223
|
+
* image has decoded remains valid once the image arrives.
|
|
224
|
+
*/
|
|
225
|
+
declare interface GLTexture {
|
|
226
|
+
/** The live `WebGLTexture`. MUTABLE — swapped for a fresh handle on
|
|
227
|
+
* `webglcontextrestored` while consumers keep the same `GLTexture` reference. */
|
|
228
|
+
handle: WebGLTexture;
|
|
229
|
+
/** GL texture target (always `gl.TEXTURE_2D` for this package). */
|
|
230
|
+
readonly target: GLenum;
|
|
231
|
+
/** Texture width in texels. Updated once an async upload resolves. */
|
|
232
|
+
width: number;
|
|
233
|
+
/** Texture height in texels. Updated once an async upload resolves. */
|
|
234
|
+
height: number;
|
|
235
|
+
/** True when the texture is safe to sample with final content (placeholders
|
|
236
|
+
* read as not-ready until their image/upload completes). */
|
|
237
|
+
isReady: boolean;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Synchronously read back a rectangle of the render target's color attachment
|
|
241
|
+
* via `gl.readPixels` — the lite-gl equivalent of Babylon's
|
|
242
|
+
* `_readTexturePixelsSync`. Binds the target's framebuffer (leaving it bound,
|
|
243
|
+
* matching Babylon).
|
|
244
|
+
*
|
|
245
|
+
* The returned array element type follows the color attachment type:
|
|
246
|
+
* `Uint8Array` for `UNSIGNED_BYTE`, `Float32Array` for `FLOAT`, `Uint16Array`
|
|
247
|
+
* for `HALF_FLOAT`. Origin is GL bottom-left.
|
|
248
|
+
*
|
|
249
|
+
* @param engine - The engine.
|
|
250
|
+
* @param rt - The render target to read from.
|
|
251
|
+
* @param x - Lower-left X of the read rectangle, in texels.
|
|
252
|
+
* @param y - Lower-left Y of the read rectangle, in texels.
|
|
253
|
+
* @param width - Read rectangle width in texels.
|
|
254
|
+
* @param height - Read rectangle height in texels.
|
|
255
|
+
* @param into - Optional preallocated buffer (`width*height*4` elements of the
|
|
256
|
+
* matching type). Reused to avoid per-call allocation.
|
|
257
|
+
* @returns The pixel buffer (the provided `into`, or a freshly allocated one).
|
|
258
|
+
* Empty buffer on a lost/disposed context.
|
|
259
|
+
*/
|
|
260
|
+
export declare function readRenderTargetPixels(engine: GLEngineContext, rt: GLRenderTarget, x: number, y: number, width: number, height: number, into?: ArrayBufferView): ArrayBufferView;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Resize both targets of a {@link GLPingPong}. No-op when disposed.
|
|
264
|
+
*
|
|
265
|
+
* @param engine - The engine that owns `pp`.
|
|
266
|
+
* @param pp - The ping-pong pair to resize.
|
|
267
|
+
* @param width - New width in texels (positive integer).
|
|
268
|
+
* @param height - New height in texels (positive integer).
|
|
269
|
+
*/
|
|
270
|
+
export declare function resizePingPong(engine: GLEngineContext, pp: GLPingPong, width: number, height: number): void;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Resize the render target's color attachment (and depth/stencil renderbuffer).
|
|
274
|
+
* Reallocates storage at the new size; the contents are discarded. The
|
|
275
|
+
* `GLRenderTarget` / `GLTexture` identity is preserved, so consumers and
|
|
276
|
+
* effect-sampler bindings holding the reference stay valid. If this target was
|
|
277
|
+
* the live draw target, it is rebound (with the new-size viewport) afterwards.
|
|
278
|
+
*
|
|
279
|
+
* No-op when the size is unchanged or `rt` is disposed. While the context is
|
|
280
|
+
* lost the new size is recorded but the GL reallocation is deferred to the
|
|
281
|
+
* restore hook.
|
|
282
|
+
*
|
|
283
|
+
* @param engine - The engine.
|
|
284
|
+
* @param rt - The render target to resize.
|
|
285
|
+
* @param width - New width in texels (≥ 1).
|
|
286
|
+
* @param height - New height in texels (≥ 1).
|
|
287
|
+
*/
|
|
288
|
+
export declare function resizeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget, width: number, height: number): void;
|
|
289
|
+
|
|
290
|
+
export { }
|
package/render-target.js
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { p as pickSizedInternalFormat, i as bindTextureForUpload } from "./texture-DaMd1gGm.js";
|
|
2
|
+
const UNSIGNED_BYTE = 5121;
|
|
3
|
+
const HALF_FLOAT = 5131;
|
|
4
|
+
const FLOAT = 5126;
|
|
5
|
+
const RGBA = 6408;
|
|
6
|
+
const RGBA8 = 32856;
|
|
7
|
+
const LINEAR = 9729;
|
|
8
|
+
const CLAMP_TO_EDGE = 33071;
|
|
9
|
+
function createRenderTarget(engine, options) {
|
|
10
|
+
return buildRT(engine, options, RGBA8, RGBA, UNSIGNED_BYTE);
|
|
11
|
+
}
|
|
12
|
+
function createFloatRenderTarget(engine, options) {
|
|
13
|
+
const type = resolveColorType(engine, options.type ?? HALF_FLOAT);
|
|
14
|
+
const internalFormat = pickSizedInternalFormat(engine.gl, RGBA, type);
|
|
15
|
+
return buildRT(engine, options, internalFormat, RGBA, type);
|
|
16
|
+
}
|
|
17
|
+
function bindRenderTarget(engine, rt) {
|
|
18
|
+
if (engine._isLost || engine._disposed) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (rt !== null && rt._disposed) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const gl = engine.gl;
|
|
25
|
+
const s = engine._state;
|
|
26
|
+
const fb = rt === null ? null : rt._framebuffer;
|
|
27
|
+
if (s.boundFramebuffer !== fb) {
|
|
28
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
29
|
+
s.boundFramebuffer = fb;
|
|
30
|
+
}
|
|
31
|
+
engine._currentRenderTarget = rt;
|
|
32
|
+
if (rt === null) {
|
|
33
|
+
setViewportCached(engine, 0, 0, engine.canvas.width, engine.canvas.height);
|
|
34
|
+
} else {
|
|
35
|
+
setViewportCached(engine, 0, 0, rt.width, rt.height);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function generateRenderTargetMipMaps(engine, rt) {
|
|
39
|
+
if (engine._isLost || engine._disposed || rt._disposed || rt.texture.handle === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
bindTextureForUpload(engine, rt.texture.handle);
|
|
43
|
+
engine.gl.generateMipmap(engine.gl.TEXTURE_2D);
|
|
44
|
+
}
|
|
45
|
+
function resizeRenderTarget(engine, rt, width, height) {
|
|
46
|
+
var _a, _b;
|
|
47
|
+
if (rt._disposed) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
validateSize(width, height);
|
|
51
|
+
if (rt.width === width && rt.height === height) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
rt.width = width;
|
|
55
|
+
rt.height = height;
|
|
56
|
+
rt.texture.width = width;
|
|
57
|
+
rt.texture.height = height;
|
|
58
|
+
if (engine._isLost || engine._disposed) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const wasBound = engine._state.boundFramebuffer === rt._framebuffer && rt._framebuffer !== null;
|
|
62
|
+
if (!rt._config.ownsColorTexture) {
|
|
63
|
+
(_b = (_a = rt.texture)._updateRaw) == null ? void 0 : _b.call(_a, engine, null, width, height, 4);
|
|
64
|
+
}
|
|
65
|
+
rt._deleteGpu(engine.gl);
|
|
66
|
+
allocateRenderTargetGpu(engine, rt);
|
|
67
|
+
if (wasBound) {
|
|
68
|
+
bindRenderTarget(engine, rt);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function readRenderTargetPixels(engine, rt, x, y, width, height, into) {
|
|
72
|
+
const elements = width * height * 4;
|
|
73
|
+
if (engine._isLost || engine._disposed || rt._disposed) {
|
|
74
|
+
return into ?? new Uint8Array(0);
|
|
75
|
+
}
|
|
76
|
+
const gl = engine.gl;
|
|
77
|
+
const s = engine._state;
|
|
78
|
+
if (s.boundFramebuffer !== rt._framebuffer) {
|
|
79
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, rt._framebuffer);
|
|
80
|
+
s.boundFramebuffer = rt._framebuffer;
|
|
81
|
+
}
|
|
82
|
+
const type = rt._config.type;
|
|
83
|
+
let buffer = into;
|
|
84
|
+
if (buffer === void 0) {
|
|
85
|
+
buffer = type === gl.FLOAT ? new Float32Array(elements) : type === gl.HALF_FLOAT ? new Uint16Array(elements) : new Uint8Array(elements);
|
|
86
|
+
}
|
|
87
|
+
gl.readPixels(x, y, width, height, gl.RGBA, type, buffer);
|
|
88
|
+
return buffer;
|
|
89
|
+
}
|
|
90
|
+
function disposeRenderTarget(engine, rt) {
|
|
91
|
+
if (rt === null || rt === void 0 || rt._disposed) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
rt._disposed = true;
|
|
95
|
+
if (rt._config.ownsColorTexture) {
|
|
96
|
+
rt.texture._disposed = true;
|
|
97
|
+
}
|
|
98
|
+
if (engine._currentRenderTarget === rt) {
|
|
99
|
+
engine._currentRenderTarget = null;
|
|
100
|
+
}
|
|
101
|
+
const i = engine._renderTargets.indexOf(rt);
|
|
102
|
+
if (i !== -1) {
|
|
103
|
+
engine._renderTargets.splice(i, 1);
|
|
104
|
+
}
|
|
105
|
+
const handle = rt.texture.handle;
|
|
106
|
+
if (!engine._isLost && !engine._disposed) {
|
|
107
|
+
rt._deleteGpu(engine.gl);
|
|
108
|
+
} else {
|
|
109
|
+
rt._framebuffer = null;
|
|
110
|
+
rt._depthStencil = null;
|
|
111
|
+
}
|
|
112
|
+
if (handle !== null) {
|
|
113
|
+
const bound = engine._state.boundTextures;
|
|
114
|
+
for (let u = 0; u < bound.length; u++) {
|
|
115
|
+
if (bound[u] === handle) {
|
|
116
|
+
bound[u] = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function createPingPong(engine, options) {
|
|
122
|
+
const a = createRenderTarget(engine, options);
|
|
123
|
+
let b;
|
|
124
|
+
try {
|
|
125
|
+
b = createRenderTarget(engine, options);
|
|
126
|
+
} catch (e) {
|
|
127
|
+
disposeRenderTarget(engine, a);
|
|
128
|
+
throw e;
|
|
129
|
+
}
|
|
130
|
+
const pp = {
|
|
131
|
+
_a: a,
|
|
132
|
+
_b: b,
|
|
133
|
+
_readIsA: true,
|
|
134
|
+
_disposed: false,
|
|
135
|
+
get read() {
|
|
136
|
+
return pp._readIsA ? pp._a : pp._b;
|
|
137
|
+
},
|
|
138
|
+
get write() {
|
|
139
|
+
return pp._readIsA ? pp._b : pp._a;
|
|
140
|
+
},
|
|
141
|
+
swap() {
|
|
142
|
+
pp._readIsA = !pp._readIsA;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
return pp;
|
|
146
|
+
}
|
|
147
|
+
function resizePingPong(engine, pp, width, height) {
|
|
148
|
+
if (pp._disposed) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
resizeRenderTarget(engine, pp._a, width, height);
|
|
152
|
+
resizeRenderTarget(engine, pp._b, width, height);
|
|
153
|
+
}
|
|
154
|
+
function disposePingPong(engine, pp) {
|
|
155
|
+
if (pp === null || pp === void 0 || pp._disposed) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
pp._disposed = true;
|
|
159
|
+
disposeRenderTarget(engine, pp._a);
|
|
160
|
+
disposeRenderTarget(engine, pp._b);
|
|
161
|
+
}
|
|
162
|
+
function buildRT(engine, options, internalFormat, format, type) {
|
|
163
|
+
const width = options.width;
|
|
164
|
+
const height = options.height;
|
|
165
|
+
validateSize(width, height);
|
|
166
|
+
const gl = engine.gl;
|
|
167
|
+
const byo = options.colorTexture;
|
|
168
|
+
const config = {
|
|
169
|
+
internalFormat,
|
|
170
|
+
format,
|
|
171
|
+
type,
|
|
172
|
+
hasDepth: options.generateDepthBuffer ?? false,
|
|
173
|
+
minFilter: options.minFilter ?? LINEAR,
|
|
174
|
+
magFilter: options.magFilter ?? LINEAR,
|
|
175
|
+
wrapS: options.wrapS ?? CLAMP_TO_EDGE,
|
|
176
|
+
wrapT: options.wrapT ?? CLAMP_TO_EDGE,
|
|
177
|
+
ownsColorTexture: byo === void 0
|
|
178
|
+
};
|
|
179
|
+
const texture = byo ?? {
|
|
180
|
+
handle: null,
|
|
181
|
+
target: gl.TEXTURE_2D,
|
|
182
|
+
width,
|
|
183
|
+
height,
|
|
184
|
+
isReady: false,
|
|
185
|
+
_disposed: false,
|
|
186
|
+
_refCount: 1,
|
|
187
|
+
// Owned-by-RT: its storage is (re)allocated by allocateRenderTargetGpu,
|
|
188
|
+
// never via the engine `_textures` replay (it is NOT registered there).
|
|
189
|
+
_upload: () => {
|
|
190
|
+
},
|
|
191
|
+
_wasReady: false
|
|
192
|
+
};
|
|
193
|
+
const rt = {
|
|
194
|
+
texture,
|
|
195
|
+
width,
|
|
196
|
+
height,
|
|
197
|
+
isReady: false,
|
|
198
|
+
_framebuffer: null,
|
|
199
|
+
_depthStencil: null,
|
|
200
|
+
_rebuildDepthStencil: void 0,
|
|
201
|
+
_config: config,
|
|
202
|
+
_disposed: false,
|
|
203
|
+
_deleteGpu: () => {
|
|
204
|
+
},
|
|
205
|
+
_restore: () => {
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
rt._deleteGpu = (glc) => {
|
|
209
|
+
const s = engine._state;
|
|
210
|
+
if (rt._framebuffer !== null) {
|
|
211
|
+
if (s.boundFramebuffer === rt._framebuffer) {
|
|
212
|
+
s.boundFramebuffer = null;
|
|
213
|
+
}
|
|
214
|
+
glc.deleteFramebuffer(rt._framebuffer);
|
|
215
|
+
rt._framebuffer = null;
|
|
216
|
+
}
|
|
217
|
+
if (rt._depthStencil !== null) {
|
|
218
|
+
glc.deleteRenderbuffer(rt._depthStencil);
|
|
219
|
+
rt._depthStencil = null;
|
|
220
|
+
}
|
|
221
|
+
if (config.ownsColorTexture && rt.texture.handle !== null) {
|
|
222
|
+
glc.deleteTexture(rt.texture.handle);
|
|
223
|
+
rt.texture.handle = null;
|
|
224
|
+
}
|
|
225
|
+
rt.texture.isReady = false;
|
|
226
|
+
rt.isReady = false;
|
|
227
|
+
};
|
|
228
|
+
rt._restore = (target) => {
|
|
229
|
+
try {
|
|
230
|
+
allocateRenderTargetGpu(target, rt);
|
|
231
|
+
} catch (err) {
|
|
232
|
+
console.error("lite-gl: render target restore failed", err);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
allocateRenderTargetGpu(engine, rt);
|
|
236
|
+
engine._renderTargets.push(rt);
|
|
237
|
+
return rt;
|
|
238
|
+
}
|
|
239
|
+
function resolveColorType(engine, type) {
|
|
240
|
+
const gl = engine.gl;
|
|
241
|
+
if (type === FLOAT && !engine.caps.textureFloatRender) {
|
|
242
|
+
return engine.caps.textureHalfFloatRender ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;
|
|
243
|
+
}
|
|
244
|
+
if (type === HALF_FLOAT && !engine.caps.textureHalfFloatRender) {
|
|
245
|
+
return gl.UNSIGNED_BYTE;
|
|
246
|
+
}
|
|
247
|
+
return type;
|
|
248
|
+
}
|
|
249
|
+
function validateSize(width, height) {
|
|
250
|
+
if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1) {
|
|
251
|
+
throw new Error(`lite-gl: render target size must be positive integers, got ${width}x${height}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function allocateRenderTargetGpu(engine, rt) {
|
|
255
|
+
var _a;
|
|
256
|
+
if (engine._isLost || engine._disposed) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const gl = engine.gl;
|
|
260
|
+
const s = engine._state;
|
|
261
|
+
const c = rt._config;
|
|
262
|
+
const prevFb = s.boundFramebuffer;
|
|
263
|
+
let createdTexture = null;
|
|
264
|
+
let fb = null;
|
|
265
|
+
let rb = null;
|
|
266
|
+
try {
|
|
267
|
+
if (c.ownsColorTexture) {
|
|
268
|
+
const texHandle = gl.createTexture();
|
|
269
|
+
if (texHandle === null) {
|
|
270
|
+
throw new Error("lite-gl: gl.createTexture returned null (render target color)");
|
|
271
|
+
}
|
|
272
|
+
createdTexture = texHandle;
|
|
273
|
+
rt.texture.handle = texHandle;
|
|
274
|
+
bindTextureForUpload(engine, texHandle);
|
|
275
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);
|
|
276
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, c.minFilter);
|
|
277
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, c.magFilter);
|
|
278
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, c.wrapS);
|
|
279
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, c.wrapT);
|
|
280
|
+
rt.texture.isReady = true;
|
|
281
|
+
rt.texture._wasReady = true;
|
|
282
|
+
}
|
|
283
|
+
fb = gl.createFramebuffer();
|
|
284
|
+
if (fb === null) {
|
|
285
|
+
throw new Error("lite-gl: gl.createFramebuffer returned null");
|
|
286
|
+
}
|
|
287
|
+
rt._framebuffer = fb;
|
|
288
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
289
|
+
s.boundFramebuffer = fb;
|
|
290
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rt.texture.handle, 0);
|
|
291
|
+
rt._depthStencil = null;
|
|
292
|
+
if (c.hasDepth) {
|
|
293
|
+
rb = gl.createRenderbuffer();
|
|
294
|
+
if (rb === null) {
|
|
295
|
+
throw new Error("lite-gl: gl.createRenderbuffer returned null");
|
|
296
|
+
}
|
|
297
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
|
298
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rt.width, rt.height);
|
|
299
|
+
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
|
|
300
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
|
301
|
+
rt._depthStencil = rb;
|
|
302
|
+
}
|
|
303
|
+
(_a = rt._rebuildDepthStencil) == null ? void 0 : _a.call(rt, engine);
|
|
304
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
305
|
+
if (status !== gl.FRAMEBUFFER_COMPLETE) {
|
|
306
|
+
throw new Error(`lite-gl: render target framebuffer incomplete (status 0x${status.toString(16)})`);
|
|
307
|
+
}
|
|
308
|
+
rt.isReady = true;
|
|
309
|
+
} catch (e) {
|
|
310
|
+
if (rt._depthStencil !== null) {
|
|
311
|
+
gl.deleteRenderbuffer(rt._depthStencil);
|
|
312
|
+
}
|
|
313
|
+
rt._depthStencil = null;
|
|
314
|
+
if (fb !== null) {
|
|
315
|
+
gl.deleteFramebuffer(fb);
|
|
316
|
+
}
|
|
317
|
+
rt._framebuffer = null;
|
|
318
|
+
if (createdTexture !== null) {
|
|
319
|
+
gl.deleteTexture(createdTexture);
|
|
320
|
+
rt.texture.handle = null;
|
|
321
|
+
rt.texture.isReady = false;
|
|
322
|
+
}
|
|
323
|
+
rt.isReady = false;
|
|
324
|
+
throw e;
|
|
325
|
+
} finally {
|
|
326
|
+
if (s.boundFramebuffer !== prevFb) {
|
|
327
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, prevFb);
|
|
328
|
+
s.boundFramebuffer = prevFb;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function setViewportCached(engine, x, y, w, h) {
|
|
333
|
+
const s = engine._state;
|
|
334
|
+
if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
s.viewportX = x;
|
|
338
|
+
s.viewportY = y;
|
|
339
|
+
s.viewportW = w;
|
|
340
|
+
s.viewportH = h;
|
|
341
|
+
engine.gl.viewport(x, y, w, h);
|
|
342
|
+
}
|
|
343
|
+
export {
|
|
344
|
+
bindRenderTarget,
|
|
345
|
+
createFloatRenderTarget,
|
|
346
|
+
createPingPong,
|
|
347
|
+
createRenderTarget,
|
|
348
|
+
disposePingPong,
|
|
349
|
+
disposeRenderTarget,
|
|
350
|
+
generateRenderTargetMipMaps,
|
|
351
|
+
readRenderTargetPixels,
|
|
352
|
+
resizePingPong,
|
|
353
|
+
resizeRenderTarget
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=render-target.js.map
|