@luma.gl/webgl 9.1.0-alpha.13 → 9.1.0-alpha.15
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/dist/adapter/resources/webgl-framebuffer.d.ts +32 -33
- package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-framebuffer.js +40 -41
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +1 -0
- package/dist/adapter/webgl-device.d.ts +2 -1
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +1 -2
- package/dist/dist.dev.js +1653 -1682
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +1565 -1594
- package/dist/index.cjs.map +4 -4
- package/package.json +4 -4
- package/src/adapter/resources/webgl-framebuffer.ts +43 -43
- package/src/adapter/resources/webgl-texture.ts +2 -0
- package/src/adapter/webgl-device.ts +1 -2
package/dist/dist.dev.js
CHANGED
|
@@ -2142,1877 +2142,1849 @@ var __exports__ = (() => {
|
|
|
2142
2142
|
};
|
|
2143
2143
|
|
|
2144
2144
|
// src/adapter/webgl-canvas-context.ts
|
|
2145
|
-
var
|
|
2145
|
+
var import_core5 = __toESM(require_core(), 1);
|
|
2146
2146
|
|
|
2147
2147
|
// src/adapter/resources/webgl-framebuffer.ts
|
|
2148
|
-
var import_core9 = __toESM(require_core(), 1);
|
|
2149
|
-
|
|
2150
|
-
// src/adapter/resources/webgl-texture.ts
|
|
2151
|
-
var import_core8 = __toESM(require_core(), 1);
|
|
2152
|
-
|
|
2153
|
-
// src/context/state-tracker/with-parameters.ts
|
|
2154
|
-
function withGLParameters(gl, parameters, func) {
|
|
2155
|
-
if (isObjectEmpty2(parameters)) {
|
|
2156
|
-
return func(gl);
|
|
2157
|
-
}
|
|
2158
|
-
const { nocatch = true } = parameters;
|
|
2159
|
-
const webglState = WebGLStateTracker.get(gl);
|
|
2160
|
-
webglState.push();
|
|
2161
|
-
setGLParameters(gl, parameters);
|
|
2162
|
-
let value;
|
|
2163
|
-
if (nocatch) {
|
|
2164
|
-
value = func(gl);
|
|
2165
|
-
webglState.pop();
|
|
2166
|
-
} else {
|
|
2167
|
-
try {
|
|
2168
|
-
value = func(gl);
|
|
2169
|
-
} finally {
|
|
2170
|
-
webglState.pop();
|
|
2171
|
-
}
|
|
2172
|
-
}
|
|
2173
|
-
return value;
|
|
2174
|
-
}
|
|
2175
|
-
function isObjectEmpty2(object) {
|
|
2176
|
-
for (const key in object) {
|
|
2177
|
-
return false;
|
|
2178
|
-
}
|
|
2179
|
-
return true;
|
|
2180
|
-
}
|
|
2181
|
-
|
|
2182
|
-
// src/adapter/converters/device-parameters.ts
|
|
2183
2148
|
var import_core4 = __toESM(require_core(), 1);
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2149
|
+
var WEBGLFramebuffer = class extends import_core4.Framebuffer {
|
|
2150
|
+
device;
|
|
2151
|
+
gl;
|
|
2152
|
+
handle;
|
|
2153
|
+
colorAttachments = [];
|
|
2154
|
+
depthStencilAttachment = null;
|
|
2155
|
+
constructor(device, props) {
|
|
2156
|
+
super(device, props);
|
|
2157
|
+
const isDefaultFramebuffer = props.handle === null;
|
|
2158
|
+
this.device = device;
|
|
2159
|
+
this.gl = device.gl;
|
|
2160
|
+
this.handle = this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
|
|
2161
|
+
if (!isDefaultFramebuffer) {
|
|
2162
|
+
device.setSpectorMetadata(this.handle, { id: this.props.id, props: this.props });
|
|
2163
|
+
this.autoCreateAttachmentTextures();
|
|
2164
|
+
this.updateAttachments();
|
|
2165
|
+
}
|
|
2196
2166
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2167
|
+
/** destroys any auto created resources etc. */
|
|
2168
|
+
destroy() {
|
|
2169
|
+
super.destroy();
|
|
2170
|
+
if (!this.destroyed && this.handle !== null) {
|
|
2171
|
+
this.gl.deleteFramebuffer(this.handle);
|
|
2172
|
+
}
|
|
2201
2173
|
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2174
|
+
updateAttachments() {
|
|
2175
|
+
const prevHandle = this.gl.bindFramebuffer(
|
|
2176
|
+
36160 /* FRAMEBUFFER */,
|
|
2177
|
+
this.handle
|
|
2178
|
+
);
|
|
2179
|
+
for (let i = 0; i < this.colorAttachments.length; ++i) {
|
|
2180
|
+
const attachment = this.colorAttachments[i];
|
|
2181
|
+
if (attachment) {
|
|
2182
|
+
const attachmentPoint = 36064 /* COLOR_ATTACHMENT0 */ + i;
|
|
2183
|
+
this._attachTextureView(attachmentPoint, attachment);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
if (this.depthStencilAttachment) {
|
|
2187
|
+
const attachmentPoint = getDepthStencilAttachmentWebGL(
|
|
2188
|
+
this.depthStencilAttachment.props.format
|
|
2189
|
+
);
|
|
2190
|
+
this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
|
|
2191
|
+
}
|
|
2192
|
+
if (this.props.check !== false) {
|
|
2193
|
+
const status = this.gl.checkFramebufferStatus(36160 /* FRAMEBUFFER */);
|
|
2194
|
+
if (status !== 36053 /* FRAMEBUFFER_COMPLETE */) {
|
|
2195
|
+
throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
this.gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle);
|
|
2209
2199
|
}
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2200
|
+
// PRIVATE
|
|
2201
|
+
/** In WebGL we must use renderbuffers for depth/stencil attachments (unless we have extensions) */
|
|
2202
|
+
// protected override createDepthStencilTexture(format: TextureFormat): Texture {
|
|
2203
|
+
// // return new WEBGLRenderbuffer(this.device, {
|
|
2204
|
+
// return new WEBGLTexture(this.device, {
|
|
2205
|
+
// id: `${this.id}-depth-stencil`,
|
|
2206
|
+
// format,
|
|
2207
|
+
// width: this.width,
|
|
2208
|
+
// height: this.height,
|
|
2209
|
+
// mipmaps: false
|
|
2210
|
+
// });
|
|
2211
|
+
// }
|
|
2212
|
+
/**
|
|
2213
|
+
* @param attachment
|
|
2214
|
+
* @param texture
|
|
2215
|
+
* @param layer = 0 - index into WEBGLTextureArray and Texture3D or face for `TextureCubeMap`
|
|
2216
|
+
* @param level = 0 - mipmapLevel
|
|
2217
|
+
*/
|
|
2218
|
+
_attachTextureView(attachment, textureView) {
|
|
2219
|
+
const { gl } = this.device;
|
|
2220
|
+
const { texture } = textureView;
|
|
2221
|
+
const level = textureView.props.baseMipLevel;
|
|
2222
|
+
const layer = textureView.props.baseArrayLayer;
|
|
2223
|
+
gl.bindTexture(texture.glTarget, texture.handle);
|
|
2224
|
+
switch (texture.glTarget) {
|
|
2225
|
+
case 35866 /* TEXTURE_2D_ARRAY */:
|
|
2226
|
+
case 32879 /* TEXTURE_3D */:
|
|
2227
|
+
gl.framebufferTextureLayer(36160 /* FRAMEBUFFER */, attachment, texture.handle, level, layer);
|
|
2218
2228
|
break;
|
|
2219
|
-
case
|
|
2220
|
-
|
|
2221
|
-
gl.
|
|
2229
|
+
case 34067 /* TEXTURE_CUBE_MAP */:
|
|
2230
|
+
const face = mapIndexToCubeMapFace(layer);
|
|
2231
|
+
gl.framebufferTexture2D(36160 /* FRAMEBUFFER */, attachment, face, texture.handle, level);
|
|
2222
2232
|
break;
|
|
2223
|
-
case
|
|
2224
|
-
gl.
|
|
2225
|
-
gl.cullFace(1029 /* BACK */);
|
|
2233
|
+
case 3553 /* TEXTURE_2D */:
|
|
2234
|
+
gl.framebufferTexture2D(36160 /* FRAMEBUFFER */, attachment, 3553 /* TEXTURE_2D */, texture.handle, level);
|
|
2226
2235
|
break;
|
|
2236
|
+
default:
|
|
2237
|
+
throw new Error("Illegal texture type");
|
|
2227
2238
|
}
|
|
2239
|
+
gl.bindTexture(texture.glTarget, null);
|
|
2228
2240
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2241
|
+
};
|
|
2242
|
+
function mapIndexToCubeMapFace(layer) {
|
|
2243
|
+
return layer < 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ ? layer + 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ : layer;
|
|
2244
|
+
}
|
|
2245
|
+
function _getFrameBufferStatus(status) {
|
|
2246
|
+
switch (status) {
|
|
2247
|
+
case 36053 /* FRAMEBUFFER_COMPLETE */:
|
|
2248
|
+
return "success";
|
|
2249
|
+
case 36054 /* FRAMEBUFFER_INCOMPLETE_ATTACHMENT */:
|
|
2250
|
+
return "Mismatched attachments";
|
|
2251
|
+
case 36055 /* FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */:
|
|
2252
|
+
return "No attachments";
|
|
2253
|
+
case 36057 /* FRAMEBUFFER_INCOMPLETE_DIMENSIONS */:
|
|
2254
|
+
return "Height/width mismatch";
|
|
2255
|
+
case 36061 /* FRAMEBUFFER_UNSUPPORTED */:
|
|
2256
|
+
return "Unsupported or split attachments";
|
|
2257
|
+
case 36182 /* FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */:
|
|
2258
|
+
return "Samples mismatch";
|
|
2259
|
+
default:
|
|
2260
|
+
return `${status}`;
|
|
2236
2261
|
}
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// src/adapter/webgl-canvas-context.ts
|
|
2265
|
+
var WebGLCanvasContext = class extends import_core5.CanvasContext {
|
|
2266
|
+
device;
|
|
2267
|
+
format = "rgba8unorm";
|
|
2268
|
+
depthStencilFormat = "depth24plus";
|
|
2269
|
+
presentationSize;
|
|
2270
|
+
_framebuffer = null;
|
|
2271
|
+
constructor(device, props) {
|
|
2272
|
+
super(props);
|
|
2273
|
+
this.device = device;
|
|
2274
|
+
this.presentationSize = [-1, -1];
|
|
2275
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
2276
|
+
this.update();
|
|
2241
2277
|
}
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2278
|
+
getCurrentFramebuffer() {
|
|
2279
|
+
this.update();
|
|
2280
|
+
this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
|
|
2281
|
+
return this._framebuffer;
|
|
2245
2282
|
}
|
|
2246
|
-
if
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
{
|
|
2254
|
-
first: 36429 /* FIRST_VERTEX_CONVENTION_WEBGL */,
|
|
2255
|
-
last: 36430 /* LAST_VERTEX_CONVENTION_WEBGL */
|
|
2256
|
-
}
|
|
2257
|
-
);
|
|
2258
|
-
ext?.provokingVertexWEBGL(vertex);
|
|
2283
|
+
/** Resizes and updates render targets if necessary */
|
|
2284
|
+
update() {
|
|
2285
|
+
const size = this.getPixelSize();
|
|
2286
|
+
const sizeChanged = size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
|
|
2287
|
+
if (sizeChanged) {
|
|
2288
|
+
this.presentationSize = size;
|
|
2289
|
+
this.resize();
|
|
2259
2290
|
}
|
|
2260
2291
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2292
|
+
/**
|
|
2293
|
+
* Resize the canvas' drawing buffer.
|
|
2294
|
+
*
|
|
2295
|
+
* Can match the canvas CSS size, and optionally also consider devicePixelRatio
|
|
2296
|
+
* Can be called every frame
|
|
2297
|
+
*
|
|
2298
|
+
* Regardless of size, the drawing buffer will always be scaled to the viewport, but
|
|
2299
|
+
* for best visual results, usually set to either:
|
|
2300
|
+
* canvas CSS width x canvas CSS height
|
|
2301
|
+
* canvas CSS width * devicePixelRatio x canvas CSS height * devicePixelRatio
|
|
2302
|
+
* See http://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
|
|
2303
|
+
*/
|
|
2304
|
+
resize(options) {
|
|
2305
|
+
if (!this.device.gl)
|
|
2306
|
+
return;
|
|
2307
|
+
if (this.canvas) {
|
|
2308
|
+
const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
|
|
2309
|
+
this.setDevicePixelRatio(devicePixelRatio, options);
|
|
2310
|
+
return;
|
|
2276
2311
|
}
|
|
2277
2312
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2313
|
+
commit() {
|
|
2314
|
+
}
|
|
2315
|
+
};
|
|
2316
|
+
|
|
2317
|
+
// src/context/debug/spector.ts
|
|
2318
|
+
var import_core6 = __toESM(require_core(), 1);
|
|
2319
|
+
|
|
2320
|
+
// src/utils/load-script.ts
|
|
2321
|
+
async function loadScript(scriptUrl, scriptId) {
|
|
2322
|
+
const head = document.getElementsByTagName("head")[0];
|
|
2323
|
+
if (!head) {
|
|
2324
|
+
throw new Error("loadScript");
|
|
2325
|
+
}
|
|
2326
|
+
const script = document.createElement("script");
|
|
2327
|
+
script.setAttribute("type", "text/javascript");
|
|
2328
|
+
script.setAttribute("src", scriptUrl);
|
|
2329
|
+
if (scriptId) {
|
|
2330
|
+
script.id = scriptId;
|
|
2331
|
+
}
|
|
2332
|
+
return new Promise((resolve, reject) => {
|
|
2333
|
+
script.onload = resolve;
|
|
2334
|
+
script.onerror = (error) => reject(new Error(`Unable to load script '${scriptUrl}': ${error}`));
|
|
2335
|
+
head.appendChild(script);
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// src/context/debug/spector.ts
|
|
2340
|
+
var LOG_LEVEL = 1;
|
|
2341
|
+
var spector = null;
|
|
2342
|
+
var initialized = false;
|
|
2343
|
+
var DEFAULT_SPECTOR_PROPS = {
|
|
2344
|
+
debugWithSpectorJS: import_core6.log.get("spector") || import_core6.log.get("spectorjs"),
|
|
2345
|
+
// https://github.com/BabylonJS/Spector.js#basic-usage
|
|
2346
|
+
// https://forum.babylonjs.com/t/spectorcdn-is-temporarily-off/48241
|
|
2347
|
+
// spectorUrl: 'https://spectorcdn.babylonjs.com/spector.bundle.js';
|
|
2348
|
+
spectorUrl: "https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js",
|
|
2349
|
+
gl: void 0
|
|
2350
|
+
};
|
|
2351
|
+
async function loadSpectorJS(props) {
|
|
2352
|
+
if (!globalThis.SPECTOR) {
|
|
2353
|
+
try {
|
|
2354
|
+
await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
|
|
2355
|
+
} catch (error) {
|
|
2356
|
+
import_core6.log.warn(String(error));
|
|
2299
2357
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
function initializeSpectorJS(props) {
|
|
2361
|
+
props = { ...DEFAULT_SPECTOR_PROPS, ...props };
|
|
2362
|
+
if (!props.debugWithSpectorJS) {
|
|
2363
|
+
return null;
|
|
2364
|
+
}
|
|
2365
|
+
if (!spector && globalThis.SPECTOR && !globalThis.luma?.spector) {
|
|
2366
|
+
import_core6.log.probe(LOG_LEVEL, "SPECTOR found and initialized. Start with `luma.spector.displayUI()`")();
|
|
2367
|
+
const { Spector } = globalThis.SPECTOR;
|
|
2368
|
+
spector = new Spector();
|
|
2369
|
+
if (globalThis.luma) {
|
|
2370
|
+
globalThis.luma.spector = spector;
|
|
2302
2371
|
}
|
|
2303
2372
|
}
|
|
2304
|
-
if (
|
|
2305
|
-
|
|
2373
|
+
if (!spector) {
|
|
2374
|
+
return null;
|
|
2306
2375
|
}
|
|
2307
|
-
if (
|
|
2308
|
-
|
|
2309
|
-
|
|
2376
|
+
if (!initialized) {
|
|
2377
|
+
initialized = true;
|
|
2378
|
+
spector.spyCanvases();
|
|
2379
|
+
spector?.onCaptureStarted.add(
|
|
2380
|
+
(capture) => import_core6.log.info("Spector capture started:", capture)()
|
|
2381
|
+
);
|
|
2382
|
+
spector?.onCapture.add((capture) => {
|
|
2383
|
+
import_core6.log.info("Spector capture complete:", capture)();
|
|
2384
|
+
spector?.getResultUI();
|
|
2385
|
+
spector?.resultView.display();
|
|
2386
|
+
spector?.resultView.addCapture(capture);
|
|
2387
|
+
});
|
|
2310
2388
|
}
|
|
2311
|
-
if (
|
|
2312
|
-
const
|
|
2313
|
-
|
|
2314
|
-
gl
|
|
2389
|
+
if (props.gl) {
|
|
2390
|
+
const gl = props.gl;
|
|
2391
|
+
const device = gl.device;
|
|
2392
|
+
spector?.startCapture(props.gl, 500);
|
|
2393
|
+
gl.device = device;
|
|
2394
|
+
new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
|
|
2395
|
+
import_core6.log.info("Spector capture stopped after 2 seconds")();
|
|
2396
|
+
spector?.stopCapture();
|
|
2397
|
+
});
|
|
2315
2398
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2399
|
+
return spector;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
// src/context/debug/webgl-developer-tools.ts
|
|
2403
|
+
var import_core7 = __toESM(require_core(), 1);
|
|
2404
|
+
|
|
2405
|
+
// ../../node_modules/@probe.gl/env/dist/lib/globals.js
|
|
2406
|
+
var document_ = globalThis.document || {};
|
|
2407
|
+
var process_ = globalThis.process || {};
|
|
2408
|
+
var console_ = globalThis.console;
|
|
2409
|
+
var navigator_ = globalThis.navigator || {};
|
|
2410
|
+
|
|
2411
|
+
// ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
|
|
2412
|
+
function isElectron(mockUserAgent) {
|
|
2413
|
+
if (typeof window !== "undefined" && window.process?.type === "renderer") {
|
|
2414
|
+
return true;
|
|
2318
2415
|
}
|
|
2319
|
-
if (
|
|
2320
|
-
|
|
2321
|
-
const glValue = convertCompareFunction("depthCompare", parameters.stencilCompare);
|
|
2322
|
-
parameters.stencilCompare !== "always" ? gl.enable(2960 /* STENCIL_TEST */) : gl.disable(2960 /* STENCIL_TEST */);
|
|
2323
|
-
gl.stencilFuncSeparate(1028 /* FRONT */, glValue, 0, mask);
|
|
2324
|
-
gl.stencilFuncSeparate(1029 /* BACK */, glValue, 0, mask);
|
|
2416
|
+
if (typeof process !== "undefined" && Boolean(process.versions?.["electron"])) {
|
|
2417
|
+
return true;
|
|
2325
2418
|
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2419
|
+
const realUserAgent = typeof navigator !== "undefined" && navigator.userAgent;
|
|
2420
|
+
const userAgent = mockUserAgent || realUserAgent;
|
|
2421
|
+
return Boolean(userAgent && userAgent.indexOf("Electron") >= 0);
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
// ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
|
|
2425
|
+
function isBrowser() {
|
|
2426
|
+
const isNode = (
|
|
2427
|
+
// @ts-expect-error
|
|
2428
|
+
typeof process === "object" && String(process) === "[object process]" && !process?.browser
|
|
2429
|
+
);
|
|
2430
|
+
return !isNode || isElectron();
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
// ../../node_modules/@probe.gl/env/dist/lib/get-browser.js
|
|
2434
|
+
function getBrowser(mockUserAgent) {
|
|
2435
|
+
if (!mockUserAgent && !isBrowser()) {
|
|
2436
|
+
return "Node";
|
|
2335
2437
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
gl.enable(3042 /* BLEND */);
|
|
2339
|
-
break;
|
|
2340
|
-
case false:
|
|
2341
|
-
gl.disable(3042 /* BLEND */);
|
|
2342
|
-
break;
|
|
2343
|
-
default:
|
|
2438
|
+
if (isElectron(mockUserAgent)) {
|
|
2439
|
+
return "Electron";
|
|
2344
2440
|
}
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
parameters.blendColorSrcFactor || "one"
|
|
2358
|
-
);
|
|
2359
|
-
const colorDstFactor = convertBlendFactorToFunction(
|
|
2360
|
-
"blendColorDstFactor",
|
|
2361
|
-
parameters.blendColorDstFactor || "zero"
|
|
2362
|
-
);
|
|
2363
|
-
const alphaSrcFactor = convertBlendFactorToFunction(
|
|
2364
|
-
"blendAlphaSrcFactor",
|
|
2365
|
-
parameters.blendAlphaSrcFactor || "one"
|
|
2366
|
-
);
|
|
2367
|
-
const alphaDstFactor = convertBlendFactorToFunction(
|
|
2368
|
-
"blendAlphaDstFactor",
|
|
2369
|
-
parameters.blendAlphaDstFactor || "zero"
|
|
2370
|
-
);
|
|
2371
|
-
gl.blendFuncSeparate(colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor);
|
|
2441
|
+
const userAgent = mockUserAgent || navigator_.userAgent || "";
|
|
2442
|
+
if (userAgent.indexOf("Edge") > -1) {
|
|
2443
|
+
return "Edge";
|
|
2444
|
+
}
|
|
2445
|
+
if (globalThis.chrome) {
|
|
2446
|
+
return "Chrome";
|
|
2447
|
+
}
|
|
2448
|
+
if (globalThis.safari) {
|
|
2449
|
+
return "Safari";
|
|
2450
|
+
}
|
|
2451
|
+
if (globalThis.mozInnerScreenX) {
|
|
2452
|
+
return "Firefox";
|
|
2372
2453
|
}
|
|
2454
|
+
return "Unknown";
|
|
2373
2455
|
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
greater: 516 /* GREATER */,
|
|
2381
|
-
"not-equal": 517 /* NOTEQUAL */,
|
|
2382
|
-
"greater-equal": 518 /* GEQUAL */,
|
|
2383
|
-
always: 519 /* ALWAYS */
|
|
2384
|
-
});
|
|
2456
|
+
|
|
2457
|
+
// src/context/debug/webgl-developer-tools.ts
|
|
2458
|
+
var WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
|
|
2459
|
+
function getWebGLContextData(gl) {
|
|
2460
|
+
gl.luma = gl.luma || {};
|
|
2461
|
+
return gl.luma;
|
|
2385
2462
|
}
|
|
2386
|
-
function
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
"increment-clamp": 7682 /* INCR */,
|
|
2393
|
-
"decrement-clamp": 7683 /* DECR */,
|
|
2394
|
-
"increment-wrap": 34055 /* INCR_WRAP */,
|
|
2395
|
-
"decrement-wrap": 34056 /* DECR_WRAP */
|
|
2396
|
-
});
|
|
2463
|
+
async function loadWebGLDeveloperTools() {
|
|
2464
|
+
if (isBrowser() && !globalThis.WebGLDebugUtils) {
|
|
2465
|
+
globalThis.global = globalThis.global || globalThis;
|
|
2466
|
+
globalThis.global.module = {};
|
|
2467
|
+
await loadScript(WEBGL_DEBUG_CDN_URL);
|
|
2468
|
+
}
|
|
2397
2469
|
}
|
|
2398
|
-
function
|
|
2399
|
-
return
|
|
2400
|
-
add: 32774 /* FUNC_ADD */,
|
|
2401
|
-
subtract: 32778 /* FUNC_SUBTRACT */,
|
|
2402
|
-
"reverse-subtract": 32779 /* FUNC_REVERSE_SUBTRACT */,
|
|
2403
|
-
min: 32775 /* MIN */,
|
|
2404
|
-
max: 32776 /* MAX */
|
|
2405
|
-
});
|
|
2470
|
+
function makeDebugContext(gl, props = {}) {
|
|
2471
|
+
return props.debug ? getDebugContext(gl, props) : getRealContext(gl);
|
|
2406
2472
|
}
|
|
2407
|
-
function
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
zero: 0 /* ZERO */,
|
|
2411
|
-
"src-color": 768 /* SRC_COLOR */,
|
|
2412
|
-
"one-minus-src-color": 769 /* ONE_MINUS_SRC_COLOR */,
|
|
2413
|
-
"dst-color": 774 /* DST_COLOR */,
|
|
2414
|
-
"one-minus-dst-color": 775 /* ONE_MINUS_DST_COLOR */,
|
|
2415
|
-
"src-alpha": 770 /* SRC_ALPHA */,
|
|
2416
|
-
"one-minus-src-alpha": 771 /* ONE_MINUS_SRC_ALPHA */,
|
|
2417
|
-
"dst-alpha": 772 /* DST_ALPHA */,
|
|
2418
|
-
"one-minus-dst-alpha": 773 /* ONE_MINUS_DST_ALPHA */,
|
|
2419
|
-
"src-alpha-saturated": 776 /* SRC_ALPHA_SATURATE */,
|
|
2420
|
-
"constant-color": 32769 /* CONSTANT_COLOR */,
|
|
2421
|
-
"one-minus-constant-color": 32770 /* ONE_MINUS_CONSTANT_COLOR */,
|
|
2422
|
-
"constant-alpha": 32771 /* CONSTANT_ALPHA */,
|
|
2423
|
-
"one-minus-constant-alpha": 32772 /* ONE_MINUS_CONSTANT_ALPHA */
|
|
2424
|
-
});
|
|
2425
|
-
}
|
|
2426
|
-
function message(parameter, value) {
|
|
2427
|
-
return `Illegal parameter ${value} for ${parameter}`;
|
|
2428
|
-
}
|
|
2429
|
-
function map(parameter, value, valueMap) {
|
|
2430
|
-
if (!(value in valueMap)) {
|
|
2431
|
-
throw new Error(message(parameter, value));
|
|
2432
|
-
}
|
|
2433
|
-
return valueMap[value];
|
|
2434
|
-
}
|
|
2435
|
-
function mapBoolean(parameter, value) {
|
|
2436
|
-
return value;
|
|
2437
|
-
}
|
|
2438
|
-
function isObjectEmpty3(obj) {
|
|
2439
|
-
let isEmpty = true;
|
|
2440
|
-
for (const key in obj) {
|
|
2441
|
-
isEmpty = false;
|
|
2442
|
-
break;
|
|
2443
|
-
}
|
|
2444
|
-
return isEmpty;
|
|
2473
|
+
function getRealContext(gl) {
|
|
2474
|
+
const data = getWebGLContextData(gl);
|
|
2475
|
+
return data.realContext ? data.realContext : gl;
|
|
2445
2476
|
}
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
if (props.addressModeU) {
|
|
2451
|
-
params[10242 /* TEXTURE_WRAP_S */] = convertAddressMode(props.addressModeU);
|
|
2452
|
-
}
|
|
2453
|
-
if (props.addressModeV) {
|
|
2454
|
-
params[10243 /* TEXTURE_WRAP_T */] = convertAddressMode(props.addressModeV);
|
|
2455
|
-
}
|
|
2456
|
-
if (props.addressModeW) {
|
|
2457
|
-
params[32882 /* TEXTURE_WRAP_R */] = convertAddressMode(props.addressModeW);
|
|
2458
|
-
}
|
|
2459
|
-
if (props.magFilter) {
|
|
2460
|
-
params[10240 /* TEXTURE_MAG_FILTER */] = convertMaxFilterMode(props.magFilter);
|
|
2461
|
-
}
|
|
2462
|
-
if (props.minFilter || props.mipmapFilter) {
|
|
2463
|
-
params[10241 /* TEXTURE_MIN_FILTER */] = convertMinFilterMode(
|
|
2464
|
-
props.minFilter || "linear",
|
|
2465
|
-
props.mipmapFilter
|
|
2466
|
-
);
|
|
2467
|
-
}
|
|
2468
|
-
if (props.lodMinClamp !== void 0) {
|
|
2469
|
-
params[33082 /* TEXTURE_MIN_LOD */] = props.lodMinClamp;
|
|
2470
|
-
}
|
|
2471
|
-
if (props.lodMaxClamp !== void 0) {
|
|
2472
|
-
params[33083 /* TEXTURE_MAX_LOD */] = props.lodMaxClamp;
|
|
2477
|
+
function getDebugContext(gl, props) {
|
|
2478
|
+
if (!globalThis.WebGLDebugUtils) {
|
|
2479
|
+
import_core7.log.warn("webgl-debug not loaded")();
|
|
2480
|
+
return gl;
|
|
2473
2481
|
}
|
|
2474
|
-
|
|
2475
|
-
|
|
2482
|
+
const data = getWebGLContextData(gl);
|
|
2483
|
+
if (data.debugContext) {
|
|
2484
|
+
return data.debugContext;
|
|
2476
2485
|
}
|
|
2477
|
-
|
|
2478
|
-
|
|
2486
|
+
globalThis.WebGLDebugUtils.init({ ...GLEnum, ...gl });
|
|
2487
|
+
const glDebug = globalThis.WebGLDebugUtils.makeDebugContext(
|
|
2488
|
+
gl,
|
|
2489
|
+
onGLError.bind(null, props),
|
|
2490
|
+
onValidateGLFunc.bind(null, props)
|
|
2491
|
+
);
|
|
2492
|
+
for (const key in GLEnum) {
|
|
2493
|
+
if (!(key in glDebug) && typeof GLEnum[key] === "number") {
|
|
2494
|
+
glDebug[key] = GLEnum[key];
|
|
2495
|
+
}
|
|
2479
2496
|
}
|
|
2480
|
-
|
|
2481
|
-
params[34046 /* TEXTURE_MAX_ANISOTROPY_EXT */] = props.maxAnisotropy;
|
|
2497
|
+
class WebGLDebugContext {
|
|
2482
2498
|
}
|
|
2483
|
-
|
|
2499
|
+
Object.setPrototypeOf(glDebug, Object.getPrototypeOf(gl));
|
|
2500
|
+
Object.setPrototypeOf(WebGLDebugContext, glDebug);
|
|
2501
|
+
const debugContext = Object.create(WebGLDebugContext);
|
|
2502
|
+
data.realContext = gl;
|
|
2503
|
+
data.debugContext = debugContext;
|
|
2504
|
+
debugContext.debug = true;
|
|
2505
|
+
return debugContext;
|
|
2484
2506
|
}
|
|
2485
|
-
function
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
return 10497 /* REPEAT */;
|
|
2491
|
-
case "mirror-repeat":
|
|
2492
|
-
return 33648 /* MIRRORED_REPEAT */;
|
|
2493
|
-
}
|
|
2507
|
+
function getFunctionString(functionName, functionArgs) {
|
|
2508
|
+
functionArgs = Array.from(functionArgs).map((arg) => arg === void 0 ? "undefined" : arg);
|
|
2509
|
+
let args = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, functionArgs);
|
|
2510
|
+
args = `${args.slice(0, 100)}${args.length > 100 ? "..." : ""}`;
|
|
2511
|
+
return `gl.${functionName}(${args})`;
|
|
2494
2512
|
}
|
|
2495
|
-
function
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2513
|
+
function onGLError(props, err, functionName, args) {
|
|
2514
|
+
args = Array.from(args).map((arg) => arg === void 0 ? "undefined" : arg);
|
|
2515
|
+
const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
|
|
2516
|
+
const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
|
|
2517
|
+
const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
|
|
2518
|
+
import_core7.log.error(message2)();
|
|
2519
|
+
debugger;
|
|
2520
|
+
if (props.throwOnError) {
|
|
2521
|
+
throw new Error(message2);
|
|
2501
2522
|
}
|
|
2502
2523
|
}
|
|
2503
|
-
function
|
|
2504
|
-
|
|
2505
|
-
|
|
2524
|
+
function onValidateGLFunc(props, functionName, functionArgs) {
|
|
2525
|
+
let functionString = "";
|
|
2526
|
+
if (import_core7.log.level >= 1) {
|
|
2527
|
+
functionString = getFunctionString(functionName, functionArgs);
|
|
2528
|
+
import_core7.log.log(1, functionString)();
|
|
2506
2529
|
}
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2530
|
+
if (props.break && props.break.length > 0) {
|
|
2531
|
+
functionString = functionString || getFunctionString(functionName, functionArgs);
|
|
2532
|
+
const isBreakpoint = props.break.every(
|
|
2533
|
+
(breakOn) => functionString.indexOf(breakOn) !== -1
|
|
2534
|
+
);
|
|
2535
|
+
if (isBreakpoint) {
|
|
2536
|
+
debugger;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
for (const arg of functionArgs) {
|
|
2540
|
+
if (arg === void 0) {
|
|
2541
|
+
functionString = functionString || getFunctionString(functionName, functionArgs);
|
|
2542
|
+
if (props.throwOnError) {
|
|
2543
|
+
throw new Error(`Undefined argument: ${functionString}`);
|
|
2544
|
+
} else {
|
|
2545
|
+
import_core7.log.error(`Undefined argument: ${functionString}`)();
|
|
2546
|
+
debugger;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2512
2549
|
}
|
|
2513
2550
|
}
|
|
2514
2551
|
|
|
2515
|
-
// src/
|
|
2516
|
-
var
|
|
2517
|
-
|
|
2552
|
+
// src/utils/uid.ts
|
|
2553
|
+
var uidCounters = {};
|
|
2554
|
+
function uid(id = "id") {
|
|
2555
|
+
uidCounters[id] = uidCounters[id] || 1;
|
|
2556
|
+
const count = uidCounters[id]++;
|
|
2557
|
+
return `${id}-${count}`;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
// src/adapter/resources/webgl-buffer.ts
|
|
2561
|
+
var import_core8 = __toESM(require_core(), 1);
|
|
2562
|
+
var WEBGLBuffer = class extends import_core8.Buffer {
|
|
2518
2563
|
device;
|
|
2564
|
+
gl;
|
|
2519
2565
|
handle;
|
|
2520
|
-
|
|
2521
|
-
|
|
2566
|
+
/** Target in OpenGL defines the type of buffer */
|
|
2567
|
+
glTarget;
|
|
2568
|
+
/** Usage is a hint on how frequently the buffer will be updates */
|
|
2569
|
+
glUsage;
|
|
2570
|
+
/** Index type is needed when issuing draw calls, so we pre-compute it */
|
|
2571
|
+
glIndexType = 5123 /* UNSIGNED_SHORT */;
|
|
2572
|
+
/** Number of bytes allocated on the GPU for this buffer */
|
|
2573
|
+
byteLength;
|
|
2574
|
+
/** Number of bytes used */
|
|
2575
|
+
bytesUsed;
|
|
2576
|
+
constructor(device, props = {}) {
|
|
2522
2577
|
super(device, props);
|
|
2523
2578
|
this.device = device;
|
|
2524
|
-
this.
|
|
2525
|
-
|
|
2526
|
-
this.
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2579
|
+
this.gl = this.device.gl;
|
|
2580
|
+
const handle = typeof props === "object" ? props.handle : void 0;
|
|
2581
|
+
this.handle = handle || this.gl.createBuffer();
|
|
2582
|
+
device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
|
|
2583
|
+
this.glTarget = getWebGLTarget(this.props.usage);
|
|
2584
|
+
this.glUsage = getWebGLUsage(this.props.usage);
|
|
2585
|
+
this.glIndexType = this.props.indexType === "uint32" ? 5125 /* UNSIGNED_INT */ : 5123 /* UNSIGNED_SHORT */;
|
|
2586
|
+
if (props.data) {
|
|
2587
|
+
this._initWithData(props.data, props.byteOffset, props.byteLength);
|
|
2588
|
+
} else {
|
|
2589
|
+
this._initWithByteLength(props.byteLength || 0);
|
|
2532
2590
|
}
|
|
2533
2591
|
}
|
|
2534
|
-
|
|
2535
|
-
|
|
2592
|
+
// PRIVATE METHODS
|
|
2593
|
+
/** Allocate a new buffer and initialize to contents of typed array */
|
|
2594
|
+
_initWithData(data, byteOffset = 0, byteLength = data.byteLength + byteOffset) {
|
|
2595
|
+
const glTarget = this.glTarget;
|
|
2596
|
+
this.gl.bindBuffer(glTarget, this.handle);
|
|
2597
|
+
this.gl.bufferData(glTarget, byteLength, this.glUsage);
|
|
2598
|
+
this.gl.bufferSubData(glTarget, byteOffset, data);
|
|
2599
|
+
this.gl.bindBuffer(glTarget, null);
|
|
2600
|
+
this.bytesUsed = byteLength;
|
|
2601
|
+
this.byteLength = byteLength;
|
|
2602
|
+
this._setDebugData(data, byteOffset, byteLength);
|
|
2603
|
+
this.trackAllocatedMemory(byteLength);
|
|
2536
2604
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
case 33082 /* TEXTURE_MIN_LOD */:
|
|
2543
|
-
case 33083 /* TEXTURE_MAX_LOD */:
|
|
2544
|
-
this.device.gl.samplerParameterf(this.handle, param, value);
|
|
2545
|
-
break;
|
|
2546
|
-
default:
|
|
2547
|
-
this.device.gl.samplerParameteri(this.handle, param, value);
|
|
2548
|
-
break;
|
|
2549
|
-
}
|
|
2605
|
+
// Allocate a GPU buffer of specified size.
|
|
2606
|
+
_initWithByteLength(byteLength) {
|
|
2607
|
+
let data = byteLength;
|
|
2608
|
+
if (byteLength === 0) {
|
|
2609
|
+
data = new Float32Array(0);
|
|
2550
2610
|
}
|
|
2611
|
+
const glTarget = this.glTarget;
|
|
2612
|
+
this.gl.bindBuffer(glTarget, this.handle);
|
|
2613
|
+
this.gl.bufferData(glTarget, data, this.glUsage);
|
|
2614
|
+
this.gl.bindBuffer(glTarget, null);
|
|
2615
|
+
this.bytesUsed = byteLength;
|
|
2616
|
+
this.byteLength = byteLength;
|
|
2617
|
+
this._setDebugData(null, 0, byteLength);
|
|
2618
|
+
this.trackAllocatedMemory(byteLength);
|
|
2619
|
+
return this;
|
|
2551
2620
|
}
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
this.gl
|
|
2566
|
-
|
|
2567
|
-
|
|
2621
|
+
destroy() {
|
|
2622
|
+
if (!this.destroyed && this.handle) {
|
|
2623
|
+
this.removeStats();
|
|
2624
|
+
this.trackDeallocatedMemory();
|
|
2625
|
+
this.gl.deleteBuffer(this.handle);
|
|
2626
|
+
this.destroyed = true;
|
|
2627
|
+
this.handle = null;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
write(data, byteOffset = 0) {
|
|
2631
|
+
const srcOffset = 0;
|
|
2632
|
+
const byteLength = void 0;
|
|
2633
|
+
const glTarget = 36663 /* COPY_WRITE_BUFFER */;
|
|
2634
|
+
this.gl.bindBuffer(glTarget, this.handle);
|
|
2635
|
+
if (srcOffset !== 0 || byteLength !== void 0) {
|
|
2636
|
+
this.gl.bufferSubData(glTarget, byteOffset, data, srcOffset, byteLength);
|
|
2637
|
+
} else {
|
|
2638
|
+
this.gl.bufferSubData(glTarget, byteOffset, data);
|
|
2639
|
+
}
|
|
2640
|
+
this.gl.bindBuffer(glTarget, null);
|
|
2641
|
+
this._setDebugData(data, byteOffset, data.byteLength);
|
|
2642
|
+
}
|
|
2643
|
+
/** Asynchronously read data from the buffer */
|
|
2644
|
+
async readAsync(byteOffset = 0, byteLength) {
|
|
2645
|
+
return this.readSyncWebGL(byteOffset, byteLength);
|
|
2646
|
+
}
|
|
2647
|
+
/** Synchronously read data from the buffer. WebGL only. */
|
|
2648
|
+
readSyncWebGL(byteOffset = 0, byteLength) {
|
|
2649
|
+
byteLength = byteLength ?? this.byteLength - byteOffset;
|
|
2650
|
+
const data = new Uint8Array(byteLength);
|
|
2651
|
+
const dstOffset = 0;
|
|
2652
|
+
this.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, this.handle);
|
|
2653
|
+
this.gl.getBufferSubData(36662 /* COPY_READ_BUFFER */, byteOffset, data, dstOffset, byteLength);
|
|
2654
|
+
this.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, null);
|
|
2655
|
+
this._setDebugData(data, byteOffset, byteLength);
|
|
2656
|
+
return data;
|
|
2568
2657
|
}
|
|
2569
2658
|
};
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
case Float32Array:
|
|
2580
|
-
return 5126 /* FLOAT */;
|
|
2581
|
-
case Uint16Array:
|
|
2582
|
-
return 5123 /* UNSIGNED_SHORT */;
|
|
2583
|
-
case Uint32Array:
|
|
2584
|
-
return 5125 /* UNSIGNED_INT */;
|
|
2585
|
-
case Uint8Array:
|
|
2586
|
-
return 5121 /* UNSIGNED_BYTE */;
|
|
2587
|
-
case Uint8ClampedArray:
|
|
2588
|
-
return 5121 /* UNSIGNED_BYTE */;
|
|
2589
|
-
case Int8Array:
|
|
2590
|
-
return 5120 /* BYTE */;
|
|
2591
|
-
case Int16Array:
|
|
2592
|
-
return 5122 /* SHORT */;
|
|
2593
|
-
case Int32Array:
|
|
2594
|
-
return 5124 /* INT */;
|
|
2595
|
-
default:
|
|
2596
|
-
throw new Error(ERR_TYPE_DEDUCTION);
|
|
2659
|
+
function getWebGLTarget(usage) {
|
|
2660
|
+
if (usage & import_core8.Buffer.INDEX) {
|
|
2661
|
+
return 34963 /* ELEMENT_ARRAY_BUFFER */;
|
|
2662
|
+
}
|
|
2663
|
+
if (usage & import_core8.Buffer.VERTEX) {
|
|
2664
|
+
return 34962 /* ARRAY_BUFFER */;
|
|
2665
|
+
}
|
|
2666
|
+
if (usage & import_core8.Buffer.UNIFORM) {
|
|
2667
|
+
return 35345 /* UNIFORM_BUFFER */;
|
|
2597
2668
|
}
|
|
2669
|
+
return 34962 /* ARRAY_BUFFER */;
|
|
2598
2670
|
}
|
|
2599
|
-
function
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
case 33635 /* UNSIGNED_SHORT_5_6_5 */:
|
|
2606
|
-
case 32819 /* UNSIGNED_SHORT_4_4_4_4 */:
|
|
2607
|
-
case 32820 /* UNSIGNED_SHORT_5_5_5_1 */:
|
|
2608
|
-
return Uint16Array;
|
|
2609
|
-
case 5125 /* UNSIGNED_INT */:
|
|
2610
|
-
return Uint32Array;
|
|
2611
|
-
case 5121 /* UNSIGNED_BYTE */:
|
|
2612
|
-
return clamped ? Uint8ClampedArray : Uint8Array;
|
|
2613
|
-
case 5120 /* BYTE */:
|
|
2614
|
-
return Int8Array;
|
|
2615
|
-
case 5122 /* SHORT */:
|
|
2616
|
-
return Int16Array;
|
|
2617
|
-
case 5124 /* INT */:
|
|
2618
|
-
return Int32Array;
|
|
2619
|
-
default:
|
|
2620
|
-
throw new Error("Failed to deduce typed array type from GL constant");
|
|
2671
|
+
function getWebGLUsage(usage) {
|
|
2672
|
+
if (usage & import_core8.Buffer.INDEX) {
|
|
2673
|
+
return 35044 /* STATIC_DRAW */;
|
|
2674
|
+
}
|
|
2675
|
+
if (usage & import_core8.Buffer.VERTEX) {
|
|
2676
|
+
return 35044 /* STATIC_DRAW */;
|
|
2621
2677
|
}
|
|
2678
|
+
if (usage & import_core8.Buffer.UNIFORM) {
|
|
2679
|
+
return 35048 /* DYNAMIC_DRAW */;
|
|
2680
|
+
}
|
|
2681
|
+
return 35044 /* STATIC_DRAW */;
|
|
2622
2682
|
}
|
|
2623
2683
|
|
|
2624
|
-
// src/adapter/
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2684
|
+
// src/adapter/resources/webgl-shader.ts
|
|
2685
|
+
var import_core9 = __toESM(require_core(), 1);
|
|
2686
|
+
|
|
2687
|
+
// src/adapter/helpers/parse-shader-compiler-log.ts
|
|
2688
|
+
function parseShaderCompilerLog(errLog) {
|
|
2689
|
+
const lines = errLog.split(/\r?\n/);
|
|
2690
|
+
const messages = [];
|
|
2691
|
+
for (const line of lines) {
|
|
2692
|
+
if (line.length <= 1) {
|
|
2693
|
+
continue;
|
|
2694
|
+
}
|
|
2695
|
+
const segments = line.split(":");
|
|
2696
|
+
if (segments.length === 2) {
|
|
2697
|
+
const [messageType2, message2] = segments;
|
|
2698
|
+
messages.push({
|
|
2699
|
+
message: message2.trim(),
|
|
2700
|
+
type: getMessageType(messageType2),
|
|
2701
|
+
lineNum: 0,
|
|
2702
|
+
linePos: 0
|
|
2703
|
+
});
|
|
2704
|
+
continue;
|
|
2705
|
+
}
|
|
2706
|
+
const [messageType, linePosition, lineNumber, ...rest] = segments;
|
|
2707
|
+
let lineNum = parseInt(lineNumber, 10);
|
|
2708
|
+
if (isNaN(lineNum)) {
|
|
2709
|
+
lineNum = 0;
|
|
2710
|
+
}
|
|
2711
|
+
let linePos = parseInt(linePosition, 10);
|
|
2712
|
+
if (isNaN(linePos)) {
|
|
2713
|
+
linePos = 0;
|
|
2714
|
+
}
|
|
2715
|
+
messages.push({
|
|
2716
|
+
message: rest.join(":").trim(),
|
|
2717
|
+
type: getMessageType(messageType),
|
|
2718
|
+
lineNum,
|
|
2719
|
+
linePos
|
|
2720
|
+
// TODO
|
|
2721
|
+
});
|
|
2642
2722
|
}
|
|
2723
|
+
return messages;
|
|
2643
2724
|
}
|
|
2644
|
-
function
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
case 33635 /* UNSIGNED_SHORT_5_6_5 */:
|
|
2649
|
-
case 32819 /* UNSIGNED_SHORT_4_4_4_4 */:
|
|
2650
|
-
case 32820 /* UNSIGNED_SHORT_5_5_5_1 */:
|
|
2651
|
-
return 2;
|
|
2652
|
-
case 5126 /* FLOAT */:
|
|
2653
|
-
return 4;
|
|
2654
|
-
default:
|
|
2655
|
-
return 0;
|
|
2656
|
-
}
|
|
2725
|
+
function getMessageType(messageType) {
|
|
2726
|
+
const MESSAGE_TYPES = ["warning", "error", "info"];
|
|
2727
|
+
const lowerCaseType = messageType.toLowerCase();
|
|
2728
|
+
return MESSAGE_TYPES.includes(lowerCaseType) ? lowerCaseType : "info";
|
|
2657
2729
|
}
|
|
2658
2730
|
|
|
2659
|
-
// src/adapter/
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2731
|
+
// src/adapter/resources/webgl-shader.ts
|
|
2732
|
+
var WEBGLShader = class extends import_core9.Shader {
|
|
2733
|
+
device;
|
|
2734
|
+
handle;
|
|
2735
|
+
constructor(device, props) {
|
|
2736
|
+
super(device, props);
|
|
2737
|
+
this.device = device;
|
|
2738
|
+
switch (this.props.stage) {
|
|
2739
|
+
case "vertex":
|
|
2740
|
+
this.handle = this.props.handle || this.device.gl.createShader(35633 /* VERTEX_SHADER */);
|
|
2741
|
+
break;
|
|
2742
|
+
case "fragment":
|
|
2743
|
+
this.handle = this.props.handle || this.device.gl.createShader(35632 /* FRAGMENT_SHADER */);
|
|
2744
|
+
break;
|
|
2745
|
+
default:
|
|
2746
|
+
throw new Error(this.props.stage);
|
|
2747
|
+
}
|
|
2748
|
+
this._compile(this.source);
|
|
2671
2749
|
}
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
2679
|
-
switch (dimension) {
|
|
2680
|
-
case "2d-array":
|
|
2681
|
-
case "3d":
|
|
2682
|
-
gl.bindTexture(glTarget, handle);
|
|
2683
|
-
gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
|
|
2684
|
-
gl.bindTexture(glTarget, null);
|
|
2685
|
-
break;
|
|
2686
|
-
case "2d":
|
|
2687
|
-
case "cube":
|
|
2688
|
-
gl.bindTexture(glTarget, handle);
|
|
2689
|
-
gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
|
|
2690
|
-
gl.bindTexture(glTarget, null);
|
|
2691
|
-
break;
|
|
2692
|
-
default:
|
|
2693
|
-
throw new Error(dimension);
|
|
2750
|
+
destroy() {
|
|
2751
|
+
if (this.handle) {
|
|
2752
|
+
this.removeStats();
|
|
2753
|
+
this.device.gl.deleteShader(this.handle);
|
|
2754
|
+
this.destroyed = true;
|
|
2755
|
+
}
|
|
2694
2756
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
const { x = 0, y = 0, z = 0 } = options;
|
|
2699
|
-
const { glFormat, glType, compressed } = options;
|
|
2700
|
-
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
2701
|
-
switch (dimension) {
|
|
2702
|
-
case "2d-array":
|
|
2703
|
-
case "3d":
|
|
2704
|
-
if (compressed) {
|
|
2705
|
-
gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
|
|
2706
|
-
} else {
|
|
2707
|
-
gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
|
|
2708
|
-
}
|
|
2709
|
-
break;
|
|
2710
|
-
case "2d":
|
|
2711
|
-
case "cube":
|
|
2712
|
-
if (compressed) {
|
|
2713
|
-
gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
|
|
2714
|
-
} else {
|
|
2715
|
-
gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
|
|
2716
|
-
}
|
|
2717
|
-
break;
|
|
2718
|
-
default:
|
|
2719
|
-
throw new Error(dimension);
|
|
2757
|
+
async getCompilationInfo() {
|
|
2758
|
+
await this._waitForCompilationComplete();
|
|
2759
|
+
return this.getCompilationInfoSync();
|
|
2720
2760
|
}
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
case "1d":
|
|
2725
|
-
break;
|
|
2726
|
-
case "2d":
|
|
2727
|
-
return 3553 /* TEXTURE_2D */;
|
|
2728
|
-
case "3d":
|
|
2729
|
-
return 32879 /* TEXTURE_3D */;
|
|
2730
|
-
case "cube":
|
|
2731
|
-
return 34067 /* TEXTURE_CUBE_MAP */;
|
|
2732
|
-
case "2d-array":
|
|
2733
|
-
return 35866 /* TEXTURE_2D_ARRAY */;
|
|
2734
|
-
case "cube-array":
|
|
2735
|
-
break;
|
|
2736
|
-
}
|
|
2737
|
-
throw new Error(dimension);
|
|
2738
|
-
}
|
|
2739
|
-
function getWebGLCubeFaceTarget(glTarget, dimension, level) {
|
|
2740
|
-
return dimension === "cube" ? 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ + level : glTarget;
|
|
2741
|
-
}
|
|
2742
|
-
function readPixelsToArray(source, options) {
|
|
2743
|
-
const {
|
|
2744
|
-
sourceX = 0,
|
|
2745
|
-
sourceY = 0,
|
|
2746
|
-
sourceAttachment = 36064 /* COLOR_ATTACHMENT0 */
|
|
2747
|
-
// TODO - support gl.readBuffer
|
|
2748
|
-
} = options || {};
|
|
2749
|
-
let {
|
|
2750
|
-
target = null,
|
|
2751
|
-
// following parameters are auto deduced if not provided
|
|
2752
|
-
sourceWidth,
|
|
2753
|
-
sourceHeight,
|
|
2754
|
-
sourceDepth,
|
|
2755
|
-
sourceFormat,
|
|
2756
|
-
sourceType
|
|
2757
|
-
} = options || {};
|
|
2758
|
-
const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
|
|
2759
|
-
const { gl, handle } = framebuffer;
|
|
2760
|
-
const attachment = sourceAttachment - 36064 /* COLOR_ATTACHMENT0 */;
|
|
2761
|
-
sourceWidth ||= framebuffer.width;
|
|
2762
|
-
sourceHeight ||= framebuffer.height;
|
|
2763
|
-
sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
|
|
2764
|
-
sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || 6408 /* RGBA */;
|
|
2765
|
-
sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || 5121 /* UNSIGNED_BYTE */;
|
|
2766
|
-
target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
|
|
2767
|
-
sourceType = sourceType || getGLTypeFromTypedArray(target);
|
|
2768
|
-
const prevHandle = gl.bindFramebuffer(36160 /* FRAMEBUFFER */, handle);
|
|
2769
|
-
gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
|
|
2770
|
-
gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle || null);
|
|
2771
|
-
if (deleteFramebuffer) {
|
|
2772
|
-
framebuffer.destroy();
|
|
2773
|
-
}
|
|
2774
|
-
return target;
|
|
2775
|
-
}
|
|
2776
|
-
function readPixelsToBuffer(source, options) {
|
|
2777
|
-
const {
|
|
2778
|
-
target,
|
|
2779
|
-
sourceX = 0,
|
|
2780
|
-
sourceY = 0,
|
|
2781
|
-
sourceFormat = 6408 /* RGBA */,
|
|
2782
|
-
targetByteOffset = 0
|
|
2783
|
-
} = options || {};
|
|
2784
|
-
let { sourceWidth, sourceHeight, sourceType } = options || {};
|
|
2785
|
-
const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
|
|
2786
|
-
sourceWidth = sourceWidth || framebuffer.width;
|
|
2787
|
-
sourceHeight = sourceHeight || framebuffer.height;
|
|
2788
|
-
const webglFramebuffer = framebuffer;
|
|
2789
|
-
sourceType = sourceType || 5121 /* UNSIGNED_BYTE */;
|
|
2790
|
-
let webglBufferTarget = target;
|
|
2791
|
-
if (!webglBufferTarget) {
|
|
2792
|
-
const components = glFormatToComponents(sourceFormat);
|
|
2793
|
-
const byteCount = glTypeToBytes(sourceType);
|
|
2794
|
-
const byteLength = targetByteOffset + sourceWidth * sourceHeight * components * byteCount;
|
|
2795
|
-
webglBufferTarget = webglFramebuffer.device.createBuffer({ byteLength });
|
|
2796
|
-
}
|
|
2797
|
-
const commandEncoder = source.device.createCommandEncoder();
|
|
2798
|
-
commandEncoder.copyTextureToBuffer({
|
|
2799
|
-
source,
|
|
2800
|
-
width: sourceWidth,
|
|
2801
|
-
height: sourceHeight,
|
|
2802
|
-
origin: [sourceX, sourceY],
|
|
2803
|
-
destination: webglBufferTarget,
|
|
2804
|
-
byteOffset: targetByteOffset
|
|
2805
|
-
});
|
|
2806
|
-
commandEncoder.destroy();
|
|
2807
|
-
if (deleteFramebuffer) {
|
|
2808
|
-
framebuffer.destroy();
|
|
2809
|
-
}
|
|
2810
|
-
return webglBufferTarget;
|
|
2811
|
-
}
|
|
2812
|
-
function getFramebuffer(source) {
|
|
2813
|
-
if (!(source instanceof import_core7.Framebuffer)) {
|
|
2814
|
-
return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
|
|
2815
|
-
}
|
|
2816
|
-
return { framebuffer: source, deleteFramebuffer: false };
|
|
2817
|
-
}
|
|
2818
|
-
function toFramebuffer(texture, props) {
|
|
2819
|
-
const { device, width, height, id } = texture;
|
|
2820
|
-
const framebuffer = device.createFramebuffer({
|
|
2821
|
-
...props,
|
|
2822
|
-
id: `framebuffer-for-${id}`,
|
|
2823
|
-
width,
|
|
2824
|
-
height,
|
|
2825
|
-
colorAttachments: [texture]
|
|
2826
|
-
});
|
|
2827
|
-
return framebuffer;
|
|
2828
|
-
}
|
|
2829
|
-
function getPixelArray(pixelArray, type, format, width, height, depth) {
|
|
2830
|
-
if (pixelArray) {
|
|
2831
|
-
return pixelArray;
|
|
2832
|
-
}
|
|
2833
|
-
type = type || 5121 /* UNSIGNED_BYTE */;
|
|
2834
|
-
const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
|
|
2835
|
-
const components = glFormatToComponents(format);
|
|
2836
|
-
return new ArrayType(width * height * components);
|
|
2837
|
-
}
|
|
2838
|
-
|
|
2839
|
-
// src/adapter/resources/webgl-texture.ts
|
|
2840
|
-
function normalizeTextureData(data, options) {
|
|
2841
|
-
let lodArray;
|
|
2842
|
-
if (ArrayBuffer.isView(data)) {
|
|
2843
|
-
lodArray = [
|
|
2844
|
-
{
|
|
2845
|
-
// ts-expect-error does data really need to be Uint8ClampedArray?
|
|
2846
|
-
data,
|
|
2847
|
-
width: options.width,
|
|
2848
|
-
height: options.height
|
|
2849
|
-
// depth: options.depth
|
|
2850
|
-
}
|
|
2851
|
-
];
|
|
2852
|
-
} else if (!Array.isArray(data)) {
|
|
2853
|
-
lodArray = [data];
|
|
2854
|
-
} else {
|
|
2855
|
-
lodArray = data;
|
|
2761
|
+
getCompilationInfoSync() {
|
|
2762
|
+
const log12 = this.device.gl.getShaderInfoLog(this.handle);
|
|
2763
|
+
return log12 ? parseShaderCompilerLog(log12) : [];
|
|
2856
2764
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
device;
|
|
2862
|
-
gl;
|
|
2863
|
-
handle;
|
|
2864
|
-
sampler = void 0;
|
|
2865
|
-
// TODO - currently unused in WebGL. Create dummy sampler?
|
|
2866
|
-
view = void 0;
|
|
2867
|
-
// TODO - currently unused in WebGL. Create dummy view?
|
|
2868
|
-
mipmaps = false;
|
|
2869
|
-
/**
|
|
2870
|
-
* @note `target` cannot be modified by bind:
|
|
2871
|
-
* textures are special because when you first bind them to a target,
|
|
2872
|
-
* When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
|
|
2873
|
-
* And it will always be a 2D texture; this state cannot be changed ever.
|
|
2874
|
-
* A texture that was first bound as a GL_TEXTURE_2D, must always be bound as a GL_TEXTURE_2D;
|
|
2875
|
-
* attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
|
|
2876
|
-
*/
|
|
2877
|
-
glTarget;
|
|
2878
|
-
// Texture type
|
|
2879
|
-
/** The WebGL format - essentially channel structure */
|
|
2880
|
-
glFormat;
|
|
2881
|
-
/** The WebGL data format - the type of each channel */
|
|
2882
|
-
glType;
|
|
2883
|
-
/** The WebGL constant corresponding to the WebGPU style constant in format */
|
|
2884
|
-
glInternalFormat;
|
|
2885
|
-
/** Whether the internal format is compressed */
|
|
2886
|
-
compressed;
|
|
2887
|
-
// data;
|
|
2888
|
-
// inherited props
|
|
2889
|
-
// dimension: ...
|
|
2890
|
-
// format: GLTextureTarget;
|
|
2891
|
-
// width: number = undefined;
|
|
2892
|
-
// height: number = undefined;
|
|
2893
|
-
// depth: number = undefined;
|
|
2894
|
-
// state
|
|
2895
|
-
/** Texture binding slot */
|
|
2896
|
-
textureUnit = 0;
|
|
2897
|
-
/** For automatically updating video */
|
|
2898
|
-
_video = null;
|
|
2899
|
-
constructor(device, props) {
|
|
2900
|
-
super(device, { ...import_core8.Texture.defaultProps, ...props, data: void 0 });
|
|
2901
|
-
this.device = device;
|
|
2902
|
-
this.gl = this.device.gl;
|
|
2903
|
-
this.glTarget = getWebGLTextureTarget(this.props.dimension);
|
|
2904
|
-
const format = getTextureFormatWebGL(this.props.format);
|
|
2905
|
-
this.glInternalFormat = format.internalFormat;
|
|
2906
|
-
this.glFormat = format.format;
|
|
2907
|
-
this.glType = format.type;
|
|
2908
|
-
this.compressed = format.compressed;
|
|
2909
|
-
if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
|
|
2910
|
-
props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
|
|
2911
|
-
const video = props.data;
|
|
2912
|
-
this._video = null;
|
|
2913
|
-
video.addEventListener("loadeddata", () => this.initialize(props));
|
|
2914
|
-
}
|
|
2915
|
-
this.initialize({ ...this.props, data: props.data });
|
|
2916
|
-
Object.seal(this);
|
|
2765
|
+
getTranslatedSource() {
|
|
2766
|
+
const extensions = this.device.getExtension("WEBGL_debug_shaders");
|
|
2767
|
+
const ext = extensions.WEBGL_debug_shaders;
|
|
2768
|
+
return ext?.getTranslatedShaderSource(this.handle) || null;
|
|
2917
2769
|
}
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
if (
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
height = textureSize?.height || 1;
|
|
2931
|
-
}
|
|
2932
|
-
this.width = width;
|
|
2933
|
-
this.height = height;
|
|
2934
|
-
this.depth = props.depth;
|
|
2935
|
-
this.setSampler(props.sampler);
|
|
2936
|
-
this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
|
|
2937
|
-
this.bind();
|
|
2938
|
-
if (!this.props.data) {
|
|
2939
|
-
initializeTextureStorage(this.gl, this.mipLevels, this);
|
|
2770
|
+
// PRIVATE METHODS
|
|
2771
|
+
/** Compile a shader and get compilation status */
|
|
2772
|
+
async _compile(source) {
|
|
2773
|
+
const addGLSLVersion = (source2) => source2.startsWith("#version ") ? source2 : `#version 300 es
|
|
2774
|
+
${source2}`;
|
|
2775
|
+
source = addGLSLVersion(source);
|
|
2776
|
+
const { gl } = this.device;
|
|
2777
|
+
gl.shaderSource(this.handle, source);
|
|
2778
|
+
gl.compileShader(this.handle);
|
|
2779
|
+
if (import_core9.log.level === 0) {
|
|
2780
|
+
this.compilationStatus = "pending";
|
|
2781
|
+
return;
|
|
2940
2782
|
}
|
|
2941
|
-
if (
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
case "2d":
|
|
2947
|
-
this.setTexture2DData(props.data);
|
|
2948
|
-
break;
|
|
2949
|
-
case "3d":
|
|
2950
|
-
this.setTexture3DData(props.data);
|
|
2951
|
-
break;
|
|
2952
|
-
case "cube":
|
|
2953
|
-
this.setTextureCubeData(props.data);
|
|
2954
|
-
break;
|
|
2955
|
-
case "2d-array":
|
|
2956
|
-
this.setTextureArrayData(props.data);
|
|
2957
|
-
break;
|
|
2958
|
-
case "cube-array":
|
|
2959
|
-
this.setTextureCubeArrayData(props.data);
|
|
2960
|
-
break;
|
|
2961
|
-
default:
|
|
2962
|
-
throw new Error(props.dimension);
|
|
2783
|
+
if (!this.device.features.has("compilation-status-async-webgl")) {
|
|
2784
|
+
this._getCompilationStatus();
|
|
2785
|
+
this.debugShader();
|
|
2786
|
+
if (this.compilationStatus === "error") {
|
|
2787
|
+
throw new Error(`GLSL compilation errors in ${this.props.stage} shader ${this.props.id}`);
|
|
2963
2788
|
}
|
|
2964
|
-
}
|
|
2965
|
-
this.mipmaps = Boolean(props.mipmaps);
|
|
2966
|
-
if (this.mipmaps) {
|
|
2967
|
-
this.generateMipmap();
|
|
2968
|
-
}
|
|
2969
|
-
}
|
|
2970
|
-
/*
|
|
2971
|
-
initializeCube(props?: TextureProps): void {
|
|
2972
|
-
const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
|
|
2973
|
-
|
|
2974
|
-
// Store props for accessors
|
|
2975
|
-
// this.props = props;
|
|
2976
|
-
|
|
2977
|
-
// @ts-expect-error
|
|
2978
|
-
this.setCubeMapData(props).then(() => {
|
|
2979
|
-
// TODO - should genMipmap() be called on the cubemap or on the faces?
|
|
2980
|
-
// TODO - without generateMipmap() cube textures do not work at all!!! Why?
|
|
2981
|
-
if (mipmaps) {
|
|
2982
|
-
this.generateMipmap(props);
|
|
2983
|
-
}
|
|
2984
|
-
|
|
2985
|
-
this.setSampler(props.sampler);
|
|
2986
|
-
|
|
2987
|
-
// v8 compatibility?
|
|
2988
|
-
// const {parameters = {} as Record<GL, any>} = props;
|
|
2989
|
-
// this._setSamplerParameters(parameters);
|
|
2990
|
-
});
|
|
2991
|
-
}
|
|
2992
|
-
*/
|
|
2993
|
-
destroy() {
|
|
2994
|
-
if (this.handle) {
|
|
2995
|
-
this.gl.deleteTexture(this.handle);
|
|
2996
|
-
this.removeStats();
|
|
2997
|
-
this.trackDeallocatedMemory("Texture");
|
|
2998
|
-
this.destroyed = true;
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
toString() {
|
|
3002
|
-
return `Texture(${this.id},${this.width}x${this.height})`;
|
|
3003
|
-
}
|
|
3004
|
-
createView(props) {
|
|
3005
|
-
return new WEBGLTextureView(this.device, { ...props, texture: this });
|
|
3006
|
-
}
|
|
3007
|
-
setSampler(sampler = {}) {
|
|
3008
|
-
let samplerProps;
|
|
3009
|
-
if (sampler instanceof WEBGLSampler) {
|
|
3010
|
-
this.sampler = sampler;
|
|
3011
|
-
samplerProps = sampler.props;
|
|
3012
|
-
} else {
|
|
3013
|
-
this.sampler = new WEBGLSampler(this.device, sampler);
|
|
3014
|
-
samplerProps = sampler;
|
|
3015
|
-
}
|
|
3016
|
-
const parameters = convertSamplerParametersToWebGL(samplerProps);
|
|
3017
|
-
this._setSamplerParameters(parameters);
|
|
3018
|
-
}
|
|
3019
|
-
/** Update external texture (video frame or canvas) */
|
|
3020
|
-
update() {
|
|
3021
|
-
import_core8.log.warn("Texture.update() not implemented");
|
|
3022
|
-
}
|
|
3023
|
-
// Call to regenerate mipmaps after modifying texture(s)
|
|
3024
|
-
generateMipmap(params = {}) {
|
|
3025
|
-
if (!this.props.data) {
|
|
3026
2789
|
return;
|
|
3027
2790
|
}
|
|
3028
|
-
|
|
3029
|
-
this.
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
this.gl.bindTexture(this.glTarget, null);
|
|
3034
|
-
}
|
|
3035
|
-
// Image Data Setters
|
|
3036
|
-
copyExternalImage(options) {
|
|
3037
|
-
const size = import_core8.Texture.getExternalImageSize(options.image);
|
|
3038
|
-
const opts = { ...import_core8.Texture.defaultCopyExternalImageOptions, ...size, ...options };
|
|
3039
|
-
const { image, depth, mipLevel, x, y, z } = opts;
|
|
3040
|
-
let { width, height } = opts;
|
|
3041
|
-
const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
|
|
3042
|
-
width = Math.min(width, size.width - x);
|
|
3043
|
-
height = Math.min(height, size.height - y);
|
|
3044
|
-
if (options.sourceX || options.sourceY) {
|
|
3045
|
-
throw new Error(
|
|
3046
|
-
"WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer"
|
|
3047
|
-
);
|
|
3048
|
-
}
|
|
3049
|
-
copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
|
|
3050
|
-
dimension,
|
|
3051
|
-
mipLevel,
|
|
3052
|
-
x,
|
|
3053
|
-
y,
|
|
3054
|
-
z,
|
|
3055
|
-
width,
|
|
3056
|
-
height,
|
|
3057
|
-
depth,
|
|
3058
|
-
glFormat,
|
|
3059
|
-
glInternalFormat,
|
|
3060
|
-
glType,
|
|
3061
|
-
glTarget
|
|
3062
|
-
});
|
|
3063
|
-
return { width: opts.width, height: opts.height };
|
|
3064
|
-
}
|
|
3065
|
-
setTexture1DData(data) {
|
|
3066
|
-
throw new Error("setTexture1DData not supported in WebGL.");
|
|
3067
|
-
}
|
|
3068
|
-
/** Set a simple texture */
|
|
3069
|
-
setTexture2DData(lodData, depth = 0) {
|
|
3070
|
-
this.bind();
|
|
3071
|
-
const lodArray = normalizeTextureData(lodData, this);
|
|
3072
|
-
if (lodArray.length > 1 && this.props.mipmaps !== false) {
|
|
3073
|
-
import_core8.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
|
|
3074
|
-
}
|
|
3075
|
-
for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
|
|
3076
|
-
const imageData = lodArray[lodLevel];
|
|
3077
|
-
this._setMipLevel(depth, lodLevel, imageData);
|
|
3078
|
-
}
|
|
3079
|
-
this.unbind();
|
|
3080
|
-
}
|
|
3081
|
-
/**
|
|
3082
|
-
* Sets a 3D texture
|
|
3083
|
-
* @param data
|
|
3084
|
-
*/
|
|
3085
|
-
setTexture3DData(data) {
|
|
3086
|
-
if (this.props.dimension !== "3d") {
|
|
3087
|
-
throw new Error(this.id);
|
|
3088
|
-
}
|
|
3089
|
-
if (ArrayBuffer.isView(data)) {
|
|
3090
|
-
this.bind();
|
|
3091
|
-
copyCPUDataToMipLevel(this.device.gl, data, this);
|
|
3092
|
-
this.unbind();
|
|
3093
|
-
}
|
|
3094
|
-
}
|
|
3095
|
-
/**
|
|
3096
|
-
* Set a Texture Cube Data
|
|
3097
|
-
* @todo - could support TextureCubeArray with depth
|
|
3098
|
-
* @param data
|
|
3099
|
-
* @param index
|
|
3100
|
-
*/
|
|
3101
|
-
setTextureCubeData(data, depth = 0) {
|
|
3102
|
-
if (this.props.dimension !== "cube") {
|
|
3103
|
-
throw new Error(this.id);
|
|
3104
|
-
}
|
|
3105
|
-
for (const face of import_core8.Texture.CubeFaces) {
|
|
3106
|
-
this.setTextureCubeFaceData(data[face], face);
|
|
3107
|
-
}
|
|
2791
|
+
import_core9.log.once(1, "Shader compilation is asynchronous")();
|
|
2792
|
+
await this._waitForCompilationComplete();
|
|
2793
|
+
import_core9.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
|
|
2794
|
+
this._getCompilationStatus();
|
|
2795
|
+
this.debugShader();
|
|
3108
2796
|
}
|
|
3109
|
-
/**
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
2797
|
+
/** Use KHR_parallel_shader_compile extension if available */
|
|
2798
|
+
async _waitForCompilationComplete() {
|
|
2799
|
+
const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
|
|
2800
|
+
const DELAY_MS = 10;
|
|
2801
|
+
if (!this.device.features.has("compilation-status-async-webgl")) {
|
|
2802
|
+
await waitMs(DELAY_MS);
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const { gl } = this.device;
|
|
2806
|
+
for (; ; ) {
|
|
2807
|
+
const complete = gl.getShaderParameter(this.handle, 37297 /* COMPLETION_STATUS_KHR */);
|
|
2808
|
+
if (complete) {
|
|
2809
|
+
return;
|
|
2810
|
+
}
|
|
2811
|
+
await waitMs(DELAY_MS);
|
|
3116
2812
|
}
|
|
3117
|
-
throw new Error("setTextureArrayData not implemented.");
|
|
3118
2813
|
}
|
|
3119
2814
|
/**
|
|
3120
|
-
*
|
|
3121
|
-
*
|
|
2815
|
+
* Get the shader compilation status
|
|
2816
|
+
* TODO - Load log even when no error reported, to catch warnings?
|
|
2817
|
+
* https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
|
|
3122
2818
|
*/
|
|
3123
|
-
|
|
3124
|
-
|
|
2819
|
+
_getCompilationStatus() {
|
|
2820
|
+
this.compilationStatus = this.device.gl.getShaderParameter(this.handle, 35713 /* COMPILE_STATUS */) ? "success" : "error";
|
|
3125
2821
|
}
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
2822
|
+
};
|
|
2823
|
+
|
|
2824
|
+
// src/adapter/resources/webgl-sampler.ts
|
|
2825
|
+
var import_core11 = __toESM(require_core(), 1);
|
|
2826
|
+
|
|
2827
|
+
// src/adapter/converters/device-parameters.ts
|
|
2828
|
+
var import_core10 = __toESM(require_core(), 1);
|
|
2829
|
+
function withDeviceAndGLParameters(device, parameters, glParameters, func) {
|
|
2830
|
+
if (isObjectEmpty2(parameters)) {
|
|
2831
|
+
return func(device);
|
|
3132
2832
|
}
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
data,
|
|
3142
|
-
format = 6408 /* RGBA */,
|
|
3143
|
-
type = 5121 /* UNSIGNED_BYTE */
|
|
3144
|
-
// generateMipmap = false // TODO
|
|
3145
|
-
} = options;
|
|
3146
|
-
const { gl } = this;
|
|
3147
|
-
const imageData = pixels || data;
|
|
3148
|
-
this.bind();
|
|
3149
|
-
if (imageData instanceof Promise) {
|
|
3150
|
-
imageData.then(
|
|
3151
|
-
(resolvedImageData) => this.setImageDataForFace(
|
|
3152
|
-
Object.assign({}, options, {
|
|
3153
|
-
face,
|
|
3154
|
-
data: resolvedImageData,
|
|
3155
|
-
pixels: resolvedImageData
|
|
3156
|
-
})
|
|
3157
|
-
)
|
|
3158
|
-
);
|
|
3159
|
-
} else if (this.width || this.height) {
|
|
3160
|
-
gl.texImage2D(face, 0, format, width, height, 0, format, type, imageData);
|
|
3161
|
-
} else {
|
|
3162
|
-
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
3163
|
-
}
|
|
2833
|
+
const webglDevice = device;
|
|
2834
|
+
webglDevice.pushState();
|
|
2835
|
+
try {
|
|
2836
|
+
setDeviceParameters(device, parameters);
|
|
2837
|
+
setGLParameters(webglDevice.gl, glParameters);
|
|
2838
|
+
return func(device);
|
|
2839
|
+
} finally {
|
|
2840
|
+
webglDevice.popState();
|
|
3164
2841
|
}
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
2842
|
+
}
|
|
2843
|
+
function withDeviceParameters(device, parameters, func) {
|
|
2844
|
+
if (isObjectEmpty2(parameters)) {
|
|
2845
|
+
return func(device);
|
|
2846
|
+
}
|
|
2847
|
+
const webglDevice = device;
|
|
2848
|
+
webglDevice.pushState();
|
|
2849
|
+
try {
|
|
2850
|
+
setDeviceParameters(device, parameters);
|
|
2851
|
+
return func(device);
|
|
2852
|
+
} finally {
|
|
2853
|
+
webglDevice.popState();
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
function setDeviceParameters(device, parameters) {
|
|
2857
|
+
const webglDevice = device;
|
|
2858
|
+
const { gl } = webglDevice;
|
|
2859
|
+
if (parameters.cullMode) {
|
|
2860
|
+
switch (parameters.cullMode) {
|
|
2861
|
+
case "none":
|
|
2862
|
+
gl.disable(2884 /* CULL_FACE */);
|
|
2863
|
+
break;
|
|
2864
|
+
case "front":
|
|
2865
|
+
gl.enable(2884 /* CULL_FACE */);
|
|
2866
|
+
gl.cullFace(1028 /* FRONT */);
|
|
2867
|
+
break;
|
|
2868
|
+
case "back":
|
|
2869
|
+
gl.enable(2884 /* CULL_FACE */);
|
|
2870
|
+
gl.cullFace(1029 /* BACK */);
|
|
2871
|
+
break;
|
|
3172
2872
|
}
|
|
3173
|
-
return faceData;
|
|
3174
2873
|
}
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
case 33082 /* TEXTURE_MIN_LOD */:
|
|
3187
|
-
case 33083 /* TEXTURE_MAX_LOD */:
|
|
3188
|
-
this.gl.texParameterf(this.glTarget, param, value);
|
|
3189
|
-
break;
|
|
3190
|
-
case 10241 /* TEXTURE_MIN_FILTER */:
|
|
3191
|
-
this.gl.texParameteri(this.glTarget, param, value);
|
|
3192
|
-
break;
|
|
3193
|
-
case 10242 /* TEXTURE_WRAP_S */:
|
|
3194
|
-
case 10243 /* TEXTURE_WRAP_T */:
|
|
3195
|
-
this.gl.texParameteri(this.glTarget, param, value);
|
|
3196
|
-
break;
|
|
3197
|
-
case 34046 /* TEXTURE_MAX_ANISOTROPY_EXT */:
|
|
3198
|
-
if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
|
|
3199
|
-
this.gl.texParameteri(this.glTarget, param, value);
|
|
3200
|
-
}
|
|
3201
|
-
break;
|
|
3202
|
-
default:
|
|
3203
|
-
this.gl.texParameteri(this.glTarget, param, value);
|
|
3204
|
-
break;
|
|
3205
|
-
}
|
|
2874
|
+
if (parameters.frontFace) {
|
|
2875
|
+
gl.frontFace(
|
|
2876
|
+
map("frontFace", parameters.frontFace, {
|
|
2877
|
+
ccw: 2305 /* CCW */,
|
|
2878
|
+
cw: 2304 /* CW */
|
|
2879
|
+
})
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2882
|
+
if (parameters.unclippedDepth) {
|
|
2883
|
+
if (device.features.has("depth-clip-control")) {
|
|
2884
|
+
gl.enable(34383 /* DEPTH_CLAMP_EXT */);
|
|
3206
2885
|
}
|
|
3207
|
-
this.gl.bindTexture(this.glTarget, null);
|
|
3208
2886
|
}
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
// pixel data (imageDataMap) is an Object from Face to Image or Promise.
|
|
3225
|
-
// For example:
|
|
3226
|
-
// {
|
|
3227
|
-
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
|
|
3228
|
-
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
|
|
3229
|
-
// ... }
|
|
3230
|
-
// To provide multiple level-of-details (LODs) this can be Face to Array
|
|
3231
|
-
// of Image or Promise, like this
|
|
3232
|
-
// {
|
|
3233
|
-
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
3234
|
-
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
3235
|
-
// ... }
|
|
3236
|
-
|
|
3237
|
-
const imageDataMap = this._getImageDataMap(pixels || data);
|
|
3238
|
-
|
|
3239
|
-
const resolvedFaces = WEBGLTexture.FACES.map(face => {
|
|
3240
|
-
const facePixels = imageDataMap[face];
|
|
3241
|
-
return Array.isArray(facePixels) ? facePixels : [facePixels];
|
|
3242
|
-
});
|
|
3243
|
-
this.bind();
|
|
3244
|
-
|
|
3245
|
-
WEBGLTexture.FACES.forEach((face, index) => {
|
|
3246
|
-
if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
|
|
3247
|
-
// If the user provides multiple LODs, then automatic mipmap
|
|
3248
|
-
// generation generateMipmap() should be disabled to avoid overwritting them.
|
|
3249
|
-
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
2887
|
+
if (parameters.depthBias !== void 0) {
|
|
2888
|
+
gl.enable(32823 /* POLYGON_OFFSET_FILL */);
|
|
2889
|
+
gl.polygonOffset(parameters.depthBias, parameters.depthBiasSlopeScale || 0);
|
|
2890
|
+
}
|
|
2891
|
+
if (parameters.provokingVertex) {
|
|
2892
|
+
if (device.features.has("provoking-vertex-webgl")) {
|
|
2893
|
+
const extensions = webglDevice.getExtension("WEBGL_provoking_vertex");
|
|
2894
|
+
const ext = extensions.WEBGL_provoking_vertex;
|
|
2895
|
+
const vertex = map(
|
|
2896
|
+
"provokingVertex",
|
|
2897
|
+
parameters.provokingVertex,
|
|
2898
|
+
{
|
|
2899
|
+
first: 36429 /* FIRST_VERTEX_CONVENTION_WEBGL */,
|
|
2900
|
+
last: 36430 /* LAST_VERTEX_CONVENTION_WEBGL */
|
|
3250
2901
|
}
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
if (width && height) {
|
|
3254
|
-
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
|
|
3255
|
-
} else {
|
|
3256
|
-
gl.texImage2D(face, lodLevel, format, format, type, image);
|
|
3257
|
-
}
|
|
3258
|
-
});
|
|
3259
|
-
});
|
|
3260
|
-
|
|
3261
|
-
this.unbind();
|
|
3262
|
-
}
|
|
3263
|
-
*/
|
|
3264
|
-
// INTERNAL SETTERS
|
|
3265
|
-
/**
|
|
3266
|
-
* Copy a region of data from a CPU memory buffer into this texture.
|
|
3267
|
-
* @todo - GLUnpackParameters parameters
|
|
3268
|
-
*/
|
|
3269
|
-
_setMipLevel(depth, mipLevel, textureData, glTarget = this.glTarget) {
|
|
3270
|
-
if (import_core8.Texture.isExternalImage(textureData)) {
|
|
3271
|
-
copyExternalImageToMipLevel(this.device.gl, this.handle, textureData, {
|
|
3272
|
-
...this,
|
|
3273
|
-
depth,
|
|
3274
|
-
mipLevel,
|
|
3275
|
-
glTarget
|
|
3276
|
-
});
|
|
3277
|
-
return;
|
|
3278
|
-
}
|
|
3279
|
-
if (import_core8.Texture.isTextureLevelData(textureData)) {
|
|
3280
|
-
copyCPUDataToMipLevel(this.device.gl, textureData.data, {
|
|
3281
|
-
...this,
|
|
3282
|
-
depth,
|
|
3283
|
-
mipLevel,
|
|
3284
|
-
glTarget
|
|
3285
|
-
});
|
|
3286
|
-
return;
|
|
2902
|
+
);
|
|
2903
|
+
ext?.provokingVertexWEBGL(vertex);
|
|
3287
2904
|
}
|
|
3288
|
-
throw new Error("Texture: invalid image data");
|
|
3289
|
-
}
|
|
3290
|
-
// HELPERS
|
|
3291
|
-
getActiveUnit() {
|
|
3292
|
-
return this.gl.getParameter(34016 /* ACTIVE_TEXTURE */) - 33984 /* TEXTURE0 */;
|
|
3293
2905
|
}
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
2906
|
+
if (parameters.polygonMode || parameters.polygonOffsetLine) {
|
|
2907
|
+
if (device.features.has("polygon-mode-webgl")) {
|
|
2908
|
+
if (parameters.polygonMode) {
|
|
2909
|
+
const extensions = webglDevice.getExtension("WEBGL_polygon_mode");
|
|
2910
|
+
const ext = extensions.WEBGL_polygon_mode;
|
|
2911
|
+
const mode = map("polygonMode", parameters.polygonMode, {
|
|
2912
|
+
fill: 6914 /* FILL_WEBGL */,
|
|
2913
|
+
line: 6913 /* LINE_WEBGL */
|
|
2914
|
+
});
|
|
2915
|
+
ext?.polygonModeWEBGL(1028 /* FRONT */, mode);
|
|
2916
|
+
ext?.polygonModeWEBGL(1029 /* BACK */, mode);
|
|
2917
|
+
}
|
|
2918
|
+
if (parameters.polygonOffsetLine) {
|
|
2919
|
+
gl.enable(10754 /* POLYGON_OFFSET_LINE_WEBGL */);
|
|
2920
|
+
}
|
|
3299
2921
|
}
|
|
3300
|
-
gl.bindTexture(this.glTarget, this.handle);
|
|
3301
|
-
return textureUnit;
|
|
3302
2922
|
}
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
this.textureUnit = textureUnit;
|
|
3307
|
-
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
2923
|
+
if (device.features.has("shader-clip-cull-distance-webgl")) {
|
|
2924
|
+
if (parameters.clipDistance0) {
|
|
2925
|
+
gl.enable(12288 /* CLIP_DISTANCE0_WEBGL */);
|
|
3308
2926
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
}
|
|
3312
|
-
};
|
|
3313
|
-
|
|
3314
|
-
// src/adapter/resources/webgl-framebuffer.ts
|
|
3315
|
-
var WEBGLFramebuffer = class extends import_core9.Framebuffer {
|
|
3316
|
-
device;
|
|
3317
|
-
gl;
|
|
3318
|
-
handle;
|
|
3319
|
-
colorAttachments = [];
|
|
3320
|
-
depthStencilAttachment = null;
|
|
3321
|
-
constructor(device, props) {
|
|
3322
|
-
super(device, props);
|
|
3323
|
-
const isDefaultFramebuffer = props.handle === null;
|
|
3324
|
-
this.device = device;
|
|
3325
|
-
this.gl = device.gl;
|
|
3326
|
-
this.handle = this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
|
|
3327
|
-
if (!isDefaultFramebuffer) {
|
|
3328
|
-
device.setSpectorMetadata(this.handle, { id: this.props.id, props: this.props });
|
|
3329
|
-
this.autoCreateAttachmentTextures();
|
|
3330
|
-
this.updateAttachments();
|
|
2927
|
+
if (parameters.clipDistance1) {
|
|
2928
|
+
gl.enable(12289 /* CLIP_DISTANCE1_WEBGL */);
|
|
3331
2929
|
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
destroy() {
|
|
3335
|
-
super.destroy();
|
|
3336
|
-
if (!this.destroyed && this.handle !== null) {
|
|
3337
|
-
this.gl.deleteFramebuffer(this.handle);
|
|
2930
|
+
if (parameters.clipDistance2) {
|
|
2931
|
+
gl.enable(12290 /* CLIP_DISTANCE2_WEBGL */);
|
|
3338
2932
|
}
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
const prevHandle = this.gl.bindFramebuffer(
|
|
3342
|
-
36160 /* FRAMEBUFFER */,
|
|
3343
|
-
this.handle
|
|
3344
|
-
);
|
|
3345
|
-
for (let i = 0; i < this.colorAttachments.length; ++i) {
|
|
3346
|
-
const attachment = this.colorAttachments[i];
|
|
3347
|
-
if (attachment) {
|
|
3348
|
-
const attachmentPoint = 36064 /* COLOR_ATTACHMENT0 */ + i;
|
|
3349
|
-
this._attachTextureView(attachmentPoint, attachment);
|
|
3350
|
-
}
|
|
2933
|
+
if (parameters.clipDistance3) {
|
|
2934
|
+
gl.enable(12291 /* CLIP_DISTANCE3_WEBGL */);
|
|
3351
2935
|
}
|
|
3352
|
-
if (
|
|
3353
|
-
|
|
3354
|
-
this.depthStencilAttachment.props.format
|
|
3355
|
-
);
|
|
3356
|
-
this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
|
|
2936
|
+
if (parameters.clipDistance4) {
|
|
2937
|
+
gl.enable(12292 /* CLIP_DISTANCE4_WEBGL */);
|
|
3357
2938
|
}
|
|
3358
|
-
if (
|
|
3359
|
-
|
|
3360
|
-
if (status !== 36053 /* FRAMEBUFFER_COMPLETE */) {
|
|
3361
|
-
throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
|
|
3362
|
-
}
|
|
2939
|
+
if (parameters.clipDistance5) {
|
|
2940
|
+
gl.enable(12293 /* CLIP_DISTANCE5_WEBGL */);
|
|
3363
2941
|
}
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
// PRIVATE
|
|
3367
|
-
/** In WebGL we must use renderbuffers for depth/stencil attachments (unless we have extensions) */
|
|
3368
|
-
createDepthStencilTexture(format) {
|
|
3369
|
-
return new WEBGLTexture(this.device, {
|
|
3370
|
-
id: `${this.id}-depth-stencil`,
|
|
3371
|
-
format,
|
|
3372
|
-
width: this.width,
|
|
3373
|
-
height: this.height,
|
|
3374
|
-
mipmaps: false
|
|
3375
|
-
});
|
|
3376
|
-
}
|
|
3377
|
-
/**
|
|
3378
|
-
* Attachment resize is expected to be a noop if size is same
|
|
3379
|
-
*
|
|
3380
|
-
protected override resizeAttachments(width: number, height: number): this {
|
|
3381
|
-
// for default framebuffer, just update the stored size
|
|
3382
|
-
if (this.handle === null) {
|
|
3383
|
-
// assert(width === undefined && height === undefined);
|
|
3384
|
-
this.width = this.gl.drawingBufferWidth;
|
|
3385
|
-
this.height = this.gl.drawingBufferHeight;
|
|
3386
|
-
return this;
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
|
-
if (width === undefined) {
|
|
3390
|
-
width = this.gl.drawingBufferWidth;
|
|
3391
|
-
}
|
|
3392
|
-
if (height === undefined) {
|
|
3393
|
-
height = this.gl.drawingBufferHeight;
|
|
3394
|
-
}
|
|
3395
|
-
|
|
3396
|
-
// TODO Not clear that this is better than default destroy/create implementation
|
|
3397
|
-
|
|
3398
|
-
for (const colorAttachment of this.colorAttachments) {
|
|
3399
|
-
colorAttachment.texture.clone({width, height});
|
|
3400
|
-
}
|
|
3401
|
-
if (this.depthStencilAttachment) {
|
|
3402
|
-
this.depthStencilAttachment.texture.resize({width, height});
|
|
3403
|
-
}
|
|
3404
|
-
return this;
|
|
2942
|
+
if (parameters.clipDistance6) {
|
|
2943
|
+
gl.enable(12294 /* CLIP_DISTANCE6_WEBGL */);
|
|
3405
2944
|
}
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
* @param attachment
|
|
3409
|
-
* @param texture
|
|
3410
|
-
* @param layer = 0 - index into WEBGLTextureArray and Texture3D or face for `TextureCubeMap`
|
|
3411
|
-
* @param level = 0 - mipmapLevel
|
|
3412
|
-
*/
|
|
3413
|
-
_attachTextureView(attachment, textureView) {
|
|
3414
|
-
const { gl } = this.device;
|
|
3415
|
-
const { texture } = textureView;
|
|
3416
|
-
const level = textureView.props.baseMipLevel;
|
|
3417
|
-
const layer = textureView.props.baseArrayLayer;
|
|
3418
|
-
gl.bindTexture(texture.glTarget, texture.handle);
|
|
3419
|
-
switch (texture.glTarget) {
|
|
3420
|
-
case 35866 /* TEXTURE_2D_ARRAY */:
|
|
3421
|
-
case 32879 /* TEXTURE_3D */:
|
|
3422
|
-
gl.framebufferTextureLayer(36160 /* FRAMEBUFFER */, attachment, texture.handle, level, layer);
|
|
3423
|
-
break;
|
|
3424
|
-
case 34067 /* TEXTURE_CUBE_MAP */:
|
|
3425
|
-
const face = mapIndexToCubeMapFace(layer);
|
|
3426
|
-
gl.framebufferTexture2D(36160 /* FRAMEBUFFER */, attachment, face, texture.handle, level);
|
|
3427
|
-
break;
|
|
3428
|
-
case 3553 /* TEXTURE_2D */:
|
|
3429
|
-
gl.framebufferTexture2D(36160 /* FRAMEBUFFER */, attachment, 3553 /* TEXTURE_2D */, texture.handle, level);
|
|
3430
|
-
break;
|
|
3431
|
-
default:
|
|
3432
|
-
throw new Error("Illegal texture type");
|
|
2945
|
+
if (parameters.clipDistance7) {
|
|
2946
|
+
gl.enable(12295 /* CLIP_DISTANCE7_WEBGL */);
|
|
3433
2947
|
}
|
|
3434
|
-
gl.bindTexture(texture.glTarget, null);
|
|
3435
2948
|
}
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
2949
|
+
if (parameters.depthWriteEnabled !== void 0) {
|
|
2950
|
+
gl.depthMask(mapBoolean("depthWriteEnabled", parameters.depthWriteEnabled));
|
|
2951
|
+
}
|
|
2952
|
+
if (parameters.depthCompare) {
|
|
2953
|
+
parameters.depthCompare !== "always" ? gl.enable(2929 /* DEPTH_TEST */) : gl.disable(2929 /* DEPTH_TEST */);
|
|
2954
|
+
gl.depthFunc(convertCompareFunction("depthCompare", parameters.depthCompare));
|
|
2955
|
+
}
|
|
2956
|
+
if (parameters.stencilWriteMask) {
|
|
2957
|
+
const mask = parameters.stencilWriteMask;
|
|
2958
|
+
gl.stencilMaskSeparate(1028 /* FRONT */, mask);
|
|
2959
|
+
gl.stencilMaskSeparate(1029 /* BACK */, mask);
|
|
2960
|
+
}
|
|
2961
|
+
if (parameters.stencilReadMask) {
|
|
2962
|
+
import_core10.log.warn("stencilReadMask not supported under WebGL");
|
|
2963
|
+
}
|
|
2964
|
+
if (parameters.stencilCompare) {
|
|
2965
|
+
const mask = parameters.stencilReadMask || 4294967295;
|
|
2966
|
+
const glValue = convertCompareFunction("depthCompare", parameters.stencilCompare);
|
|
2967
|
+
parameters.stencilCompare !== "always" ? gl.enable(2960 /* STENCIL_TEST */) : gl.disable(2960 /* STENCIL_TEST */);
|
|
2968
|
+
gl.stencilFuncSeparate(1028 /* FRONT */, glValue, 0, mask);
|
|
2969
|
+
gl.stencilFuncSeparate(1029 /* BACK */, glValue, 0, mask);
|
|
2970
|
+
}
|
|
2971
|
+
if (parameters.stencilPassOperation && parameters.stencilFailOperation && parameters.stencilDepthFailOperation) {
|
|
2972
|
+
const dppass = convertStencilOperation("stencilPassOperation", parameters.stencilPassOperation);
|
|
2973
|
+
const sfail = convertStencilOperation("stencilFailOperation", parameters.stencilFailOperation);
|
|
2974
|
+
const dpfail = convertStencilOperation(
|
|
2975
|
+
"stencilDepthFailOperation",
|
|
2976
|
+
parameters.stencilDepthFailOperation
|
|
2977
|
+
);
|
|
2978
|
+
gl.stencilOpSeparate(1028 /* FRONT */, sfail, dpfail, dppass);
|
|
2979
|
+
gl.stencilOpSeparate(1029 /* BACK */, sfail, dpfail, dppass);
|
|
2980
|
+
}
|
|
2981
|
+
switch (parameters.blend) {
|
|
2982
|
+
case true:
|
|
2983
|
+
gl.enable(3042 /* BLEND */);
|
|
2984
|
+
break;
|
|
2985
|
+
case false:
|
|
2986
|
+
gl.disable(3042 /* BLEND */);
|
|
2987
|
+
break;
|
|
2988
|
+
default:
|
|
2989
|
+
}
|
|
2990
|
+
if (parameters.blendColorOperation || parameters.blendAlphaOperation) {
|
|
2991
|
+
const colorEquation = convertBlendOperationToEquation(
|
|
2992
|
+
"blendColorOperation",
|
|
2993
|
+
parameters.blendColorOperation || "add"
|
|
2994
|
+
);
|
|
2995
|
+
const alphaEquation = convertBlendOperationToEquation(
|
|
2996
|
+
"blendAlphaOperation",
|
|
2997
|
+
parameters.blendAlphaOperation || "add"
|
|
2998
|
+
);
|
|
2999
|
+
gl.blendEquationSeparate(colorEquation, alphaEquation);
|
|
3000
|
+
const colorSrcFactor = convertBlendFactorToFunction(
|
|
3001
|
+
"blendColorSrcFactor",
|
|
3002
|
+
parameters.blendColorSrcFactor || "one"
|
|
3003
|
+
);
|
|
3004
|
+
const colorDstFactor = convertBlendFactorToFunction(
|
|
3005
|
+
"blendColorDstFactor",
|
|
3006
|
+
parameters.blendColorDstFactor || "zero"
|
|
3007
|
+
);
|
|
3008
|
+
const alphaSrcFactor = convertBlendFactorToFunction(
|
|
3009
|
+
"blendAlphaSrcFactor",
|
|
3010
|
+
parameters.blendAlphaSrcFactor || "one"
|
|
3011
|
+
);
|
|
3012
|
+
const alphaDstFactor = convertBlendFactorToFunction(
|
|
3013
|
+
"blendAlphaDstFactor",
|
|
3014
|
+
parameters.blendAlphaDstFactor || "zero"
|
|
3015
|
+
);
|
|
3016
|
+
gl.blendFuncSeparate(colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor);
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
function convertCompareFunction(parameter, value) {
|
|
3020
|
+
return map(parameter, value, {
|
|
3021
|
+
never: 512 /* NEVER */,
|
|
3022
|
+
less: 513 /* LESS */,
|
|
3023
|
+
equal: 514 /* EQUAL */,
|
|
3024
|
+
"less-equal": 515 /* LEQUAL */,
|
|
3025
|
+
greater: 516 /* GREATER */,
|
|
3026
|
+
"not-equal": 517 /* NOTEQUAL */,
|
|
3027
|
+
"greater-equal": 518 /* GEQUAL */,
|
|
3028
|
+
always: 519 /* ALWAYS */
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
function convertStencilOperation(parameter, value) {
|
|
3032
|
+
return map(parameter, value, {
|
|
3033
|
+
keep: 7680 /* KEEP */,
|
|
3034
|
+
zero: 0 /* ZERO */,
|
|
3035
|
+
replace: 7681 /* REPLACE */,
|
|
3036
|
+
invert: 5386 /* INVERT */,
|
|
3037
|
+
"increment-clamp": 7682 /* INCR */,
|
|
3038
|
+
"decrement-clamp": 7683 /* DECR */,
|
|
3039
|
+
"increment-wrap": 34055 /* INCR_WRAP */,
|
|
3040
|
+
"decrement-wrap": 34056 /* DECR_WRAP */
|
|
3041
|
+
});
|
|
3042
|
+
}
|
|
3043
|
+
function convertBlendOperationToEquation(parameter, value) {
|
|
3044
|
+
return map(parameter, value, {
|
|
3045
|
+
add: 32774 /* FUNC_ADD */,
|
|
3046
|
+
subtract: 32778 /* FUNC_SUBTRACT */,
|
|
3047
|
+
"reverse-subtract": 32779 /* FUNC_REVERSE_SUBTRACT */,
|
|
3048
|
+
min: 32775 /* MIN */,
|
|
3049
|
+
max: 32776 /* MAX */
|
|
3050
|
+
});
|
|
3051
|
+
}
|
|
3052
|
+
function convertBlendFactorToFunction(parameter, value) {
|
|
3053
|
+
return map(parameter, value, {
|
|
3054
|
+
one: 1 /* ONE */,
|
|
3055
|
+
zero: 0 /* ZERO */,
|
|
3056
|
+
"src-color": 768 /* SRC_COLOR */,
|
|
3057
|
+
"one-minus-src-color": 769 /* ONE_MINUS_SRC_COLOR */,
|
|
3058
|
+
"dst-color": 774 /* DST_COLOR */,
|
|
3059
|
+
"one-minus-dst-color": 775 /* ONE_MINUS_DST_COLOR */,
|
|
3060
|
+
"src-alpha": 770 /* SRC_ALPHA */,
|
|
3061
|
+
"one-minus-src-alpha": 771 /* ONE_MINUS_SRC_ALPHA */,
|
|
3062
|
+
"dst-alpha": 772 /* DST_ALPHA */,
|
|
3063
|
+
"one-minus-dst-alpha": 773 /* ONE_MINUS_DST_ALPHA */,
|
|
3064
|
+
"src-alpha-saturated": 776 /* SRC_ALPHA_SATURATE */,
|
|
3065
|
+
"constant-color": 32769 /* CONSTANT_COLOR */,
|
|
3066
|
+
"one-minus-constant-color": 32770 /* ONE_MINUS_CONSTANT_COLOR */,
|
|
3067
|
+
"constant-alpha": 32771 /* CONSTANT_ALPHA */,
|
|
3068
|
+
"one-minus-constant-alpha": 32772 /* ONE_MINUS_CONSTANT_ALPHA */
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
function message(parameter, value) {
|
|
3072
|
+
return `Illegal parameter ${value} for ${parameter}`;
|
|
3073
|
+
}
|
|
3074
|
+
function map(parameter, value, valueMap) {
|
|
3075
|
+
if (!(value in valueMap)) {
|
|
3076
|
+
throw new Error(message(parameter, value));
|
|
3077
|
+
}
|
|
3078
|
+
return valueMap[value];
|
|
3439
3079
|
}
|
|
3440
|
-
function
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
case 36057 /* FRAMEBUFFER_INCOMPLETE_DIMENSIONS */:
|
|
3449
|
-
return "Height/width mismatch";
|
|
3450
|
-
case 36061 /* FRAMEBUFFER_UNSUPPORTED */:
|
|
3451
|
-
return "Unsupported or split attachments";
|
|
3452
|
-
case 36182 /* FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */:
|
|
3453
|
-
return "Samples mismatch";
|
|
3454
|
-
default:
|
|
3455
|
-
return `${status}`;
|
|
3080
|
+
function mapBoolean(parameter, value) {
|
|
3081
|
+
return value;
|
|
3082
|
+
}
|
|
3083
|
+
function isObjectEmpty2(obj) {
|
|
3084
|
+
let isEmpty = true;
|
|
3085
|
+
for (const key in obj) {
|
|
3086
|
+
isEmpty = false;
|
|
3087
|
+
break;
|
|
3456
3088
|
}
|
|
3089
|
+
return isEmpty;
|
|
3457
3090
|
}
|
|
3458
3091
|
|
|
3459
|
-
// src/adapter/
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
presentationSize;
|
|
3465
|
-
_framebuffer = null;
|
|
3466
|
-
constructor(device, props) {
|
|
3467
|
-
super(props);
|
|
3468
|
-
this.device = device;
|
|
3469
|
-
this.presentationSize = [-1, -1];
|
|
3470
|
-
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
3471
|
-
this.update();
|
|
3092
|
+
// src/adapter/converters/sampler-parameters.ts
|
|
3093
|
+
function convertSamplerParametersToWebGL(props) {
|
|
3094
|
+
const params = {};
|
|
3095
|
+
if (props.addressModeU) {
|
|
3096
|
+
params[10242 /* TEXTURE_WRAP_S */] = convertAddressMode(props.addressModeU);
|
|
3472
3097
|
}
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
|
|
3476
|
-
return this._framebuffer;
|
|
3098
|
+
if (props.addressModeV) {
|
|
3099
|
+
params[10243 /* TEXTURE_WRAP_T */] = convertAddressMode(props.addressModeV);
|
|
3477
3100
|
}
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
const size = this.getPixelSize();
|
|
3481
|
-
const sizeChanged = size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
|
|
3482
|
-
if (sizeChanged) {
|
|
3483
|
-
this.presentationSize = size;
|
|
3484
|
-
this.resize();
|
|
3485
|
-
}
|
|
3101
|
+
if (props.addressModeW) {
|
|
3102
|
+
params[32882 /* TEXTURE_WRAP_R */] = convertAddressMode(props.addressModeW);
|
|
3486
3103
|
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
*
|
|
3490
|
-
* Can match the canvas CSS size, and optionally also consider devicePixelRatio
|
|
3491
|
-
* Can be called every frame
|
|
3492
|
-
*
|
|
3493
|
-
* Regardless of size, the drawing buffer will always be scaled to the viewport, but
|
|
3494
|
-
* for best visual results, usually set to either:
|
|
3495
|
-
* canvas CSS width x canvas CSS height
|
|
3496
|
-
* canvas CSS width * devicePixelRatio x canvas CSS height * devicePixelRatio
|
|
3497
|
-
* See http://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
|
|
3498
|
-
*/
|
|
3499
|
-
resize(options) {
|
|
3500
|
-
if (!this.device.gl)
|
|
3501
|
-
return;
|
|
3502
|
-
if (this.canvas) {
|
|
3503
|
-
const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
|
|
3504
|
-
this.setDevicePixelRatio(devicePixelRatio, options);
|
|
3505
|
-
return;
|
|
3506
|
-
}
|
|
3104
|
+
if (props.magFilter) {
|
|
3105
|
+
params[10240 /* TEXTURE_MAG_FILTER */] = convertMaxFilterMode(props.magFilter);
|
|
3507
3106
|
}
|
|
3508
|
-
|
|
3107
|
+
if (props.minFilter || props.mipmapFilter) {
|
|
3108
|
+
params[10241 /* TEXTURE_MIN_FILTER */] = convertMinFilterMode(
|
|
3109
|
+
props.minFilter || "linear",
|
|
3110
|
+
props.mipmapFilter
|
|
3111
|
+
);
|
|
3509
3112
|
}
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
// src/context/debug/spector.ts
|
|
3513
|
-
var import_core11 = __toESM(require_core(), 1);
|
|
3514
|
-
|
|
3515
|
-
// src/utils/load-script.ts
|
|
3516
|
-
async function loadScript(scriptUrl, scriptId) {
|
|
3517
|
-
const head = document.getElementsByTagName("head")[0];
|
|
3518
|
-
if (!head) {
|
|
3519
|
-
throw new Error("loadScript");
|
|
3113
|
+
if (props.lodMinClamp !== void 0) {
|
|
3114
|
+
params[33082 /* TEXTURE_MIN_LOD */] = props.lodMinClamp;
|
|
3520
3115
|
}
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
if (
|
|
3525
|
-
|
|
3116
|
+
if (props.lodMaxClamp !== void 0) {
|
|
3117
|
+
params[33083 /* TEXTURE_MAX_LOD */] = props.lodMaxClamp;
|
|
3118
|
+
}
|
|
3119
|
+
if (props.type === "comparison-sampler") {
|
|
3120
|
+
params[34892 /* TEXTURE_COMPARE_MODE */] = 34894 /* COMPARE_REF_TO_TEXTURE */;
|
|
3121
|
+
}
|
|
3122
|
+
if (props.compare) {
|
|
3123
|
+
params[34893 /* TEXTURE_COMPARE_FUNC */] = convertCompareFunction("compare", props.compare);
|
|
3124
|
+
}
|
|
3125
|
+
if (props.maxAnisotropy) {
|
|
3126
|
+
params[34046 /* TEXTURE_MAX_ANISOTROPY_EXT */] = props.maxAnisotropy;
|
|
3127
|
+
}
|
|
3128
|
+
return params;
|
|
3129
|
+
}
|
|
3130
|
+
function convertAddressMode(addressMode) {
|
|
3131
|
+
switch (addressMode) {
|
|
3132
|
+
case "clamp-to-edge":
|
|
3133
|
+
return 33071 /* CLAMP_TO_EDGE */;
|
|
3134
|
+
case "repeat":
|
|
3135
|
+
return 10497 /* REPEAT */;
|
|
3136
|
+
case "mirror-repeat":
|
|
3137
|
+
return 33648 /* MIRRORED_REPEAT */;
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
function convertMaxFilterMode(maxFilter) {
|
|
3141
|
+
switch (maxFilter) {
|
|
3142
|
+
case "nearest":
|
|
3143
|
+
return 9728 /* NEAREST */;
|
|
3144
|
+
case "linear":
|
|
3145
|
+
return 9729 /* LINEAR */;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
function convertMinFilterMode(minFilter, mipmapFilter) {
|
|
3149
|
+
if (!mipmapFilter) {
|
|
3150
|
+
return convertMaxFilterMode(minFilter);
|
|
3151
|
+
}
|
|
3152
|
+
switch (minFilter) {
|
|
3153
|
+
case "nearest":
|
|
3154
|
+
return mipmapFilter === "nearest" ? 9984 /* NEAREST_MIPMAP_NEAREST */ : 9986 /* NEAREST_MIPMAP_LINEAR */;
|
|
3155
|
+
case "linear":
|
|
3156
|
+
return mipmapFilter === "nearest" ? 9985 /* LINEAR_MIPMAP_NEAREST */ : 9987 /* LINEAR_MIPMAP_LINEAR */;
|
|
3526
3157
|
}
|
|
3527
|
-
return new Promise((resolve, reject) => {
|
|
3528
|
-
script.onload = resolve;
|
|
3529
|
-
script.onerror = (error) => reject(new Error(`Unable to load script '${scriptUrl}': ${error}`));
|
|
3530
|
-
head.appendChild(script);
|
|
3531
|
-
});
|
|
3532
3158
|
}
|
|
3533
3159
|
|
|
3534
|
-
// src/
|
|
3535
|
-
var
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
} catch (error) {
|
|
3551
|
-
import_core11.log.warn(String(error));
|
|
3160
|
+
// src/adapter/resources/webgl-sampler.ts
|
|
3161
|
+
var WEBGLSampler = class extends import_core11.Sampler {
|
|
3162
|
+
device;
|
|
3163
|
+
handle;
|
|
3164
|
+
parameters;
|
|
3165
|
+
constructor(device, props) {
|
|
3166
|
+
super(device, props);
|
|
3167
|
+
this.device = device;
|
|
3168
|
+
this.parameters = convertSamplerParametersToWebGL(props);
|
|
3169
|
+
this.handle = this.handle || this.device.gl.createSampler();
|
|
3170
|
+
this._setSamplerParameters(this.parameters);
|
|
3171
|
+
}
|
|
3172
|
+
destroy() {
|
|
3173
|
+
if (this.handle) {
|
|
3174
|
+
this.device.gl.deleteSampler(this.handle);
|
|
3175
|
+
this.handle = void 0;
|
|
3552
3176
|
}
|
|
3553
3177
|
}
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
props = { ...DEFAULT_SPECTOR_PROPS, ...props };
|
|
3557
|
-
if (!props.debugWithSpectorJS) {
|
|
3558
|
-
return null;
|
|
3178
|
+
toString() {
|
|
3179
|
+
return `Sampler(${this.id},${JSON.stringify(this.props)})`;
|
|
3559
3180
|
}
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
const
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3181
|
+
/** Set sampler parameters on the sampler */
|
|
3182
|
+
_setSamplerParameters(parameters) {
|
|
3183
|
+
for (const [pname, value] of Object.entries(parameters)) {
|
|
3184
|
+
const param = Number(pname);
|
|
3185
|
+
switch (param) {
|
|
3186
|
+
case 33082 /* TEXTURE_MIN_LOD */:
|
|
3187
|
+
case 33083 /* TEXTURE_MAX_LOD */:
|
|
3188
|
+
this.device.gl.samplerParameterf(this.handle, param, value);
|
|
3189
|
+
break;
|
|
3190
|
+
default:
|
|
3191
|
+
this.device.gl.samplerParameteri(this.handle, param, value);
|
|
3192
|
+
break;
|
|
3193
|
+
}
|
|
3566
3194
|
}
|
|
3567
3195
|
}
|
|
3568
|
-
|
|
3569
|
-
|
|
3196
|
+
};
|
|
3197
|
+
|
|
3198
|
+
// src/adapter/resources/webgl-texture.ts
|
|
3199
|
+
var import_core14 = __toESM(require_core(), 1);
|
|
3200
|
+
|
|
3201
|
+
// src/context/state-tracker/with-parameters.ts
|
|
3202
|
+
function withGLParameters(gl, parameters, func) {
|
|
3203
|
+
if (isObjectEmpty3(parameters)) {
|
|
3204
|
+
return func(gl);
|
|
3570
3205
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
}
|
|
3206
|
+
const { nocatch = true } = parameters;
|
|
3207
|
+
const webglState = WebGLStateTracker.get(gl);
|
|
3208
|
+
webglState.push();
|
|
3209
|
+
setGLParameters(gl, parameters);
|
|
3210
|
+
let value;
|
|
3211
|
+
if (nocatch) {
|
|
3212
|
+
value = func(gl);
|
|
3213
|
+
webglState.pop();
|
|
3214
|
+
} else {
|
|
3215
|
+
try {
|
|
3216
|
+
value = func(gl);
|
|
3217
|
+
} finally {
|
|
3218
|
+
webglState.pop();
|
|
3219
|
+
}
|
|
3583
3220
|
}
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
|
|
3590
|
-
import_core11.log.info("Spector capture stopped after 2 seconds")();
|
|
3591
|
-
spector?.stopCapture();
|
|
3592
|
-
});
|
|
3221
|
+
return value;
|
|
3222
|
+
}
|
|
3223
|
+
function isObjectEmpty3(object) {
|
|
3224
|
+
for (const key in object) {
|
|
3225
|
+
return false;
|
|
3593
3226
|
}
|
|
3594
|
-
return
|
|
3227
|
+
return true;
|
|
3595
3228
|
}
|
|
3596
3229
|
|
|
3597
|
-
// src/
|
|
3230
|
+
// src/adapter/resources/webgl-texture-view.ts
|
|
3598
3231
|
var import_core12 = __toESM(require_core(), 1);
|
|
3232
|
+
var WEBGLTextureView = class extends import_core12.TextureView {
|
|
3233
|
+
device;
|
|
3234
|
+
gl;
|
|
3235
|
+
handle;
|
|
3236
|
+
// Does not have a WebGL representation
|
|
3237
|
+
texture;
|
|
3238
|
+
constructor(device, props) {
|
|
3239
|
+
super(device, { ...import_core12.Texture.defaultProps, ...props });
|
|
3240
|
+
this.device = device;
|
|
3241
|
+
this.gl = this.device.gl;
|
|
3242
|
+
this.handle = null;
|
|
3243
|
+
this.texture = props.texture;
|
|
3244
|
+
}
|
|
3245
|
+
};
|
|
3599
3246
|
|
|
3600
|
-
//
|
|
3601
|
-
var
|
|
3602
|
-
var process_ = globalThis.process || {};
|
|
3603
|
-
var console_ = globalThis.console;
|
|
3604
|
-
var navigator_ = globalThis.navigator || {};
|
|
3247
|
+
// src/adapter/helpers/webgl-texture-utils.ts
|
|
3248
|
+
var import_core13 = __toESM(require_core(), 1);
|
|
3605
3249
|
|
|
3606
|
-
//
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3250
|
+
// src/adapter/helpers/typed-array-utils.ts
|
|
3251
|
+
var ERR_TYPE_DEDUCTION = "Failed to deduce GL constant from typed array";
|
|
3252
|
+
function getGLTypeFromTypedArray(arrayOrType) {
|
|
3253
|
+
const type = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
|
|
3254
|
+
switch (type) {
|
|
3255
|
+
case Float32Array:
|
|
3256
|
+
return 5126 /* FLOAT */;
|
|
3257
|
+
case Uint16Array:
|
|
3258
|
+
return 5123 /* UNSIGNED_SHORT */;
|
|
3259
|
+
case Uint32Array:
|
|
3260
|
+
return 5125 /* UNSIGNED_INT */;
|
|
3261
|
+
case Uint8Array:
|
|
3262
|
+
return 5121 /* UNSIGNED_BYTE */;
|
|
3263
|
+
case Uint8ClampedArray:
|
|
3264
|
+
return 5121 /* UNSIGNED_BYTE */;
|
|
3265
|
+
case Int8Array:
|
|
3266
|
+
return 5120 /* BYTE */;
|
|
3267
|
+
case Int16Array:
|
|
3268
|
+
return 5122 /* SHORT */;
|
|
3269
|
+
case Int32Array:
|
|
3270
|
+
return 5124 /* INT */;
|
|
3271
|
+
default:
|
|
3272
|
+
throw new Error(ERR_TYPE_DEDUCTION);
|
|
3613
3273
|
}
|
|
3614
|
-
const realUserAgent = typeof navigator !== "undefined" && navigator.userAgent;
|
|
3615
|
-
const userAgent = mockUserAgent || realUserAgent;
|
|
3616
|
-
return Boolean(userAgent && userAgent.indexOf("Electron") >= 0);
|
|
3617
3274
|
}
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3275
|
+
function getTypedArrayFromGLType(glType, options) {
|
|
3276
|
+
const { clamped = true } = options || {};
|
|
3277
|
+
switch (glType) {
|
|
3278
|
+
case 5126 /* FLOAT */:
|
|
3279
|
+
return Float32Array;
|
|
3280
|
+
case 5123 /* UNSIGNED_SHORT */:
|
|
3281
|
+
case 33635 /* UNSIGNED_SHORT_5_6_5 */:
|
|
3282
|
+
case 32819 /* UNSIGNED_SHORT_4_4_4_4 */:
|
|
3283
|
+
case 32820 /* UNSIGNED_SHORT_5_5_5_1 */:
|
|
3284
|
+
return Uint16Array;
|
|
3285
|
+
case 5125 /* UNSIGNED_INT */:
|
|
3286
|
+
return Uint32Array;
|
|
3287
|
+
case 5121 /* UNSIGNED_BYTE */:
|
|
3288
|
+
return clamped ? Uint8ClampedArray : Uint8Array;
|
|
3289
|
+
case 5120 /* BYTE */:
|
|
3290
|
+
return Int8Array;
|
|
3291
|
+
case 5122 /* SHORT */:
|
|
3292
|
+
return Int16Array;
|
|
3293
|
+
case 5124 /* INT */:
|
|
3294
|
+
return Int32Array;
|
|
3295
|
+
default:
|
|
3296
|
+
throw new Error("Failed to deduce typed array type from GL constant");
|
|
3297
|
+
}
|
|
3626
3298
|
}
|
|
3627
3299
|
|
|
3628
|
-
//
|
|
3629
|
-
function
|
|
3630
|
-
|
|
3631
|
-
|
|
3300
|
+
// src/adapter/helpers/format-utils.ts
|
|
3301
|
+
function glFormatToComponents(format) {
|
|
3302
|
+
switch (format) {
|
|
3303
|
+
case 6406 /* ALPHA */:
|
|
3304
|
+
case 33326 /* R32F */:
|
|
3305
|
+
case 6403 /* RED */:
|
|
3306
|
+
return 1;
|
|
3307
|
+
case 33328 /* RG32F */:
|
|
3308
|
+
case 33319 /* RG */:
|
|
3309
|
+
return 2;
|
|
3310
|
+
case 6407 /* RGB */:
|
|
3311
|
+
case 34837 /* RGB32F */:
|
|
3312
|
+
return 3;
|
|
3313
|
+
case 6408 /* RGBA */:
|
|
3314
|
+
case 34836 /* RGBA32F */:
|
|
3315
|
+
return 4;
|
|
3316
|
+
default:
|
|
3317
|
+
return 0;
|
|
3632
3318
|
}
|
|
3633
|
-
|
|
3634
|
-
|
|
3319
|
+
}
|
|
3320
|
+
function glTypeToBytes(type) {
|
|
3321
|
+
switch (type) {
|
|
3322
|
+
case 5121 /* UNSIGNED_BYTE */:
|
|
3323
|
+
return 1;
|
|
3324
|
+
case 33635 /* UNSIGNED_SHORT_5_6_5 */:
|
|
3325
|
+
case 32819 /* UNSIGNED_SHORT_4_4_4_4 */:
|
|
3326
|
+
case 32820 /* UNSIGNED_SHORT_5_5_5_1 */:
|
|
3327
|
+
return 2;
|
|
3328
|
+
case 5126 /* FLOAT */:
|
|
3329
|
+
return 4;
|
|
3330
|
+
default:
|
|
3331
|
+
return 0;
|
|
3635
3332
|
}
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
// src/adapter/helpers/webgl-texture-utils.ts
|
|
3336
|
+
function initializeTextureStorage(gl, levels, options) {
|
|
3337
|
+
const { dimension, width, height, depth = 0 } = options;
|
|
3338
|
+
const { glInternalFormat } = options;
|
|
3339
|
+
const glTarget = options.glTarget;
|
|
3340
|
+
switch (dimension) {
|
|
3341
|
+
case "2d-array":
|
|
3342
|
+
case "3d":
|
|
3343
|
+
gl.texStorage3D(glTarget, levels, glInternalFormat, width, height, depth);
|
|
3344
|
+
break;
|
|
3345
|
+
default:
|
|
3346
|
+
gl.texStorage2D(glTarget, levels, glInternalFormat, width, height);
|
|
3639
3347
|
}
|
|
3640
|
-
|
|
3641
|
-
|
|
3348
|
+
}
|
|
3349
|
+
function copyExternalImageToMipLevel(gl, handle, image, options) {
|
|
3350
|
+
const { width, height } = options;
|
|
3351
|
+
const { dimension, depth = 0, mipLevel = 0 } = options;
|
|
3352
|
+
const { x = 0, y = 0, z = 0 } = options;
|
|
3353
|
+
const { glFormat, glType } = options;
|
|
3354
|
+
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
3355
|
+
switch (dimension) {
|
|
3356
|
+
case "2d-array":
|
|
3357
|
+
case "3d":
|
|
3358
|
+
gl.bindTexture(glTarget, handle);
|
|
3359
|
+
gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
|
|
3360
|
+
gl.bindTexture(glTarget, null);
|
|
3361
|
+
break;
|
|
3362
|
+
case "2d":
|
|
3363
|
+
case "cube":
|
|
3364
|
+
gl.bindTexture(glTarget, handle);
|
|
3365
|
+
gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
|
|
3366
|
+
gl.bindTexture(glTarget, null);
|
|
3367
|
+
break;
|
|
3368
|
+
default:
|
|
3369
|
+
throw new Error(dimension);
|
|
3642
3370
|
}
|
|
3643
|
-
|
|
3644
|
-
|
|
3371
|
+
}
|
|
3372
|
+
function copyCPUDataToMipLevel(gl, typedArray, options) {
|
|
3373
|
+
const { dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0 } = options;
|
|
3374
|
+
const { x = 0, y = 0, z = 0 } = options;
|
|
3375
|
+
const { glFormat, glType, compressed } = options;
|
|
3376
|
+
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
3377
|
+
switch (dimension) {
|
|
3378
|
+
case "2d-array":
|
|
3379
|
+
case "3d":
|
|
3380
|
+
if (compressed) {
|
|
3381
|
+
gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
|
|
3382
|
+
} else {
|
|
3383
|
+
gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
|
|
3384
|
+
}
|
|
3385
|
+
break;
|
|
3386
|
+
case "2d":
|
|
3387
|
+
case "cube":
|
|
3388
|
+
if (compressed) {
|
|
3389
|
+
gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
|
|
3390
|
+
} else {
|
|
3391
|
+
gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
|
|
3392
|
+
}
|
|
3393
|
+
break;
|
|
3394
|
+
default:
|
|
3395
|
+
throw new Error(dimension);
|
|
3645
3396
|
}
|
|
3646
|
-
|
|
3647
|
-
|
|
3397
|
+
}
|
|
3398
|
+
function getWebGLTextureTarget(dimension) {
|
|
3399
|
+
switch (dimension) {
|
|
3400
|
+
case "1d":
|
|
3401
|
+
break;
|
|
3402
|
+
case "2d":
|
|
3403
|
+
return 3553 /* TEXTURE_2D */;
|
|
3404
|
+
case "3d":
|
|
3405
|
+
return 32879 /* TEXTURE_3D */;
|
|
3406
|
+
case "cube":
|
|
3407
|
+
return 34067 /* TEXTURE_CUBE_MAP */;
|
|
3408
|
+
case "2d-array":
|
|
3409
|
+
return 35866 /* TEXTURE_2D_ARRAY */;
|
|
3410
|
+
case "cube-array":
|
|
3411
|
+
break;
|
|
3648
3412
|
}
|
|
3649
|
-
|
|
3413
|
+
throw new Error(dimension);
|
|
3650
3414
|
}
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
var WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
|
|
3654
|
-
function getWebGLContextData(gl) {
|
|
3655
|
-
gl.luma = gl.luma || {};
|
|
3656
|
-
return gl.luma;
|
|
3415
|
+
function getWebGLCubeFaceTarget(glTarget, dimension, level) {
|
|
3416
|
+
return dimension === "cube" ? 34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ + level : glTarget;
|
|
3657
3417
|
}
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3418
|
+
function readPixelsToArray(source, options) {
|
|
3419
|
+
const {
|
|
3420
|
+
sourceX = 0,
|
|
3421
|
+
sourceY = 0,
|
|
3422
|
+
sourceAttachment = 36064 /* COLOR_ATTACHMENT0 */
|
|
3423
|
+
// TODO - support gl.readBuffer
|
|
3424
|
+
} = options || {};
|
|
3425
|
+
let {
|
|
3426
|
+
target = null,
|
|
3427
|
+
// following parameters are auto deduced if not provided
|
|
3428
|
+
sourceWidth,
|
|
3429
|
+
sourceHeight,
|
|
3430
|
+
sourceDepth,
|
|
3431
|
+
sourceFormat,
|
|
3432
|
+
sourceType
|
|
3433
|
+
} = options || {};
|
|
3434
|
+
const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
|
|
3435
|
+
const { gl, handle } = framebuffer;
|
|
3436
|
+
const attachment = sourceAttachment - 36064 /* COLOR_ATTACHMENT0 */;
|
|
3437
|
+
sourceWidth ||= framebuffer.width;
|
|
3438
|
+
sourceHeight ||= framebuffer.height;
|
|
3439
|
+
sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
|
|
3440
|
+
sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || 6408 /* RGBA */;
|
|
3441
|
+
sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || 5121 /* UNSIGNED_BYTE */;
|
|
3442
|
+
target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
|
|
3443
|
+
sourceType = sourceType || getGLTypeFromTypedArray(target);
|
|
3444
|
+
const prevHandle = gl.bindFramebuffer(36160 /* FRAMEBUFFER */, handle);
|
|
3445
|
+
gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
|
|
3446
|
+
gl.bindFramebuffer(36160 /* FRAMEBUFFER */, prevHandle || null);
|
|
3447
|
+
if (deleteFramebuffer) {
|
|
3448
|
+
framebuffer.destroy();
|
|
3663
3449
|
}
|
|
3450
|
+
return target;
|
|
3664
3451
|
}
|
|
3665
|
-
function
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
const
|
|
3678
|
-
|
|
3679
|
-
|
|
3452
|
+
function readPixelsToBuffer(source, options) {
|
|
3453
|
+
const {
|
|
3454
|
+
target,
|
|
3455
|
+
sourceX = 0,
|
|
3456
|
+
sourceY = 0,
|
|
3457
|
+
sourceFormat = 6408 /* RGBA */,
|
|
3458
|
+
targetByteOffset = 0
|
|
3459
|
+
} = options || {};
|
|
3460
|
+
let { sourceWidth, sourceHeight, sourceType } = options || {};
|
|
3461
|
+
const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
|
|
3462
|
+
sourceWidth = sourceWidth || framebuffer.width;
|
|
3463
|
+
sourceHeight = sourceHeight || framebuffer.height;
|
|
3464
|
+
const webglFramebuffer = framebuffer;
|
|
3465
|
+
sourceType = sourceType || 5121 /* UNSIGNED_BYTE */;
|
|
3466
|
+
let webglBufferTarget = target;
|
|
3467
|
+
if (!webglBufferTarget) {
|
|
3468
|
+
const components = glFormatToComponents(sourceFormat);
|
|
3469
|
+
const byteCount = glTypeToBytes(sourceType);
|
|
3470
|
+
const byteLength = targetByteOffset + sourceWidth * sourceHeight * components * byteCount;
|
|
3471
|
+
webglBufferTarget = webglFramebuffer.device.createBuffer({ byteLength });
|
|
3680
3472
|
}
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3473
|
+
const commandEncoder = source.device.createCommandEncoder();
|
|
3474
|
+
commandEncoder.copyTextureToBuffer({
|
|
3475
|
+
source,
|
|
3476
|
+
width: sourceWidth,
|
|
3477
|
+
height: sourceHeight,
|
|
3478
|
+
origin: [sourceX, sourceY],
|
|
3479
|
+
destination: webglBufferTarget,
|
|
3480
|
+
byteOffset: targetByteOffset
|
|
3481
|
+
});
|
|
3482
|
+
commandEncoder.destroy();
|
|
3483
|
+
if (deleteFramebuffer) {
|
|
3484
|
+
framebuffer.destroy();
|
|
3691
3485
|
}
|
|
3692
|
-
|
|
3486
|
+
return webglBufferTarget;
|
|
3487
|
+
}
|
|
3488
|
+
function getFramebuffer(source) {
|
|
3489
|
+
if (!(source instanceof import_core13.Framebuffer)) {
|
|
3490
|
+
return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
|
|
3693
3491
|
}
|
|
3694
|
-
|
|
3695
|
-
Object.setPrototypeOf(WebGLDebugContext, glDebug);
|
|
3696
|
-
const debugContext = Object.create(WebGLDebugContext);
|
|
3697
|
-
data.realContext = gl;
|
|
3698
|
-
data.debugContext = debugContext;
|
|
3699
|
-
debugContext.debug = true;
|
|
3700
|
-
return debugContext;
|
|
3492
|
+
return { framebuffer: source, deleteFramebuffer: false };
|
|
3701
3493
|
}
|
|
3702
|
-
function
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3494
|
+
function toFramebuffer(texture, props) {
|
|
3495
|
+
const { device, width, height, id } = texture;
|
|
3496
|
+
const framebuffer = device.createFramebuffer({
|
|
3497
|
+
...props,
|
|
3498
|
+
id: `framebuffer-for-${id}`,
|
|
3499
|
+
width,
|
|
3500
|
+
height,
|
|
3501
|
+
colorAttachments: [texture]
|
|
3502
|
+
});
|
|
3503
|
+
return framebuffer;
|
|
3707
3504
|
}
|
|
3708
|
-
function
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
|
|
3712
|
-
const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
|
|
3713
|
-
import_core12.log.error(message2)();
|
|
3714
|
-
debugger;
|
|
3715
|
-
if (props.throwOnError) {
|
|
3716
|
-
throw new Error(message2);
|
|
3505
|
+
function getPixelArray(pixelArray, type, format, width, height, depth) {
|
|
3506
|
+
if (pixelArray) {
|
|
3507
|
+
return pixelArray;
|
|
3717
3508
|
}
|
|
3509
|
+
type = type || 5121 /* UNSIGNED_BYTE */;
|
|
3510
|
+
const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
|
|
3511
|
+
const components = glFormatToComponents(format);
|
|
3512
|
+
return new ArrayType(width * height * components);
|
|
3718
3513
|
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
debugger;
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
for (const arg of functionArgs) {
|
|
3735
|
-
if (arg === void 0) {
|
|
3736
|
-
functionString = functionString || getFunctionString(functionName, functionArgs);
|
|
3737
|
-
if (props.throwOnError) {
|
|
3738
|
-
throw new Error(`Undefined argument: ${functionString}`);
|
|
3739
|
-
} else {
|
|
3740
|
-
import_core12.log.error(`Undefined argument: ${functionString}`)();
|
|
3741
|
-
debugger;
|
|
3514
|
+
|
|
3515
|
+
// src/adapter/resources/webgl-texture.ts
|
|
3516
|
+
function normalizeTextureData(data, options) {
|
|
3517
|
+
let lodArray;
|
|
3518
|
+
if (ArrayBuffer.isView(data)) {
|
|
3519
|
+
lodArray = [
|
|
3520
|
+
{
|
|
3521
|
+
// ts-expect-error does data really need to be Uint8ClampedArray?
|
|
3522
|
+
data,
|
|
3523
|
+
width: options.width,
|
|
3524
|
+
height: options.height
|
|
3525
|
+
// depth: options.depth
|
|
3742
3526
|
}
|
|
3743
|
-
|
|
3527
|
+
];
|
|
3528
|
+
} else if (!Array.isArray(data)) {
|
|
3529
|
+
lodArray = [data];
|
|
3530
|
+
} else {
|
|
3531
|
+
lodArray = data;
|
|
3744
3532
|
}
|
|
3533
|
+
return lodArray;
|
|
3745
3534
|
}
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
var uidCounters = {};
|
|
3749
|
-
function uid(id = "id") {
|
|
3750
|
-
uidCounters[id] = uidCounters[id] || 1;
|
|
3751
|
-
const count = uidCounters[id]++;
|
|
3752
|
-
return `${id}-${count}`;
|
|
3753
|
-
}
|
|
3754
|
-
|
|
3755
|
-
// src/adapter/resources/webgl-buffer.ts
|
|
3756
|
-
var import_core13 = __toESM(require_core(), 1);
|
|
3757
|
-
var WEBGLBuffer = class extends import_core13.Buffer {
|
|
3535
|
+
var WEBGLTexture = class extends import_core14.Texture {
|
|
3536
|
+
MAX_ATTRIBUTES;
|
|
3758
3537
|
device;
|
|
3759
3538
|
gl;
|
|
3760
3539
|
handle;
|
|
3761
|
-
|
|
3540
|
+
sampler = void 0;
|
|
3541
|
+
// TODO - currently unused in WebGL. Create dummy sampler?
|
|
3542
|
+
view = void 0;
|
|
3543
|
+
// TODO - currently unused in WebGL. Create dummy view?
|
|
3544
|
+
mipmaps = false;
|
|
3545
|
+
/**
|
|
3546
|
+
* @note `target` cannot be modified by bind:
|
|
3547
|
+
* textures are special because when you first bind them to a target,
|
|
3548
|
+
* When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
|
|
3549
|
+
* And it will always be a 2D texture; this state cannot be changed ever.
|
|
3550
|
+
* A texture that was first bound as a GL_TEXTURE_2D, must always be bound as a GL_TEXTURE_2D;
|
|
3551
|
+
* attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
|
|
3552
|
+
*/
|
|
3762
3553
|
glTarget;
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3554
|
+
// Texture type
|
|
3555
|
+
/** The WebGL format - essentially channel structure */
|
|
3556
|
+
glFormat;
|
|
3557
|
+
/** The WebGL data format - the type of each channel */
|
|
3558
|
+
glType;
|
|
3559
|
+
/** The WebGL constant corresponding to the WebGPU style constant in format */
|
|
3560
|
+
glInternalFormat;
|
|
3561
|
+
/** Whether the internal format is compressed */
|
|
3562
|
+
compressed;
|
|
3563
|
+
// data;
|
|
3564
|
+
// inherited props
|
|
3565
|
+
// dimension: ...
|
|
3566
|
+
// format: GLTextureTarget;
|
|
3567
|
+
// width: number = undefined;
|
|
3568
|
+
// height: number = undefined;
|
|
3569
|
+
// depth: number = undefined;
|
|
3570
|
+
// state
|
|
3571
|
+
/** Texture binding slot */
|
|
3572
|
+
textureUnit = 0;
|
|
3573
|
+
/** For automatically updating video */
|
|
3574
|
+
_video = null;
|
|
3575
|
+
constructor(device, props) {
|
|
3576
|
+
props = import_core14.Texture._fixProps(props);
|
|
3577
|
+
super(device, { ...import_core14.Texture.defaultProps, ...props, data: void 0 });
|
|
3773
3578
|
this.device = device;
|
|
3774
3579
|
this.gl = this.device.gl;
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
this.
|
|
3779
|
-
this.
|
|
3780
|
-
this.
|
|
3781
|
-
if (props.data
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
this.
|
|
3580
|
+
this.glTarget = getWebGLTextureTarget(this.props.dimension);
|
|
3581
|
+
const format = getTextureFormatWebGL(this.props.format);
|
|
3582
|
+
this.glInternalFormat = format.internalFormat;
|
|
3583
|
+
this.glFormat = format.format;
|
|
3584
|
+
this.glType = format.type;
|
|
3585
|
+
this.compressed = format.compressed;
|
|
3586
|
+
if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
|
|
3587
|
+
props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
|
|
3588
|
+
const video = props.data;
|
|
3589
|
+
this._video = null;
|
|
3590
|
+
video.addEventListener("loadeddata", () => this.initialize(props));
|
|
3591
|
+
}
|
|
3592
|
+
this.initialize({ ...this.props, data: props.data });
|
|
3593
|
+
Object.seal(this);
|
|
3594
|
+
}
|
|
3595
|
+
/**
|
|
3596
|
+
* Initialize texture with supplied props
|
|
3597
|
+
*/
|
|
3598
|
+
// eslint-disable-next-line max-statements
|
|
3599
|
+
initialize(props = {}) {
|
|
3600
|
+
this.handle = this.props.handle || this.gl.createTexture();
|
|
3601
|
+
this.device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
|
|
3602
|
+
const data = props.data;
|
|
3603
|
+
let { width, height } = props;
|
|
3604
|
+
if (!width || !height) {
|
|
3605
|
+
const textureSize = import_core14.Texture.getTextureDataSize(data);
|
|
3606
|
+
width = textureSize?.width || 1;
|
|
3607
|
+
height = textureSize?.height || 1;
|
|
3608
|
+
}
|
|
3609
|
+
this.width = width;
|
|
3610
|
+
this.height = height;
|
|
3611
|
+
this.depth = props.depth;
|
|
3612
|
+
this.setSampler(props.sampler);
|
|
3613
|
+
this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
|
|
3614
|
+
this.bind();
|
|
3615
|
+
if (!this.props.data) {
|
|
3616
|
+
initializeTextureStorage(this.gl, this.mipLevels, this);
|
|
3785
3617
|
}
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3618
|
+
if (props.data) {
|
|
3619
|
+
switch (props.dimension) {
|
|
3620
|
+
case "1d":
|
|
3621
|
+
this.setTexture1DData(props.data);
|
|
3622
|
+
break;
|
|
3623
|
+
case "2d":
|
|
3624
|
+
this.setTexture2DData(props.data);
|
|
3625
|
+
break;
|
|
3626
|
+
case "3d":
|
|
3627
|
+
this.setTexture3DData(props.data);
|
|
3628
|
+
break;
|
|
3629
|
+
case "cube":
|
|
3630
|
+
this.setTextureCubeData(props.data);
|
|
3631
|
+
break;
|
|
3632
|
+
case "2d-array":
|
|
3633
|
+
this.setTextureArrayData(props.data);
|
|
3634
|
+
break;
|
|
3635
|
+
case "cube-array":
|
|
3636
|
+
this.setTextureCubeArrayData(props.data);
|
|
3637
|
+
break;
|
|
3638
|
+
default:
|
|
3639
|
+
throw new Error(props.dimension);
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
this.mipmaps = Boolean(props.mipmaps);
|
|
3643
|
+
if (this.mipmaps) {
|
|
3644
|
+
this.generateMipmap();
|
|
3805
3645
|
}
|
|
3806
|
-
const glTarget = this.glTarget;
|
|
3807
|
-
this.gl.bindBuffer(glTarget, this.handle);
|
|
3808
|
-
this.gl.bufferData(glTarget, data, this.glUsage);
|
|
3809
|
-
this.gl.bindBuffer(glTarget, null);
|
|
3810
|
-
this.bytesUsed = byteLength;
|
|
3811
|
-
this.byteLength = byteLength;
|
|
3812
|
-
this._setDebugData(null, 0, byteLength);
|
|
3813
|
-
this.trackAllocatedMemory(byteLength);
|
|
3814
|
-
return this;
|
|
3815
3646
|
}
|
|
3647
|
+
/*
|
|
3648
|
+
initializeCube(props?: TextureProps): void {
|
|
3649
|
+
const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
|
|
3650
|
+
|
|
3651
|
+
// Store props for accessors
|
|
3652
|
+
// this.props = props;
|
|
3653
|
+
|
|
3654
|
+
// @ts-expect-error
|
|
3655
|
+
this.setCubeMapData(props).then(() => {
|
|
3656
|
+
// TODO - should genMipmap() be called on the cubemap or on the faces?
|
|
3657
|
+
// TODO - without generateMipmap() cube textures do not work at all!!! Why?
|
|
3658
|
+
if (mipmaps) {
|
|
3659
|
+
this.generateMipmap(props);
|
|
3660
|
+
}
|
|
3661
|
+
|
|
3662
|
+
this.setSampler(props.sampler);
|
|
3663
|
+
|
|
3664
|
+
// v8 compatibility?
|
|
3665
|
+
// const {parameters = {} as Record<GL, any>} = props;
|
|
3666
|
+
// this._setSamplerParameters(parameters);
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3669
|
+
*/
|
|
3816
3670
|
destroy() {
|
|
3817
|
-
if (
|
|
3671
|
+
if (this.handle) {
|
|
3672
|
+
this.gl.deleteTexture(this.handle);
|
|
3818
3673
|
this.removeStats();
|
|
3819
|
-
this.trackDeallocatedMemory();
|
|
3820
|
-
this.gl.deleteBuffer(this.handle);
|
|
3674
|
+
this.trackDeallocatedMemory("Texture");
|
|
3821
3675
|
this.destroyed = true;
|
|
3822
|
-
this.handle = null;
|
|
3823
|
-
}
|
|
3824
|
-
}
|
|
3825
|
-
write(data, byteOffset = 0) {
|
|
3826
|
-
const srcOffset = 0;
|
|
3827
|
-
const byteLength = void 0;
|
|
3828
|
-
const glTarget = 36663 /* COPY_WRITE_BUFFER */;
|
|
3829
|
-
this.gl.bindBuffer(glTarget, this.handle);
|
|
3830
|
-
if (srcOffset !== 0 || byteLength !== void 0) {
|
|
3831
|
-
this.gl.bufferSubData(glTarget, byteOffset, data, srcOffset, byteLength);
|
|
3832
|
-
} else {
|
|
3833
|
-
this.gl.bufferSubData(glTarget, byteOffset, data);
|
|
3834
3676
|
}
|
|
3835
|
-
this.gl.bindBuffer(glTarget, null);
|
|
3836
|
-
this._setDebugData(data, byteOffset, data.byteLength);
|
|
3837
|
-
}
|
|
3838
|
-
/** Asynchronously read data from the buffer */
|
|
3839
|
-
async readAsync(byteOffset = 0, byteLength) {
|
|
3840
|
-
return this.readSyncWebGL(byteOffset, byteLength);
|
|
3841
3677
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
byteLength = byteLength ?? this.byteLength - byteOffset;
|
|
3845
|
-
const data = new Uint8Array(byteLength);
|
|
3846
|
-
const dstOffset = 0;
|
|
3847
|
-
this.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, this.handle);
|
|
3848
|
-
this.gl.getBufferSubData(36662 /* COPY_READ_BUFFER */, byteOffset, data, dstOffset, byteLength);
|
|
3849
|
-
this.gl.bindBuffer(36662 /* COPY_READ_BUFFER */, null);
|
|
3850
|
-
this._setDebugData(data, byteOffset, byteLength);
|
|
3851
|
-
return data;
|
|
3678
|
+
toString() {
|
|
3679
|
+
return `Texture(${this.id},${this.width}x${this.height})`;
|
|
3852
3680
|
}
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
if (usage & import_core13.Buffer.INDEX) {
|
|
3856
|
-
return 34963 /* ELEMENT_ARRAY_BUFFER */;
|
|
3681
|
+
createView(props) {
|
|
3682
|
+
return new WEBGLTextureView(this.device, { ...props, texture: this });
|
|
3857
3683
|
}
|
|
3858
|
-
|
|
3859
|
-
|
|
3684
|
+
setSampler(sampler = {}) {
|
|
3685
|
+
let samplerProps;
|
|
3686
|
+
if (sampler instanceof WEBGLSampler) {
|
|
3687
|
+
this.sampler = sampler;
|
|
3688
|
+
samplerProps = sampler.props;
|
|
3689
|
+
} else {
|
|
3690
|
+
this.sampler = new WEBGLSampler(this.device, sampler);
|
|
3691
|
+
samplerProps = sampler;
|
|
3692
|
+
}
|
|
3693
|
+
const parameters = convertSamplerParametersToWebGL(samplerProps);
|
|
3694
|
+
this._setSamplerParameters(parameters);
|
|
3860
3695
|
}
|
|
3861
|
-
|
|
3862
|
-
|
|
3696
|
+
/** Update external texture (video frame or canvas) */
|
|
3697
|
+
update() {
|
|
3698
|
+
import_core14.log.warn("Texture.update() not implemented");
|
|
3863
3699
|
}
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3700
|
+
// Call to regenerate mipmaps after modifying texture(s)
|
|
3701
|
+
generateMipmap(params = {}) {
|
|
3702
|
+
if (!this.props.data) {
|
|
3703
|
+
return;
|
|
3704
|
+
}
|
|
3705
|
+
this.mipmaps = true;
|
|
3706
|
+
this.gl.bindTexture(this.glTarget, this.handle);
|
|
3707
|
+
withGLParameters(this.gl, params, () => {
|
|
3708
|
+
this.gl.generateMipmap(this.glTarget);
|
|
3709
|
+
});
|
|
3710
|
+
this.gl.bindTexture(this.glTarget, null);
|
|
3869
3711
|
}
|
|
3870
|
-
|
|
3871
|
-
|
|
3712
|
+
// Image Data Setters
|
|
3713
|
+
copyExternalImage(options) {
|
|
3714
|
+
const size = import_core14.Texture.getExternalImageSize(options.image);
|
|
3715
|
+
const opts = { ...import_core14.Texture.defaultCopyExternalImageOptions, ...size, ...options };
|
|
3716
|
+
const { image, depth, mipLevel, x, y, z } = opts;
|
|
3717
|
+
let { width, height } = opts;
|
|
3718
|
+
const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
|
|
3719
|
+
width = Math.min(width, size.width - x);
|
|
3720
|
+
height = Math.min(height, size.height - y);
|
|
3721
|
+
if (options.sourceX || options.sourceY) {
|
|
3722
|
+
throw new Error(
|
|
3723
|
+
"WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer"
|
|
3724
|
+
);
|
|
3725
|
+
}
|
|
3726
|
+
copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
|
|
3727
|
+
dimension,
|
|
3728
|
+
mipLevel,
|
|
3729
|
+
x,
|
|
3730
|
+
y,
|
|
3731
|
+
z,
|
|
3732
|
+
width,
|
|
3733
|
+
height,
|
|
3734
|
+
depth,
|
|
3735
|
+
glFormat,
|
|
3736
|
+
glInternalFormat,
|
|
3737
|
+
glType,
|
|
3738
|
+
glTarget
|
|
3739
|
+
});
|
|
3740
|
+
return { width: opts.width, height: opts.height };
|
|
3872
3741
|
}
|
|
3873
|
-
|
|
3874
|
-
|
|
3742
|
+
setTexture1DData(data) {
|
|
3743
|
+
throw new Error("setTexture1DData not supported in WebGL.");
|
|
3875
3744
|
}
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
// src/adapter/helpers/parse-shader-compiler-log.ts
|
|
3883
|
-
function parseShaderCompilerLog(errLog) {
|
|
3884
|
-
const lines = errLog.split(/\r?\n/);
|
|
3885
|
-
const messages = [];
|
|
3886
|
-
for (const line of lines) {
|
|
3887
|
-
if (line.length <= 1) {
|
|
3888
|
-
continue;
|
|
3889
|
-
}
|
|
3890
|
-
const segments = line.split(":");
|
|
3891
|
-
if (segments.length === 2) {
|
|
3892
|
-
const [messageType2, message2] = segments;
|
|
3893
|
-
messages.push({
|
|
3894
|
-
message: message2.trim(),
|
|
3895
|
-
type: getMessageType(messageType2),
|
|
3896
|
-
lineNum: 0,
|
|
3897
|
-
linePos: 0
|
|
3898
|
-
});
|
|
3899
|
-
continue;
|
|
3900
|
-
}
|
|
3901
|
-
const [messageType, linePosition, lineNumber, ...rest] = segments;
|
|
3902
|
-
let lineNum = parseInt(lineNumber, 10);
|
|
3903
|
-
if (isNaN(lineNum)) {
|
|
3904
|
-
lineNum = 0;
|
|
3745
|
+
/** Set a simple texture */
|
|
3746
|
+
setTexture2DData(lodData, depth = 0) {
|
|
3747
|
+
this.bind();
|
|
3748
|
+
const lodArray = normalizeTextureData(lodData, this);
|
|
3749
|
+
if (lodArray.length > 1 && this.props.mipmaps !== false) {
|
|
3750
|
+
import_core14.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
|
|
3905
3751
|
}
|
|
3906
|
-
let
|
|
3907
|
-
|
|
3908
|
-
|
|
3752
|
+
for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
|
|
3753
|
+
const imageData = lodArray[lodLevel];
|
|
3754
|
+
this._setMipLevel(depth, lodLevel, imageData);
|
|
3909
3755
|
}
|
|
3910
|
-
|
|
3911
|
-
message: rest.join(":").trim(),
|
|
3912
|
-
type: getMessageType(messageType),
|
|
3913
|
-
lineNum,
|
|
3914
|
-
linePos
|
|
3915
|
-
// TODO
|
|
3916
|
-
});
|
|
3756
|
+
this.unbind();
|
|
3917
3757
|
}
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
constructor(device, props) {
|
|
3931
|
-
super(device, props);
|
|
3932
|
-
this.device = device;
|
|
3933
|
-
switch (this.props.stage) {
|
|
3934
|
-
case "vertex":
|
|
3935
|
-
this.handle = this.props.handle || this.device.gl.createShader(35633 /* VERTEX_SHADER */);
|
|
3936
|
-
break;
|
|
3937
|
-
case "fragment":
|
|
3938
|
-
this.handle = this.props.handle || this.device.gl.createShader(35632 /* FRAGMENT_SHADER */);
|
|
3939
|
-
break;
|
|
3940
|
-
default:
|
|
3941
|
-
throw new Error(this.props.stage);
|
|
3758
|
+
/**
|
|
3759
|
+
* Sets a 3D texture
|
|
3760
|
+
* @param data
|
|
3761
|
+
*/
|
|
3762
|
+
setTexture3DData(data) {
|
|
3763
|
+
if (this.props.dimension !== "3d") {
|
|
3764
|
+
throw new Error(this.id);
|
|
3765
|
+
}
|
|
3766
|
+
if (ArrayBuffer.isView(data)) {
|
|
3767
|
+
this.bind();
|
|
3768
|
+
copyCPUDataToMipLevel(this.device.gl, data, this);
|
|
3769
|
+
this.unbind();
|
|
3942
3770
|
}
|
|
3943
|
-
this._compile(this.source);
|
|
3944
3771
|
}
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3772
|
+
/**
|
|
3773
|
+
* Set a Texture Cube Data
|
|
3774
|
+
* @todo - could support TextureCubeArray with depth
|
|
3775
|
+
* @param data
|
|
3776
|
+
* @param index
|
|
3777
|
+
*/
|
|
3778
|
+
setTextureCubeData(data, depth = 0) {
|
|
3779
|
+
if (this.props.dimension !== "cube") {
|
|
3780
|
+
throw new Error(this.id);
|
|
3781
|
+
}
|
|
3782
|
+
for (const face of import_core14.Texture.CubeFaces) {
|
|
3783
|
+
this.setTextureCubeFaceData(data[face], face);
|
|
3950
3784
|
}
|
|
3951
3785
|
}
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3786
|
+
/**
|
|
3787
|
+
* Sets an entire texture array
|
|
3788
|
+
* @param data
|
|
3789
|
+
*/
|
|
3790
|
+
setTextureArrayData(data) {
|
|
3791
|
+
if (this.props.dimension !== "2d-array") {
|
|
3792
|
+
throw new Error(this.id);
|
|
3793
|
+
}
|
|
3794
|
+
throw new Error("setTextureArrayData not implemented.");
|
|
3955
3795
|
}
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3796
|
+
/**
|
|
3797
|
+
* Sets an entire texture cube array
|
|
3798
|
+
* @param data
|
|
3799
|
+
*/
|
|
3800
|
+
setTextureCubeArrayData(data) {
|
|
3801
|
+
throw new Error("setTextureCubeArrayData not supported in WebGL2.");
|
|
3959
3802
|
}
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3803
|
+
setTextureCubeFaceData(lodData, face, depth = 0) {
|
|
3804
|
+
if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
|
|
3805
|
+
import_core14.log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
3806
|
+
}
|
|
3807
|
+
const faceDepth = import_core14.Texture.CubeFaces.indexOf(face);
|
|
3808
|
+
this.setTexture2DData(lodData, faceDepth);
|
|
3964
3809
|
}
|
|
3965
|
-
//
|
|
3966
|
-
/**
|
|
3967
|
-
|
|
3968
|
-
const
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3810
|
+
// INTERNAL METHODS
|
|
3811
|
+
/** @todo update this method to accept LODs */
|
|
3812
|
+
setImageDataForFace(options) {
|
|
3813
|
+
const {
|
|
3814
|
+
face,
|
|
3815
|
+
width,
|
|
3816
|
+
height,
|
|
3817
|
+
pixels,
|
|
3818
|
+
data,
|
|
3819
|
+
format = 6408 /* RGBA */,
|
|
3820
|
+
type = 5121 /* UNSIGNED_BYTE */
|
|
3821
|
+
// generateMipmap = false // TODO
|
|
3822
|
+
} = options;
|
|
3823
|
+
const { gl } = this;
|
|
3824
|
+
const imageData = pixels || data;
|
|
3825
|
+
this.bind();
|
|
3826
|
+
if (imageData instanceof Promise) {
|
|
3827
|
+
imageData.then(
|
|
3828
|
+
(resolvedImageData) => this.setImageDataForFace(
|
|
3829
|
+
Object.assign({}, options, {
|
|
3830
|
+
face,
|
|
3831
|
+
data: resolvedImageData,
|
|
3832
|
+
pixels: resolvedImageData
|
|
3833
|
+
})
|
|
3834
|
+
)
|
|
3835
|
+
);
|
|
3836
|
+
} else if (this.width || this.height) {
|
|
3837
|
+
gl.texImage2D(face, 0, format, width, height, 0, format, type, imageData);
|
|
3838
|
+
} else {
|
|
3839
|
+
gl.texImage2D(face, 0, format, format, type, imageData);
|
|
3977
3840
|
}
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3841
|
+
}
|
|
3842
|
+
_getImageDataMap(faceData) {
|
|
3843
|
+
for (let i = 0; i < import_core14.Texture.CubeFaces.length; ++i) {
|
|
3844
|
+
const faceName = import_core14.Texture.CubeFaces[i];
|
|
3845
|
+
if (faceData[faceName]) {
|
|
3846
|
+
faceData[34069 /* TEXTURE_CUBE_MAP_POSITIVE_X */ + i] = faceData[faceName];
|
|
3847
|
+
delete faceData[faceName];
|
|
3983
3848
|
}
|
|
3984
|
-
return;
|
|
3985
3849
|
}
|
|
3986
|
-
|
|
3987
|
-
await this._waitForCompilationComplete();
|
|
3988
|
-
import_core14.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
|
|
3989
|
-
this._getCompilationStatus();
|
|
3990
|
-
this.debugShader();
|
|
3850
|
+
return faceData;
|
|
3991
3851
|
}
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
3852
|
+
// RESOURCE METHODS
|
|
3853
|
+
/**
|
|
3854
|
+
* Sets sampler parameters on texture
|
|
3855
|
+
*/
|
|
3856
|
+
_setSamplerParameters(parameters) {
|
|
3857
|
+
import_core14.log.log(1, "texture sampler parameters", parameters)();
|
|
3858
|
+
this.gl.bindTexture(this.glTarget, this.handle);
|
|
3859
|
+
for (const [pname, pvalue] of Object.entries(parameters)) {
|
|
3860
|
+
const param = Number(pname);
|
|
3861
|
+
const value = pvalue;
|
|
3862
|
+
switch (param) {
|
|
3863
|
+
case 33082 /* TEXTURE_MIN_LOD */:
|
|
3864
|
+
case 33083 /* TEXTURE_MAX_LOD */:
|
|
3865
|
+
this.gl.texParameterf(this.glTarget, param, value);
|
|
3866
|
+
break;
|
|
3867
|
+
case 10241 /* TEXTURE_MIN_FILTER */:
|
|
3868
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
3869
|
+
break;
|
|
3870
|
+
case 10242 /* TEXTURE_WRAP_S */:
|
|
3871
|
+
case 10243 /* TEXTURE_WRAP_T */:
|
|
3872
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
3873
|
+
break;
|
|
3874
|
+
case 34046 /* TEXTURE_MAX_ANISOTROPY_EXT */:
|
|
3875
|
+
if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
|
|
3876
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
3877
|
+
}
|
|
3878
|
+
break;
|
|
3879
|
+
default:
|
|
3880
|
+
this.gl.texParameteri(this.glTarget, param, value);
|
|
3881
|
+
break;
|
|
4005
3882
|
}
|
|
4006
|
-
await waitMs(DELAY_MS);
|
|
4007
3883
|
}
|
|
3884
|
+
this.gl.bindTexture(this.glTarget, null);
|
|
4008
3885
|
}
|
|
3886
|
+
// CLASSIC
|
|
3887
|
+
/*
|
|
3888
|
+
setCubeMapData(options: {
|
|
3889
|
+
width: number;
|
|
3890
|
+
height: number;
|
|
3891
|
+
data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
|
|
3892
|
+
format?: any;
|
|
3893
|
+
type?: any;
|
|
3894
|
+
/** @deprecated Use .data *
|
|
3895
|
+
pixels: any;
|
|
3896
|
+
}): void {
|
|
3897
|
+
const {gl} = this;
|
|
3898
|
+
|
|
3899
|
+
const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
|
|
3900
|
+
|
|
3901
|
+
// pixel data (imageDataMap) is an Object from Face to Image or Promise.
|
|
3902
|
+
// For example:
|
|
3903
|
+
// {
|
|
3904
|
+
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
|
|
3905
|
+
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
|
|
3906
|
+
// ... }
|
|
3907
|
+
// To provide multiple level-of-details (LODs) this can be Face to Array
|
|
3908
|
+
// of Image or Promise, like this
|
|
3909
|
+
// {
|
|
3910
|
+
// GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
3911
|
+
// GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
|
|
3912
|
+
// ... }
|
|
3913
|
+
|
|
3914
|
+
const imageDataMap = this._getImageDataMap(pixels || data);
|
|
3915
|
+
|
|
3916
|
+
const resolvedFaces = WEBGLTexture.FACES.map(face => {
|
|
3917
|
+
const facePixels = imageDataMap[face];
|
|
3918
|
+
return Array.isArray(facePixels) ? facePixels : [facePixels];
|
|
3919
|
+
});
|
|
3920
|
+
this.bind();
|
|
3921
|
+
|
|
3922
|
+
WEBGLTexture.FACES.forEach((face, index) => {
|
|
3923
|
+
if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
|
|
3924
|
+
// If the user provides multiple LODs, then automatic mipmap
|
|
3925
|
+
// generation generateMipmap() should be disabled to avoid overwritting them.
|
|
3926
|
+
log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
3927
|
+
}
|
|
3928
|
+
resolvedFaces[index].forEach((image, lodLevel) => {
|
|
3929
|
+
// TODO: adjust width & height for LOD!
|
|
3930
|
+
if (width && height) {
|
|
3931
|
+
gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
|
|
3932
|
+
} else {
|
|
3933
|
+
gl.texImage2D(face, lodLevel, format, format, type, image);
|
|
3934
|
+
}
|
|
3935
|
+
});
|
|
3936
|
+
});
|
|
3937
|
+
|
|
3938
|
+
this.unbind();
|
|
3939
|
+
}
|
|
3940
|
+
*/
|
|
3941
|
+
// INTERNAL SETTERS
|
|
4009
3942
|
/**
|
|
4010
|
-
*
|
|
4011
|
-
*
|
|
4012
|
-
* https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
|
|
3943
|
+
* Copy a region of data from a CPU memory buffer into this texture.
|
|
3944
|
+
* @todo - GLUnpackParameters parameters
|
|
4013
3945
|
*/
|
|
4014
|
-
|
|
4015
|
-
|
|
3946
|
+
_setMipLevel(depth, mipLevel, textureData, glTarget = this.glTarget) {
|
|
3947
|
+
if (import_core14.Texture.isExternalImage(textureData)) {
|
|
3948
|
+
copyExternalImageToMipLevel(this.device.gl, this.handle, textureData, {
|
|
3949
|
+
...this,
|
|
3950
|
+
depth,
|
|
3951
|
+
mipLevel,
|
|
3952
|
+
glTarget
|
|
3953
|
+
});
|
|
3954
|
+
return;
|
|
3955
|
+
}
|
|
3956
|
+
if (import_core14.Texture.isTextureLevelData(textureData)) {
|
|
3957
|
+
copyCPUDataToMipLevel(this.device.gl, textureData.data, {
|
|
3958
|
+
...this,
|
|
3959
|
+
depth,
|
|
3960
|
+
mipLevel,
|
|
3961
|
+
glTarget
|
|
3962
|
+
});
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
throw new Error("Texture: invalid image data");
|
|
3966
|
+
}
|
|
3967
|
+
// HELPERS
|
|
3968
|
+
getActiveUnit() {
|
|
3969
|
+
return this.gl.getParameter(34016 /* ACTIVE_TEXTURE */) - 33984 /* TEXTURE0 */;
|
|
3970
|
+
}
|
|
3971
|
+
bind(textureUnit) {
|
|
3972
|
+
const { gl } = this;
|
|
3973
|
+
if (textureUnit !== void 0) {
|
|
3974
|
+
this.textureUnit = textureUnit;
|
|
3975
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
3976
|
+
}
|
|
3977
|
+
gl.bindTexture(this.glTarget, this.handle);
|
|
3978
|
+
return textureUnit;
|
|
3979
|
+
}
|
|
3980
|
+
unbind(textureUnit) {
|
|
3981
|
+
const { gl } = this;
|
|
3982
|
+
if (textureUnit !== void 0) {
|
|
3983
|
+
this.textureUnit = textureUnit;
|
|
3984
|
+
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
|
3985
|
+
}
|
|
3986
|
+
gl.bindTexture(this.glTarget, null);
|
|
3987
|
+
return textureUnit;
|
|
4016
3988
|
}
|
|
4017
3989
|
};
|
|
4018
3990
|
|
|
@@ -5863,8 +5835,7 @@ ${source2}`;
|
|
|
5863
5835
|
const newProps = this._getBufferProps(props);
|
|
5864
5836
|
return new WEBGLBuffer(this, newProps);
|
|
5865
5837
|
}
|
|
5866
|
-
|
|
5867
|
-
_createTexture(props) {
|
|
5838
|
+
createTexture(props) {
|
|
5868
5839
|
return new WEBGLTexture(this, props);
|
|
5869
5840
|
}
|
|
5870
5841
|
createExternalTexture(props) {
|