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