@luma.gl/engine 9.2.6 → 9.3.0-alpha.4
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/animation-loop/animation-loop.d.ts +3 -1
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +10 -4
- package/dist/animation-loop/animation-loop.js.map +1 -1
- package/dist/compute/computation.d.ts.map +1 -1
- package/dist/compute/computation.js +3 -2
- package/dist/compute/computation.js.map +1 -1
- package/dist/compute/swap.d.ts +2 -0
- package/dist/compute/swap.d.ts.map +1 -1
- package/dist/compute/swap.js +10 -5
- package/dist/compute/swap.js.map +1 -1
- package/dist/dist.dev.js +1251 -574
- package/dist/dist.min.js +216 -48
- package/dist/dynamic-texture/dynamic-texture.d.ts +95 -0
- package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -0
- package/dist/dynamic-texture/dynamic-texture.js +389 -0
- package/dist/dynamic-texture/dynamic-texture.js.map +1 -0
- package/dist/dynamic-texture/mipmaps.d.ts +6 -0
- package/dist/dynamic-texture/mipmaps.d.ts.map +1 -0
- package/dist/dynamic-texture/mipmaps.js +441 -0
- package/dist/dynamic-texture/mipmaps.js.map +1 -0
- package/dist/dynamic-texture/texture-data.d.ts +137 -0
- package/dist/dynamic-texture/texture-data.d.ts.map +1 -0
- package/dist/dynamic-texture/texture-data.js +183 -0
- package/dist/dynamic-texture/texture-data.js.map +1 -0
- package/dist/factories/pipeline-factory.d.ts.map +1 -1
- package/dist/factories/pipeline-factory.js +3 -3
- package/dist/factories/pipeline-factory.js.map +1 -1
- package/dist/factories/shader-factory.d.ts.map +1 -1
- package/dist/factories/shader-factory.js +3 -2
- package/dist/factories/shader-factory.js.map +1 -1
- package/dist/index.cjs +1243 -583
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/model/model.d.ts +31 -10
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +34 -14
- package/dist/model/model.js.map +1 -1
- package/dist/models/billboard-texture-model.d.ts +8 -5
- package/dist/models/billboard-texture-model.d.ts.map +1 -1
- package/dist/models/billboard-texture-model.js +70 -18
- package/dist/models/billboard-texture-model.js.map +1 -1
- package/dist/passes/get-fragment-shader.js +15 -11
- package/dist/passes/get-fragment-shader.js.map +1 -1
- package/dist/passes/shader-pass-renderer.d.ts +5 -5
- package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
- package/dist/passes/shader-pass-renderer.js +13 -12
- package/dist/passes/shader-pass-renderer.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/buffer-layout-order.d.ts.map +1 -1
- package/dist/utils/buffer-layout-order.js +12 -2
- package/dist/utils/buffer-layout-order.js.map +1 -1
- package/package.json +6 -6
- package/src/animation-loop/animation-loop.ts +11 -4
- package/src/compute/computation.ts +3 -2
- package/src/compute/swap.ts +13 -7
- package/src/dynamic-texture/dynamic-texture.ts +499 -0
- package/src/dynamic-texture/mipmaps.ts +517 -0
- package/src/dynamic-texture/texture-data.ts +301 -0
- package/src/factories/pipeline-factory.ts +4 -3
- package/src/factories/shader-factory.ts +4 -2
- package/src/index.ts +9 -4
- package/src/model/model.ts +37 -18
- package/src/models/billboard-texture-model.ts +81 -22
- package/src/passes/get-fragment-shader.ts +15 -11
- package/src/passes/shader-pass-renderer.ts +22 -16
- package/src/types.ts +11 -0
- package/src/utils/buffer-layout-order.ts +18 -2
- package/dist/async-texture/async-texture.d.ts +0 -166
- package/dist/async-texture/async-texture.d.ts.map +0 -1
- package/dist/async-texture/async-texture.js +0 -386
- package/dist/async-texture/async-texture.js.map +0 -1
- package/src/async-texture/async-texture.ts +0 -551
- /package/src/{async-texture/texture-setters.ts.disabled → dynamic-texture/texture-data.ts.disabled} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(dist_exports, {
|
|
|
35
35
|
ConeGeometry: () => ConeGeometry,
|
|
36
36
|
CubeGeometry: () => CubeGeometry,
|
|
37
37
|
CylinderGeometry: () => CylinderGeometry,
|
|
38
|
+
DynamicTexture: () => DynamicTexture,
|
|
38
39
|
GPUGeometry: () => GPUGeometry,
|
|
39
40
|
Geometry: () => Geometry,
|
|
40
41
|
GroupNode: () => GroupNode,
|
|
@@ -265,7 +266,7 @@ var _AnimationLoop = class {
|
|
|
265
266
|
gpuTime;
|
|
266
267
|
frameRate;
|
|
267
268
|
display;
|
|
268
|
-
|
|
269
|
+
_needsRedraw = "initialized";
|
|
269
270
|
_initialized = false;
|
|
270
271
|
_running = false;
|
|
271
272
|
_animationFrameId = null;
|
|
@@ -307,9 +308,15 @@ var _AnimationLoop = class {
|
|
|
307
308
|
}
|
|
308
309
|
/** Flags this animation loop as needing redraw */
|
|
309
310
|
setNeedsRedraw(reason) {
|
|
310
|
-
this.
|
|
311
|
+
this._needsRedraw = this._needsRedraw || reason;
|
|
311
312
|
return this;
|
|
312
313
|
}
|
|
314
|
+
/** Query redraw status. Clears the flag. */
|
|
315
|
+
needsRedraw() {
|
|
316
|
+
const reason = this._needsRedraw;
|
|
317
|
+
this._needsRedraw = false;
|
|
318
|
+
return reason;
|
|
319
|
+
}
|
|
313
320
|
setProps(props) {
|
|
314
321
|
if ("autoResizeViewport" in props) {
|
|
315
322
|
this.props.autoResizeViewport = props.autoResizeViewport || false;
|
|
@@ -453,7 +460,7 @@ var _AnimationLoop = class {
|
|
|
453
460
|
(_a = this.device) == null ? void 0 : _a.submit();
|
|
454
461
|
}
|
|
455
462
|
_clearNeedsRedraw() {
|
|
456
|
-
this.
|
|
463
|
+
this._needsRedraw = false;
|
|
457
464
|
}
|
|
458
465
|
_setupFrame() {
|
|
459
466
|
this._resizeViewport();
|
|
@@ -512,7 +519,7 @@ var _AnimationLoop = class {
|
|
|
512
519
|
this.animationProps.width = width;
|
|
513
520
|
this.animationProps.height = height;
|
|
514
521
|
this.animationProps.aspect = aspect;
|
|
515
|
-
this.animationProps.needsRedraw = this.
|
|
522
|
+
this.animationProps.needsRedraw = this._needsRedraw;
|
|
516
523
|
this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
|
|
517
524
|
if (this.timeline) {
|
|
518
525
|
this.timeline.update(this.animationProps.engineTime);
|
|
@@ -670,8 +677,8 @@ function clearError(device) {
|
|
|
670
677
|
}
|
|
671
678
|
|
|
672
679
|
// dist/model/model.js
|
|
673
|
-
var
|
|
674
|
-
var
|
|
680
|
+
var import_core12 = require("@luma.gl/core");
|
|
681
|
+
var import_shadertools3 = require("@luma.gl/shadertools");
|
|
675
682
|
|
|
676
683
|
// dist/geometry/gpu-geometry.js
|
|
677
684
|
var import_core3 = require("@luma.gl/core");
|
|
@@ -786,8 +793,9 @@ var import_core4 = require("@luma.gl/core");
|
|
|
786
793
|
var _PipelineFactory = class {
|
|
787
794
|
/** Get the singleton default pipeline factory for the specified device */
|
|
788
795
|
static getDefaultPipelineFactory(device) {
|
|
789
|
-
|
|
790
|
-
|
|
796
|
+
const moduleData = device.getModuleData("@luma.gl/engine");
|
|
797
|
+
moduleData.defaultPipelineFactory ||= new _PipelineFactory(device);
|
|
798
|
+
return moduleData.defaultPipelineFactory;
|
|
791
799
|
}
|
|
792
800
|
device;
|
|
793
801
|
cachingEnabled;
|
|
@@ -952,8 +960,9 @@ var import_core5 = require("@luma.gl/core");
|
|
|
952
960
|
var _ShaderFactory = class {
|
|
953
961
|
/** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
|
|
954
962
|
static getDefaultShaderFactory(device) {
|
|
955
|
-
device.
|
|
956
|
-
|
|
963
|
+
const moduleData = device.getModuleData("@luma.gl/engine");
|
|
964
|
+
moduleData.defaultShaderFactory ||= new _ShaderFactory(device);
|
|
965
|
+
return moduleData.defaultShaderFactory;
|
|
957
966
|
}
|
|
958
967
|
device;
|
|
959
968
|
cachingEnabled;
|
|
@@ -1166,14 +1175,24 @@ var BufferLayoutHelper = class {
|
|
|
1166
1175
|
};
|
|
1167
1176
|
|
|
1168
1177
|
// dist/utils/buffer-layout-order.js
|
|
1178
|
+
function getMinLocation(attributeNames, shaderLayoutMap) {
|
|
1179
|
+
let minLocation = Infinity;
|
|
1180
|
+
for (const name of attributeNames) {
|
|
1181
|
+
const location = shaderLayoutMap[name];
|
|
1182
|
+
if (location !== void 0) {
|
|
1183
|
+
minLocation = Math.min(minLocation, location);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
return minLocation;
|
|
1187
|
+
}
|
|
1169
1188
|
function sortedBufferLayoutByShaderSourceLocations(shaderLayout, bufferLayout) {
|
|
1170
1189
|
const shaderLayoutMap = Object.fromEntries(shaderLayout.attributes.map((attr) => [attr.name, attr.location]));
|
|
1171
1190
|
const sortedLayout = bufferLayout.slice();
|
|
1172
1191
|
sortedLayout.sort((a, b) => {
|
|
1173
1192
|
const attributeNamesA = a.attributes ? a.attributes.map((attr) => attr.attribute) : [a.name];
|
|
1174
1193
|
const attributeNamesB = b.attributes ? b.attributes.map((attr) => attr.attribute) : [b.name];
|
|
1175
|
-
const minLocationA =
|
|
1176
|
-
const minLocationB =
|
|
1194
|
+
const minLocationA = getMinLocation(attributeNamesA, shaderLayoutMap);
|
|
1195
|
+
const minLocationB = getMinLocation(attributeNamesB, shaderLayoutMap);
|
|
1177
1196
|
return minLocationA - minLocationB;
|
|
1178
1197
|
});
|
|
1179
1198
|
return sortedLayout;
|
|
@@ -1306,49 +1325,795 @@ var ShaderInputs = class {
|
|
|
1306
1325
|
}
|
|
1307
1326
|
};
|
|
1308
1327
|
|
|
1309
|
-
// dist/
|
|
1310
|
-
var
|
|
1328
|
+
// dist/dynamic-texture/dynamic-texture.js
|
|
1329
|
+
var import_core11 = require("@luma.gl/core");
|
|
1311
1330
|
|
|
1312
|
-
// dist/
|
|
1313
|
-
var
|
|
1314
|
-
|
|
1315
|
-
|
|
1331
|
+
// dist/dynamic-texture/texture-data.js
|
|
1332
|
+
var import_core8 = require("@luma.gl/core");
|
|
1333
|
+
var TEXTURE_CUBE_FACE_MAP = { "+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5 };
|
|
1334
|
+
function getFirstMipLevel(layer) {
|
|
1335
|
+
if (!layer)
|
|
1336
|
+
return null;
|
|
1337
|
+
return Array.isArray(layer) ? layer[0] ?? null : layer;
|
|
1316
1338
|
}
|
|
1317
|
-
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1339
|
+
function getTextureSizeFromData(props) {
|
|
1340
|
+
const { dimension, data } = props;
|
|
1341
|
+
if (!data) {
|
|
1342
|
+
return null;
|
|
1343
|
+
}
|
|
1344
|
+
switch (dimension) {
|
|
1345
|
+
case "1d": {
|
|
1346
|
+
const mipLevel = getFirstMipLevel(data);
|
|
1347
|
+
if (!mipLevel)
|
|
1348
|
+
return null;
|
|
1349
|
+
const { width } = getTextureMipLevelSize(mipLevel);
|
|
1350
|
+
return { width, height: 1 };
|
|
1351
|
+
}
|
|
1352
|
+
case "2d": {
|
|
1353
|
+
const mipLevel = getFirstMipLevel(data);
|
|
1354
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1355
|
+
}
|
|
1356
|
+
case "3d":
|
|
1357
|
+
case "2d-array": {
|
|
1358
|
+
if (!Array.isArray(data) || data.length === 0)
|
|
1359
|
+
return null;
|
|
1360
|
+
const mipLevel = getFirstMipLevel(data[0]);
|
|
1361
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1362
|
+
}
|
|
1363
|
+
case "cube": {
|
|
1364
|
+
const face = Object.keys(data)[0] ?? null;
|
|
1365
|
+
if (!face)
|
|
1366
|
+
return null;
|
|
1367
|
+
const faceData = data[face];
|
|
1368
|
+
const mipLevel = getFirstMipLevel(faceData);
|
|
1369
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1370
|
+
}
|
|
1371
|
+
case "cube-array": {
|
|
1372
|
+
if (!Array.isArray(data) || data.length === 0)
|
|
1373
|
+
return null;
|
|
1374
|
+
const firstCube = data[0];
|
|
1375
|
+
const face = Object.keys(firstCube)[0] ?? null;
|
|
1376
|
+
if (!face)
|
|
1377
|
+
return null;
|
|
1378
|
+
const mipLevel = getFirstMipLevel(firstCube[face]);
|
|
1379
|
+
return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
|
|
1380
|
+
}
|
|
1381
|
+
default:
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1323
1384
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1385
|
+
function getTextureMipLevelSize(data) {
|
|
1386
|
+
if ((0, import_core8.isExternalImage)(data)) {
|
|
1387
|
+
return (0, import_core8.getExternalImageSize)(data);
|
|
1388
|
+
}
|
|
1389
|
+
if (typeof data === "object" && "width" in data && "height" in data) {
|
|
1390
|
+
return { width: data.width, height: data.height };
|
|
1391
|
+
}
|
|
1392
|
+
throw new Error("Unsupported mip-level data");
|
|
1393
|
+
}
|
|
1394
|
+
function isTextureImageData(data) {
|
|
1395
|
+
return typeof data === "object" && data !== null && "data" in data && "width" in data && "height" in data;
|
|
1396
|
+
}
|
|
1397
|
+
function getCubeFaceIndex(face) {
|
|
1398
|
+
const idx = TEXTURE_CUBE_FACE_MAP[face];
|
|
1399
|
+
if (idx === void 0)
|
|
1400
|
+
throw new Error(`Invalid cube face: ${face}`);
|
|
1401
|
+
return idx;
|
|
1402
|
+
}
|
|
1403
|
+
function getCubeArrayFaceIndex(cubeIndex, face) {
|
|
1404
|
+
return 6 * cubeIndex + getCubeFaceIndex(face);
|
|
1405
|
+
}
|
|
1406
|
+
function getTexture1DSubresources(data) {
|
|
1407
|
+
throw new Error("setTexture1DData not supported in WebGL.");
|
|
1408
|
+
}
|
|
1409
|
+
function _normalizeTexture2DData(data) {
|
|
1410
|
+
return Array.isArray(data) ? data : [data];
|
|
1411
|
+
}
|
|
1412
|
+
function getTexture2DSubresources(slice, lodData) {
|
|
1413
|
+
const lodArray = _normalizeTexture2DData(lodData);
|
|
1414
|
+
const z = slice;
|
|
1415
|
+
const subresources = [];
|
|
1416
|
+
for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
|
|
1417
|
+
const imageData = lodArray[mipLevel];
|
|
1418
|
+
if ((0, import_core8.isExternalImage)(imageData)) {
|
|
1419
|
+
subresources.push({
|
|
1420
|
+
type: "external-image",
|
|
1421
|
+
image: imageData,
|
|
1422
|
+
z,
|
|
1423
|
+
mipLevel
|
|
1424
|
+
});
|
|
1425
|
+
} else if (isTextureImageData(imageData)) {
|
|
1426
|
+
subresources.push({
|
|
1427
|
+
type: "texture-data",
|
|
1428
|
+
data: imageData,
|
|
1429
|
+
z,
|
|
1430
|
+
mipLevel
|
|
1431
|
+
});
|
|
1432
|
+
} else {
|
|
1433
|
+
throw new Error("Unsupported 2D mip-level payload");
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
return subresources;
|
|
1437
|
+
}
|
|
1438
|
+
function getTexture3DSubresources(data) {
|
|
1439
|
+
const subresources = [];
|
|
1440
|
+
for (let depth = 0; depth < data.length; depth++) {
|
|
1441
|
+
subresources.push(...getTexture2DSubresources(depth, data[depth]));
|
|
1442
|
+
}
|
|
1443
|
+
return subresources;
|
|
1444
|
+
}
|
|
1445
|
+
function getTextureArraySubresources(data) {
|
|
1446
|
+
const subresources = [];
|
|
1447
|
+
for (let layer = 0; layer < data.length; layer++) {
|
|
1448
|
+
subresources.push(...getTexture2DSubresources(layer, data[layer]));
|
|
1449
|
+
}
|
|
1450
|
+
return subresources;
|
|
1451
|
+
}
|
|
1452
|
+
function getTextureCubeSubresources(data) {
|
|
1453
|
+
const subresources = [];
|
|
1454
|
+
for (const [face, faceData] of Object.entries(data)) {
|
|
1455
|
+
const faceDepth = getCubeFaceIndex(face);
|
|
1456
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
1457
|
+
}
|
|
1458
|
+
return subresources;
|
|
1459
|
+
}
|
|
1460
|
+
function getTextureCubeArraySubresources(data) {
|
|
1461
|
+
const subresources = [];
|
|
1462
|
+
data.forEach((cubeData, cubeIndex) => {
|
|
1463
|
+
for (const [face, faceData] of Object.entries(cubeData)) {
|
|
1464
|
+
const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
|
|
1465
|
+
subresources.push(...getTexture2DSubresources(faceDepth, faceData));
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
return subresources;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
// dist/dynamic-texture/mipmaps.js
|
|
1472
|
+
var import_core10 = require("@luma.gl/core");
|
|
1473
|
+
|
|
1474
|
+
// dist/compute/computation.js
|
|
1475
|
+
var import_core9 = require("@luma.gl/core");
|
|
1476
|
+
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
1477
|
+
var import_types2 = require("@math.gl/types");
|
|
1478
|
+
var LOG_DRAW_PRIORITY = 2;
|
|
1479
|
+
var LOG_DRAW_TIMEOUT = 1e4;
|
|
1480
|
+
var _Computation = class {
|
|
1481
|
+
device;
|
|
1482
|
+
id;
|
|
1483
|
+
pipelineFactory;
|
|
1484
|
+
shaderFactory;
|
|
1485
|
+
userData = {};
|
|
1486
|
+
/** Bindings (textures, samplers, uniform buffers) */
|
|
1487
|
+
bindings = {};
|
|
1488
|
+
/** The underlying GPU pipeline. */
|
|
1489
|
+
pipeline;
|
|
1490
|
+
/** Assembled compute shader source */
|
|
1491
|
+
source;
|
|
1492
|
+
/** the underlying compiled compute shader */
|
|
1493
|
+
// @ts-ignore Set in function called from constructor
|
|
1494
|
+
shader;
|
|
1495
|
+
/** ShaderInputs instance */
|
|
1496
|
+
shaderInputs;
|
|
1497
|
+
// @ts-ignore Set in function called from constructor
|
|
1498
|
+
_uniformStore;
|
|
1499
|
+
_pipelineNeedsUpdate = "newly created";
|
|
1500
|
+
_getModuleUniforms;
|
|
1501
|
+
props;
|
|
1502
|
+
_destroyed = false;
|
|
1503
|
+
constructor(device, props) {
|
|
1504
|
+
var _a, _b, _c;
|
|
1505
|
+
if (device.type !== "webgpu") {
|
|
1506
|
+
throw new Error("Computation is only supported in WebGPU");
|
|
1507
|
+
}
|
|
1508
|
+
this.props = { ..._Computation.defaultProps, ...props };
|
|
1509
|
+
props = this.props;
|
|
1510
|
+
this.id = props.id || uid("model");
|
|
1511
|
+
this.device = device;
|
|
1512
|
+
Object.assign(this.userData, props.userData);
|
|
1513
|
+
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
1514
|
+
this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
|
|
1515
|
+
this.setShaderInputs(this.shaderInputs);
|
|
1516
|
+
this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
|
|
1517
|
+
const platformInfo = getPlatformInfo(device);
|
|
1518
|
+
const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
|
|
1519
|
+
this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
1520
|
+
this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
|
|
1521
|
+
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
1522
|
+
platformInfo,
|
|
1523
|
+
...this.props,
|
|
1524
|
+
modules
|
|
1525
|
+
});
|
|
1526
|
+
this.source = source3;
|
|
1527
|
+
this._getModuleUniforms = getUniforms2;
|
|
1528
|
+
this.pipeline = this._updatePipeline();
|
|
1529
|
+
if (props.bindings) {
|
|
1530
|
+
this.setBindings(props.bindings);
|
|
1531
|
+
}
|
|
1532
|
+
Object.seal(this);
|
|
1533
|
+
}
|
|
1534
|
+
destroy() {
|
|
1535
|
+
if (this._destroyed)
|
|
1536
|
+
return;
|
|
1537
|
+
this.pipelineFactory.release(this.pipeline);
|
|
1538
|
+
this.shaderFactory.release(this.shader);
|
|
1539
|
+
this._uniformStore.destroy();
|
|
1540
|
+
this._destroyed = true;
|
|
1541
|
+
}
|
|
1542
|
+
// Draw call
|
|
1543
|
+
predraw() {
|
|
1544
|
+
this.updateShaderInputs();
|
|
1545
|
+
}
|
|
1546
|
+
dispatch(computePass, x, y, z) {
|
|
1326
1547
|
try {
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1548
|
+
this._logDrawCallStart();
|
|
1549
|
+
this.pipeline = this._updatePipeline();
|
|
1550
|
+
this.pipeline.setBindings(this.bindings);
|
|
1551
|
+
computePass.setPipeline(this.pipeline);
|
|
1552
|
+
computePass.setBindings([]);
|
|
1553
|
+
computePass.dispatch(x, y, z);
|
|
1554
|
+
} finally {
|
|
1555
|
+
this._logDrawCallEnd();
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
// Update fixed fields (can trigger pipeline rebuild)
|
|
1559
|
+
// Update dynamic fields
|
|
1560
|
+
/**
|
|
1561
|
+
* Updates the vertex count (used in draw calls)
|
|
1562
|
+
* @note Any attributes with stepMode=vertex need to be at least this big
|
|
1563
|
+
*/
|
|
1564
|
+
setVertexCount(vertexCount) {
|
|
1565
|
+
}
|
|
1566
|
+
/**
|
|
1567
|
+
* Updates the instance count (used in draw calls)
|
|
1568
|
+
* @note Any attributes with stepMode=instance need to be at least this big
|
|
1569
|
+
*/
|
|
1570
|
+
setInstanceCount(instanceCount) {
|
|
1571
|
+
}
|
|
1572
|
+
setShaderInputs(shaderInputs) {
|
|
1573
|
+
this.shaderInputs = shaderInputs;
|
|
1574
|
+
this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
|
|
1575
|
+
for (const moduleName of Object.keys(this.shaderInputs.modules)) {
|
|
1576
|
+
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
1577
|
+
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Updates shader module settings (which results in uniforms being set)
|
|
1582
|
+
*/
|
|
1583
|
+
setShaderModuleProps(props) {
|
|
1584
|
+
const uniforms = this._getModuleUniforms(props);
|
|
1585
|
+
const keys = Object.keys(uniforms).filter((k) => {
|
|
1586
|
+
const uniform = uniforms[k];
|
|
1587
|
+
return !(0, import_types2.isNumericArray)(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
|
|
1588
|
+
});
|
|
1589
|
+
const bindings = {};
|
|
1590
|
+
for (const k of keys) {
|
|
1591
|
+
bindings[k] = uniforms[k];
|
|
1592
|
+
delete uniforms[k];
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
updateShaderInputs() {
|
|
1596
|
+
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Sets bindings (textures, samplers, uniform buffers)
|
|
1600
|
+
*/
|
|
1601
|
+
setBindings(bindings) {
|
|
1602
|
+
Object.assign(this.bindings, bindings);
|
|
1603
|
+
}
|
|
1604
|
+
_setPipelineNeedsUpdate(reason) {
|
|
1605
|
+
this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
|
|
1606
|
+
}
|
|
1607
|
+
_updatePipeline() {
|
|
1608
|
+
if (this._pipelineNeedsUpdate) {
|
|
1609
|
+
let prevShader = null;
|
|
1610
|
+
if (this.pipeline) {
|
|
1611
|
+
import_core9.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
1612
|
+
prevShader = this.shader;
|
|
1613
|
+
}
|
|
1614
|
+
this._pipelineNeedsUpdate = false;
|
|
1615
|
+
this.shader = this.shaderFactory.createShader({
|
|
1616
|
+
id: `${this.id}-fragment`,
|
|
1617
|
+
stage: "compute",
|
|
1618
|
+
source: this.source,
|
|
1619
|
+
debugShaders: this.props.debugShaders
|
|
1620
|
+
});
|
|
1621
|
+
this.pipeline = this.pipelineFactory.createComputePipeline({
|
|
1622
|
+
...this.props,
|
|
1623
|
+
shader: this.shader
|
|
1624
|
+
});
|
|
1625
|
+
if (prevShader) {
|
|
1626
|
+
this.shaderFactory.release(prevShader);
|
|
1627
|
+
}
|
|
1334
1628
|
}
|
|
1629
|
+
return this.pipeline;
|
|
1630
|
+
}
|
|
1631
|
+
/** Throttle draw call logging */
|
|
1632
|
+
_lastLogTime = 0;
|
|
1633
|
+
_logOpen = false;
|
|
1634
|
+
_logDrawCallStart() {
|
|
1635
|
+
const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
|
|
1636
|
+
if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
this._lastLogTime = Date.now();
|
|
1640
|
+
this._logOpen = true;
|
|
1641
|
+
import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
|
|
1642
|
+
}
|
|
1643
|
+
_logDrawCallEnd() {
|
|
1644
|
+
if (this._logOpen) {
|
|
1645
|
+
const uniformTable = this.shaderInputs.getDebugTable();
|
|
1646
|
+
import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
|
|
1647
|
+
import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
|
|
1648
|
+
this._logOpen = false;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
_drawCount = 0;
|
|
1652
|
+
// TODO - fix typing of luma data types
|
|
1653
|
+
_getBufferOrConstantValues(attribute, dataType) {
|
|
1654
|
+
const TypedArrayConstructor = (0, import_core9.getTypedArrayConstructor)(dataType);
|
|
1655
|
+
const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
1656
|
+
return typedArray.toString();
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
var Computation = _Computation;
|
|
1660
|
+
__publicField(Computation, "defaultProps", {
|
|
1661
|
+
...import_core9.ComputePipeline.defaultProps,
|
|
1662
|
+
id: "unnamed",
|
|
1663
|
+
handle: void 0,
|
|
1664
|
+
userData: {},
|
|
1665
|
+
source: "",
|
|
1666
|
+
modules: [],
|
|
1667
|
+
defines: {},
|
|
1668
|
+
bindings: void 0,
|
|
1669
|
+
shaderInputs: void 0,
|
|
1670
|
+
pipelineFactory: void 0,
|
|
1671
|
+
shaderFactory: void 0,
|
|
1672
|
+
shaderAssembler: import_shadertools2.ShaderAssembler.getDefaultShaderAssembler(),
|
|
1673
|
+
debugShaders: void 0
|
|
1674
|
+
});
|
|
1675
|
+
function getPlatformInfo(device) {
|
|
1676
|
+
return {
|
|
1677
|
+
type: device.type,
|
|
1678
|
+
shaderLanguage: device.info.shadingLanguage,
|
|
1679
|
+
shaderLanguageVersion: device.info.shadingLanguageVersion,
|
|
1680
|
+
gpu: device.info.gpu,
|
|
1681
|
+
// HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
|
|
1682
|
+
features: device.features
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
// dist/dynamic-texture/mipmaps.js
|
|
1687
|
+
var RENDER_DIMENSIONS = [
|
|
1688
|
+
"2d",
|
|
1689
|
+
"2d-array",
|
|
1690
|
+
"cube",
|
|
1691
|
+
"cube-array"
|
|
1692
|
+
];
|
|
1693
|
+
var WORKGROUP_SIZE = {
|
|
1694
|
+
x: 4,
|
|
1695
|
+
y: 4,
|
|
1696
|
+
z: 4
|
|
1697
|
+
};
|
|
1698
|
+
function generateMipmap(device, texture) {
|
|
1699
|
+
if (texture.mipLevels <= 1) {
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
if (device.type !== "webgpu") {
|
|
1703
|
+
throw new Error(`Cannot generate mipmaps on device type "${device.type}". Use generateMipmapsWebGL for WebGL devices.`);
|
|
1704
|
+
}
|
|
1705
|
+
if (texture.dimension === "3d") {
|
|
1706
|
+
generateMipmaps3D(device, texture);
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
if (RENDER_DIMENSIONS.includes(texture.dimension)) {
|
|
1710
|
+
generateMipmapsRender(device, texture);
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
throw new Error(`Cannot generate mipmaps for texture dimension "${texture.dimension}" with WebGPU.`);
|
|
1714
|
+
}
|
|
1715
|
+
function generateMipmapsRender(device, texture) {
|
|
1716
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
1717
|
+
const colorAttachmentFormat = getColorAttachmentFormat(texture.format, "render", texture.dimension);
|
|
1718
|
+
const viewDimension = texture.dimension;
|
|
1719
|
+
const shader = getRenderMipmapWGSL(viewDimension);
|
|
1720
|
+
const sampler = device.createSampler({ minFilter: "linear", magFilter: "linear" });
|
|
1721
|
+
const uniformValues = new Uint32Array(1);
|
|
1722
|
+
const uniformsBuffer = device.createBuffer({
|
|
1723
|
+
byteLength: 16,
|
|
1724
|
+
usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
|
|
1725
|
+
});
|
|
1726
|
+
const model = new Model(device, {
|
|
1727
|
+
source: shader,
|
|
1728
|
+
colorAttachmentFormats: [colorAttachmentFormat],
|
|
1729
|
+
topology: "triangle-list",
|
|
1730
|
+
vertexCount: 3,
|
|
1731
|
+
shaderLayout: {
|
|
1732
|
+
attributes: [],
|
|
1733
|
+
bindings: [
|
|
1734
|
+
{ type: "sampler", name: "sourceSampler", group: 0, location: 0 },
|
|
1735
|
+
{
|
|
1736
|
+
type: "texture",
|
|
1737
|
+
name: "sourceTexture",
|
|
1738
|
+
group: 0,
|
|
1739
|
+
location: 1,
|
|
1740
|
+
viewDimension,
|
|
1741
|
+
sampleType: "float"
|
|
1742
|
+
},
|
|
1743
|
+
{ type: "uniform", name: "uniforms", group: 0, location: 2 }
|
|
1744
|
+
]
|
|
1745
|
+
},
|
|
1746
|
+
bindings: {
|
|
1747
|
+
sourceSampler: sampler,
|
|
1748
|
+
sourceTexture: texture,
|
|
1749
|
+
uniforms: uniformsBuffer
|
|
1750
|
+
}
|
|
1751
|
+
});
|
|
1752
|
+
let sourceWidth = texture.width;
|
|
1753
|
+
let sourceHeight = texture.height;
|
|
1754
|
+
const layerCount = texture.dimension === "2d" ? 1 : texture.depth;
|
|
1755
|
+
try {
|
|
1756
|
+
for (let baseMipLevel = 1; baseMipLevel < texture.mipLevels; ++baseMipLevel) {
|
|
1757
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
1758
|
+
const sourceMipLevel = baseMipLevel - 1;
|
|
1759
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
1760
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
1761
|
+
const sourceView = texture.createView({
|
|
1762
|
+
dimension: viewDimension,
|
|
1763
|
+
baseMipLevel: sourceMipLevel,
|
|
1764
|
+
mipLevelCount: 1,
|
|
1765
|
+
baseArrayLayer: 0,
|
|
1766
|
+
arrayLayerCount: texture.depth
|
|
1767
|
+
});
|
|
1768
|
+
model.setBindings({ sourceTexture: sourceView });
|
|
1769
|
+
for (let baseArrayLayer = 0; baseArrayLayer < layerCount; ++baseArrayLayer) {
|
|
1770
|
+
uniformValues[0] = baseArrayLayer;
|
|
1771
|
+
uniformsBuffer.write(uniformValues);
|
|
1772
|
+
const destinationView = texture.createView({
|
|
1773
|
+
dimension: "2d",
|
|
1774
|
+
baseMipLevel,
|
|
1775
|
+
mipLevelCount: 1,
|
|
1776
|
+
baseArrayLayer,
|
|
1777
|
+
arrayLayerCount: 1
|
|
1778
|
+
});
|
|
1779
|
+
const framebuffer = device.createFramebuffer({
|
|
1780
|
+
colorAttachments: [destinationView]
|
|
1781
|
+
});
|
|
1782
|
+
const renderPass = device.beginRenderPass({
|
|
1783
|
+
id: `mipmap-generation:${texture.format}:${baseMipLevel}:${baseArrayLayer}`,
|
|
1784
|
+
framebuffer
|
|
1785
|
+
});
|
|
1786
|
+
renderPass.setParameters({
|
|
1787
|
+
viewport: [0, 0, destinationWidth, destinationHeight, 0, 1],
|
|
1788
|
+
scissorRect: [0, 0, destinationWidth, destinationHeight]
|
|
1789
|
+
});
|
|
1790
|
+
model.draw(renderPass);
|
|
1791
|
+
renderPass.end();
|
|
1792
|
+
device.submit();
|
|
1793
|
+
destinationView.destroy();
|
|
1794
|
+
framebuffer.destroy();
|
|
1795
|
+
}
|
|
1796
|
+
sourceView.destroy();
|
|
1797
|
+
sourceWidth = destinationWidth;
|
|
1798
|
+
sourceHeight = destinationHeight;
|
|
1799
|
+
}
|
|
1800
|
+
} finally {
|
|
1801
|
+
model.destroy();
|
|
1802
|
+
sampler.destroy();
|
|
1803
|
+
uniformsBuffer.destroy();
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function getColorAttachmentFormat(format, path, dimension) {
|
|
1807
|
+
if (import_core10.textureFormatDecoder.isColor(format)) {
|
|
1808
|
+
return format;
|
|
1809
|
+
}
|
|
1810
|
+
throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Only color textures can be used for this operation. Required capabilities: color. Actual capabilities: color=false.`);
|
|
1811
|
+
}
|
|
1812
|
+
function generateMipmaps3D(device, texture) {
|
|
1813
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
1814
|
+
const format = getColorAttachmentFormat(texture.format, "compute", texture.dimension);
|
|
1815
|
+
const shaderSource = get3DComputeMipmapWGSL(format);
|
|
1816
|
+
const uniformsBuffer = device.createBuffer({
|
|
1817
|
+
byteLength: 32,
|
|
1818
|
+
usage: import_core10.Buffer.UNIFORM | import_core10.Buffer.COPY_DST
|
|
1335
1819
|
});
|
|
1820
|
+
const uniformValues = new Uint32Array(8);
|
|
1821
|
+
let sourceWidth = texture.width;
|
|
1822
|
+
let sourceHeight = texture.height;
|
|
1823
|
+
let sourceDepth = texture.depth;
|
|
1824
|
+
try {
|
|
1825
|
+
for (let destinationMipLevel = 1; destinationMipLevel < texture.mipLevels; ++destinationMipLevel) {
|
|
1826
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
1827
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
1828
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
1829
|
+
const destinationDepth = Math.max(1, sourceDepth >> 1);
|
|
1830
|
+
uniformValues[0] = sourceWidth;
|
|
1831
|
+
uniformValues[1] = sourceHeight;
|
|
1832
|
+
uniformValues[2] = sourceDepth;
|
|
1833
|
+
uniformValues[3] = destinationWidth;
|
|
1834
|
+
uniformValues[4] = destinationHeight;
|
|
1835
|
+
uniformValues[5] = destinationDepth;
|
|
1836
|
+
uniformValues[6] = 0;
|
|
1837
|
+
uniformsBuffer.write(uniformValues);
|
|
1838
|
+
const sourceView = texture.createView({
|
|
1839
|
+
dimension: "3d",
|
|
1840
|
+
baseMipLevel: destinationMipLevel - 1,
|
|
1841
|
+
mipLevelCount: 1,
|
|
1842
|
+
baseArrayLayer: 0,
|
|
1843
|
+
arrayLayerCount: 1
|
|
1844
|
+
});
|
|
1845
|
+
const destinationView = texture.createView({
|
|
1846
|
+
dimension: "3d",
|
|
1847
|
+
baseMipLevel: destinationMipLevel,
|
|
1848
|
+
mipLevelCount: 1,
|
|
1849
|
+
baseArrayLayer: 0,
|
|
1850
|
+
arrayLayerCount: 1
|
|
1851
|
+
});
|
|
1852
|
+
const computation = new Computation(device, {
|
|
1853
|
+
source: shaderSource,
|
|
1854
|
+
shaderLayout: {
|
|
1855
|
+
bindings: [
|
|
1856
|
+
{
|
|
1857
|
+
type: "texture",
|
|
1858
|
+
name: "sourceTexture",
|
|
1859
|
+
group: 0,
|
|
1860
|
+
location: 0,
|
|
1861
|
+
viewDimension: "3d",
|
|
1862
|
+
sampleType: "float"
|
|
1863
|
+
},
|
|
1864
|
+
{
|
|
1865
|
+
type: "storage",
|
|
1866
|
+
name: "destinationTexture",
|
|
1867
|
+
group: 0,
|
|
1868
|
+
location: 1,
|
|
1869
|
+
format,
|
|
1870
|
+
viewDimension: "3d",
|
|
1871
|
+
access: "write-only"
|
|
1872
|
+
},
|
|
1873
|
+
{ type: "uniform", name: "uniforms", group: 0, location: 2 }
|
|
1874
|
+
]
|
|
1875
|
+
},
|
|
1876
|
+
bindings: {
|
|
1877
|
+
sourceTexture: sourceView,
|
|
1878
|
+
destinationTexture: destinationView,
|
|
1879
|
+
uniforms: uniformsBuffer
|
|
1880
|
+
}
|
|
1881
|
+
});
|
|
1882
|
+
const workgroupsX = Math.ceil(destinationWidth / WORKGROUP_SIZE.x);
|
|
1883
|
+
const workgroupsY = Math.ceil(destinationHeight / WORKGROUP_SIZE.y);
|
|
1884
|
+
const workgroupsZ = Math.ceil(destinationDepth / WORKGROUP_SIZE.z);
|
|
1885
|
+
const computePass = device.beginComputePass({});
|
|
1886
|
+
computation.dispatch(computePass, workgroupsX, workgroupsY, workgroupsZ);
|
|
1887
|
+
computePass.end();
|
|
1888
|
+
device.submit();
|
|
1889
|
+
computation.destroy();
|
|
1890
|
+
sourceView.destroy();
|
|
1891
|
+
destinationView.destroy();
|
|
1892
|
+
sourceWidth = destinationWidth;
|
|
1893
|
+
sourceHeight = destinationHeight;
|
|
1894
|
+
sourceDepth = destinationDepth;
|
|
1895
|
+
}
|
|
1896
|
+
} finally {
|
|
1897
|
+
uniformsBuffer.destroy();
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function validateFormatCapabilities(device, texture, requiredCapabilities, path) {
|
|
1901
|
+
const { format, dimension } = texture;
|
|
1902
|
+
const capabilities = device.getTextureFormatCapabilities(format);
|
|
1903
|
+
const missingCapabilities = requiredCapabilities.filter((capability) => !capabilities[capability]);
|
|
1904
|
+
if (missingCapabilities.length > 0) {
|
|
1905
|
+
const required = requiredCapabilities.join(" + ");
|
|
1906
|
+
const actual = requiredCapabilities.map((capability) => `${capability}=${capabilities[capability]}`).join(", ");
|
|
1907
|
+
throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Required capabilities: ${required}. Actual capabilities: ${actual}.`);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function getSourceTextureType(dimension) {
|
|
1911
|
+
switch (dimension) {
|
|
1912
|
+
case "2d":
|
|
1913
|
+
return "texture_2d<f32>";
|
|
1914
|
+
case "2d-array":
|
|
1915
|
+
return "texture_2d_array<f32>";
|
|
1916
|
+
case "cube":
|
|
1917
|
+
return "texture_cube<f32>";
|
|
1918
|
+
case "cube-array":
|
|
1919
|
+
return "texture_cube_array<f32>";
|
|
1920
|
+
default:
|
|
1921
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
function getRenderMipmapWGSL(dimension) {
|
|
1925
|
+
const sourceSnippet = getRenderMipmapSampleSnippet(dimension);
|
|
1926
|
+
return `
|
|
1927
|
+
struct MipmapUniforms {
|
|
1928
|
+
sourceLayer: u32,
|
|
1929
|
+
};
|
|
1930
|
+
|
|
1931
|
+
fn _touchUniform(uniforms: MipmapUniforms) {
|
|
1932
|
+
let unusedSourceLayer = uniforms.sourceLayer;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
const faceMat = array(
|
|
1936
|
+
mat3x3f(
|
|
1937
|
+
0.0, 0.0, -2.0,
|
|
1938
|
+
0.0, -2.0, 0.0,
|
|
1939
|
+
1.0, 1.0, 1.0
|
|
1940
|
+
), // pos-x
|
|
1941
|
+
mat3x3f(
|
|
1942
|
+
0.0, 0.0, 2.0,
|
|
1943
|
+
0.0, -2.0, 0.0,
|
|
1944
|
+
-1.0, 1.0, -1.0
|
|
1945
|
+
), // neg-x
|
|
1946
|
+
mat3x3f(
|
|
1947
|
+
2.0, 0.0, 0.0,
|
|
1948
|
+
0.0, 0.0, 2.0,
|
|
1949
|
+
-1.0, 1.0, -1.0
|
|
1950
|
+
), // pos-y
|
|
1951
|
+
mat3x3f(
|
|
1952
|
+
2.0, 0.0, 0.0,
|
|
1953
|
+
0.0, 0.0, -2.0,
|
|
1954
|
+
-1.0, -1.0, 1.0
|
|
1955
|
+
), // neg-y
|
|
1956
|
+
mat3x3f(
|
|
1957
|
+
2.0, 0.0, 0.0,
|
|
1958
|
+
0.0, -2.0, 0.0,
|
|
1959
|
+
-1.0, 1.0, 1.0
|
|
1960
|
+
), // pos-z
|
|
1961
|
+
mat3x3f(
|
|
1962
|
+
-2.0, 0.0, 0.0,
|
|
1963
|
+
0.0, -2.0, 0.0,
|
|
1964
|
+
1.0, 1.0, -1.0
|
|
1965
|
+
) // neg-z
|
|
1966
|
+
);
|
|
1967
|
+
|
|
1968
|
+
struct FragmentInputs {
|
|
1969
|
+
@builtin(position) position: vec4f,
|
|
1970
|
+
@location(0) texcoord: vec2f
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
struct VertexOutput {
|
|
1974
|
+
@builtin(position) position: vec4f,
|
|
1975
|
+
@location(0) texcoord: vec2f
|
|
1976
|
+
};
|
|
1977
|
+
|
|
1978
|
+
@group(0) @binding(0) var sourceSampler: sampler;
|
|
1979
|
+
@group(0) @binding(1) var sourceTexture: ${getSourceTextureType(dimension)};
|
|
1980
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
1981
|
+
|
|
1982
|
+
@vertex
|
|
1983
|
+
fn vertexMain(
|
|
1984
|
+
@builtin(vertex_index) vertexIndex: u32
|
|
1985
|
+
) -> VertexOutput {
|
|
1986
|
+
const positions = array(
|
|
1987
|
+
vec2f(-1.0, -1.0),
|
|
1988
|
+
vec2f(-1.0, 3.0),
|
|
1989
|
+
vec2f( 3.0, -1.0)
|
|
1990
|
+
);
|
|
1991
|
+
|
|
1992
|
+
let xy = positions[vertexIndex];
|
|
1993
|
+
return VertexOutput(
|
|
1994
|
+
vec4f(xy, 0.0, 1.0),
|
|
1995
|
+
xy * vec2f(0.5, -0.5) + vec2f(0.5)
|
|
1996
|
+
);
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
@fragment
|
|
2000
|
+
fn fragmentMain(fsInput: VertexOutput) -> @location(0) vec4f {
|
|
2001
|
+
_touchUniform(uniforms);
|
|
2002
|
+
return ${sourceSnippet};
|
|
2003
|
+
}
|
|
2004
|
+
`;
|
|
2005
|
+
}
|
|
2006
|
+
function getRenderMipmapSampleSnippet(dimension) {
|
|
2007
|
+
const layer = "uniforms.sourceLayer";
|
|
2008
|
+
switch (dimension) {
|
|
2009
|
+
case "2d":
|
|
2010
|
+
return "textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, 0.0)";
|
|
2011
|
+
case "2d-array":
|
|
2012
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, i32(${layer}), 0.0)`;
|
|
2013
|
+
case "cube":
|
|
2014
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer})] * vec3f(fract(fsInput.texcoord), 1.0), 0.0)`;
|
|
2015
|
+
case "cube-array":
|
|
2016
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer} % 6u)] * vec3f(fract(fsInput.texcoord), 1.0), i32(${layer} / 6u), 0.0)`;
|
|
2017
|
+
default:
|
|
2018
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
function get3DComputeMipmapWGSL(format) {
|
|
2022
|
+
return `
|
|
2023
|
+
struct MipmapUniforms {
|
|
2024
|
+
sourceWidth: u32,
|
|
2025
|
+
sourceHeight: u32,
|
|
2026
|
+
sourceDepth: u32,
|
|
2027
|
+
destinationWidth: u32,
|
|
2028
|
+
destinationHeight: u32,
|
|
2029
|
+
destinationDepth: u32,
|
|
2030
|
+
padding: u32,
|
|
2031
|
+
};
|
|
2032
|
+
|
|
2033
|
+
@group(0) @binding(0) var sourceTexture: texture_3d<f32>;
|
|
2034
|
+
@group(0) @binding(1) var destinationTexture: texture_storage_3d<${format}, write>;
|
|
2035
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
2036
|
+
|
|
2037
|
+
@compute @workgroup_size(${WORKGROUP_SIZE.x}, ${WORKGROUP_SIZE.y}, ${WORKGROUP_SIZE.z})
|
|
2038
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
2039
|
+
if (
|
|
2040
|
+
id.x >= uniforms.destinationWidth ||
|
|
2041
|
+
id.y >= uniforms.destinationHeight ||
|
|
2042
|
+
id.z >= uniforms.destinationDepth
|
|
2043
|
+
) {
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
let sourceBase = id * 2u;
|
|
2048
|
+
let sourceX0 = min(sourceBase.x, uniforms.sourceWidth - 1u);
|
|
2049
|
+
let sourceY0 = min(sourceBase.y, uniforms.sourceHeight - 1u);
|
|
2050
|
+
let sourceZ0 = min(sourceBase.z, uniforms.sourceDepth - 1u);
|
|
2051
|
+
|
|
2052
|
+
let sourceX1 = min(sourceBase.x + 1u, uniforms.sourceWidth - 1u);
|
|
2053
|
+
let sourceY1 = min(sourceBase.y + 1u, uniforms.sourceHeight - 1u);
|
|
2054
|
+
let sourceZ1 = min(sourceBase.z + 1u, uniforms.sourceDepth - 1u);
|
|
2055
|
+
|
|
2056
|
+
var sum = textureLoad(
|
|
2057
|
+
sourceTexture,
|
|
2058
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ0)),
|
|
2059
|
+
0
|
|
2060
|
+
);
|
|
2061
|
+
sum += textureLoad(
|
|
2062
|
+
sourceTexture,
|
|
2063
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ0)),
|
|
2064
|
+
0
|
|
2065
|
+
);
|
|
2066
|
+
sum += textureLoad(
|
|
2067
|
+
sourceTexture,
|
|
2068
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ0)),
|
|
2069
|
+
0
|
|
2070
|
+
);
|
|
2071
|
+
sum += textureLoad(
|
|
2072
|
+
sourceTexture,
|
|
2073
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ0)),
|
|
2074
|
+
0
|
|
2075
|
+
);
|
|
2076
|
+
sum += textureLoad(
|
|
2077
|
+
sourceTexture,
|
|
2078
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ1)),
|
|
2079
|
+
0
|
|
2080
|
+
);
|
|
2081
|
+
sum += textureLoad(
|
|
2082
|
+
sourceTexture,
|
|
2083
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ1)),
|
|
2084
|
+
0
|
|
2085
|
+
);
|
|
2086
|
+
sum += textureLoad(
|
|
2087
|
+
sourceTexture,
|
|
2088
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ1)),
|
|
2089
|
+
0
|
|
2090
|
+
);
|
|
2091
|
+
sum += textureLoad(
|
|
2092
|
+
sourceTexture,
|
|
2093
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ1)),
|
|
2094
|
+
0
|
|
2095
|
+
);
|
|
2096
|
+
|
|
2097
|
+
textureStore(
|
|
2098
|
+
destinationTexture,
|
|
2099
|
+
vec3<i32>(i32(id.x), i32(id.y), i32(id.z)),
|
|
2100
|
+
vec4<f32>(sum.xyz / 8.0, sum.w / 8.0)
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
`;
|
|
1336
2104
|
}
|
|
1337
2105
|
|
|
1338
|
-
// dist/
|
|
1339
|
-
var
|
|
1340
|
-
var CubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
|
|
1341
|
-
var _AsyncTexture = class {
|
|
2106
|
+
// dist/dynamic-texture/dynamic-texture.js
|
|
2107
|
+
var _DynamicTexture = class {
|
|
1342
2108
|
device;
|
|
1343
2109
|
id;
|
|
2110
|
+
/** Props with defaults resolved (except `data` which is processed separately) */
|
|
1344
2111
|
props;
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
// @ts-expect-error
|
|
1351
|
-
view;
|
|
2112
|
+
/** Created resources */
|
|
2113
|
+
_texture = null;
|
|
2114
|
+
_sampler = null;
|
|
2115
|
+
_view = null;
|
|
2116
|
+
/** Ready when GPU texture has been created and data (if any) uploaded */
|
|
1352
2117
|
ready;
|
|
1353
2118
|
isReady = false;
|
|
1354
2119
|
destroyed = false;
|
|
@@ -1356,272 +2121,283 @@ var _AsyncTexture = class {
|
|
|
1356
2121
|
};
|
|
1357
2122
|
rejectReady = () => {
|
|
1358
2123
|
};
|
|
2124
|
+
get texture() {
|
|
2125
|
+
if (!this._texture)
|
|
2126
|
+
throw new Error("Texture not initialized yet");
|
|
2127
|
+
return this._texture;
|
|
2128
|
+
}
|
|
2129
|
+
get sampler() {
|
|
2130
|
+
if (!this._sampler)
|
|
2131
|
+
throw new Error("Sampler not initialized yet");
|
|
2132
|
+
return this._sampler;
|
|
2133
|
+
}
|
|
2134
|
+
get view() {
|
|
2135
|
+
if (!this._view)
|
|
2136
|
+
throw new Error("View not initialized yet");
|
|
2137
|
+
return this._view;
|
|
2138
|
+
}
|
|
1359
2139
|
get [Symbol.toStringTag]() {
|
|
1360
|
-
return "
|
|
2140
|
+
return "DynamicTexture";
|
|
1361
2141
|
}
|
|
1362
2142
|
toString() {
|
|
1363
|
-
return `
|
|
2143
|
+
return `DynamicTexture:"${this.id}":${this.texture.width}x${this.texture.height}px:(${this.isReady ? "ready" : "loading..."})`;
|
|
1364
2144
|
}
|
|
1365
2145
|
constructor(device, props) {
|
|
1366
2146
|
this.device = device;
|
|
1367
|
-
const id = uid("
|
|
1368
|
-
|
|
2147
|
+
const id = uid("dynamic-texture");
|
|
2148
|
+
const originalPropsWithAsyncData = props;
|
|
2149
|
+
this.props = { ..._DynamicTexture.defaultProps, id, ...props, data: null };
|
|
1369
2150
|
this.id = this.props.id;
|
|
1370
|
-
props = { ...props };
|
|
1371
|
-
if (typeof (props == null ? void 0 : props.data) === "string" && props.dimension === "2d") {
|
|
1372
|
-
props.data = loadImageBitmap(props.data);
|
|
1373
|
-
}
|
|
1374
|
-
if (props.mipmaps) {
|
|
1375
|
-
props.mipLevels = "auto";
|
|
1376
|
-
}
|
|
1377
2151
|
this.ready = new Promise((resolve, reject) => {
|
|
1378
|
-
this.resolveReady =
|
|
1379
|
-
this.isReady = true;
|
|
1380
|
-
resolve();
|
|
1381
|
-
};
|
|
2152
|
+
this.resolveReady = resolve;
|
|
1382
2153
|
this.rejectReady = reject;
|
|
1383
2154
|
});
|
|
1384
|
-
this.initAsync(
|
|
2155
|
+
this.initAsync(originalPropsWithAsyncData);
|
|
1385
2156
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
case "1d":
|
|
1405
|
-
this._setTexture1DData(this.texture, data);
|
|
1406
|
-
break;
|
|
1407
|
-
case "2d":
|
|
1408
|
-
this._setTexture2DData(data);
|
|
1409
|
-
break;
|
|
1410
|
-
case "3d":
|
|
1411
|
-
this._setTexture3DData(this.texture, data);
|
|
1412
|
-
break;
|
|
1413
|
-
case "2d-array":
|
|
1414
|
-
this._setTextureArrayData(this.texture, data);
|
|
1415
|
-
break;
|
|
1416
|
-
case "cube":
|
|
1417
|
-
this._setTextureCubeData(this.texture, data);
|
|
1418
|
-
break;
|
|
1419
|
-
case "cube-array":
|
|
1420
|
-
this._setTextureCubeArrayData(this.texture, data);
|
|
1421
|
-
break;
|
|
2157
|
+
/** @note Fire and forget; caller can await `ready` */
|
|
2158
|
+
async initAsync(originalPropsWithAsyncData) {
|
|
2159
|
+
try {
|
|
2160
|
+
const propsWithSyncData = await this._loadAllData(originalPropsWithAsyncData);
|
|
2161
|
+
this._checkNotDestroyed();
|
|
2162
|
+
const deduceSize = () => {
|
|
2163
|
+
if (this.props.width && this.props.height) {
|
|
2164
|
+
return { width: this.props.width, height: this.props.height };
|
|
2165
|
+
}
|
|
2166
|
+
const size2 = getTextureSizeFromData(propsWithSyncData);
|
|
2167
|
+
if (size2) {
|
|
2168
|
+
return size2;
|
|
2169
|
+
}
|
|
2170
|
+
return { width: this.props.width || 1, height: this.props.height || 1 };
|
|
2171
|
+
};
|
|
2172
|
+
const size = deduceSize();
|
|
2173
|
+
if (!size || size.width <= 0 || size.height <= 0) {
|
|
2174
|
+
throw new Error(`${this} size could not be determined or was zero`);
|
|
1422
2175
|
}
|
|
2176
|
+
const baseTextureProps = {
|
|
2177
|
+
...this.props,
|
|
2178
|
+
...size,
|
|
2179
|
+
mipLevels: 1,
|
|
2180
|
+
// temporary; updated below
|
|
2181
|
+
data: void 0
|
|
2182
|
+
};
|
|
2183
|
+
if (this.device.type === "webgpu" && this.props.mipmaps) {
|
|
2184
|
+
const requiredUsage = this.props.dimension === "3d" ? import_core11.Texture.SAMPLE | import_core11.Texture.STORAGE | import_core11.Texture.COPY_DST | import_core11.Texture.COPY_SRC : import_core11.Texture.SAMPLE | import_core11.Texture.RENDER | import_core11.Texture.COPY_DST | import_core11.Texture.COPY_SRC;
|
|
2185
|
+
baseTextureProps.usage |= requiredUsage;
|
|
2186
|
+
}
|
|
2187
|
+
const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
|
|
2188
|
+
const desired = this.props.mipLevels === "auto" ? maxMips : Math.max(1, Math.min(maxMips, this.props.mipLevels ?? 1));
|
|
2189
|
+
const finalTextureProps = { ...baseTextureProps, mipLevels: desired };
|
|
2190
|
+
this._texture = this.device.createTexture(finalTextureProps);
|
|
2191
|
+
this._sampler = this.texture.sampler;
|
|
2192
|
+
this._view = this.texture.view;
|
|
2193
|
+
if (propsWithSyncData.data) {
|
|
2194
|
+
switch (propsWithSyncData.dimension) {
|
|
2195
|
+
case "1d":
|
|
2196
|
+
this.setTexture1DData(propsWithSyncData.data);
|
|
2197
|
+
break;
|
|
2198
|
+
case "2d":
|
|
2199
|
+
this.setTexture2DData(propsWithSyncData.data);
|
|
2200
|
+
break;
|
|
2201
|
+
case "3d":
|
|
2202
|
+
this.setTexture3DData(propsWithSyncData.data);
|
|
2203
|
+
break;
|
|
2204
|
+
case "2d-array":
|
|
2205
|
+
this.setTextureArrayData(propsWithSyncData.data);
|
|
2206
|
+
break;
|
|
2207
|
+
case "cube":
|
|
2208
|
+
this.setTextureCubeData(propsWithSyncData.data);
|
|
2209
|
+
break;
|
|
2210
|
+
case "cube-array":
|
|
2211
|
+
this.setTextureCubeArrayData(propsWithSyncData.data);
|
|
2212
|
+
break;
|
|
2213
|
+
default: {
|
|
2214
|
+
throw new Error(`Unhandled dimension ${propsWithSyncData.dimension}`);
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
if (this.props.mipmaps) {
|
|
2219
|
+
this.generateMipmaps();
|
|
2220
|
+
}
|
|
2221
|
+
this.isReady = true;
|
|
2222
|
+
this.resolveReady(this.texture);
|
|
2223
|
+
import_core11.log.info(0, `${this} created`)();
|
|
2224
|
+
} catch (e) {
|
|
2225
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
2226
|
+
this.rejectReady(err);
|
|
2227
|
+
throw err;
|
|
1423
2228
|
}
|
|
1424
|
-
if (this.props.mipmaps) {
|
|
1425
|
-
this.generateMipmaps();
|
|
1426
|
-
}
|
|
1427
|
-
import_core8.log.info(1, `${this} loaded`);
|
|
1428
|
-
this.resolveReady();
|
|
1429
2229
|
}
|
|
1430
2230
|
destroy() {
|
|
1431
|
-
if (this.
|
|
1432
|
-
this.
|
|
1433
|
-
this.
|
|
2231
|
+
if (this._texture) {
|
|
2232
|
+
this._texture.destroy();
|
|
2233
|
+
this._texture = null;
|
|
2234
|
+
this._sampler = null;
|
|
2235
|
+
this._view = null;
|
|
1434
2236
|
}
|
|
1435
2237
|
this.destroyed = true;
|
|
1436
2238
|
}
|
|
1437
2239
|
generateMipmaps() {
|
|
1438
|
-
this.
|
|
2240
|
+
if (this.device.type === "webgl") {
|
|
2241
|
+
this.texture.generateMipmapsWebGL();
|
|
2242
|
+
} else if (this.device.type === "webgpu") {
|
|
2243
|
+
generateMipmap(this.device, this.texture);
|
|
2244
|
+
} else {
|
|
2245
|
+
import_core11.log.warn(`${this} mipmaps not supported on ${this.device.type}`);
|
|
2246
|
+
}
|
|
1439
2247
|
}
|
|
1440
|
-
/** Set sampler or create
|
|
2248
|
+
/** Set sampler or create one from props */
|
|
1441
2249
|
setSampler(sampler = {}) {
|
|
1442
|
-
this.
|
|
2250
|
+
this._checkReady();
|
|
2251
|
+
const s = sampler instanceof import_core11.Sampler ? sampler : this.device.createSampler(sampler);
|
|
2252
|
+
this.texture.setSampler(s);
|
|
2253
|
+
this._sampler = s;
|
|
1443
2254
|
}
|
|
1444
2255
|
/**
|
|
1445
|
-
*
|
|
1446
|
-
*
|
|
1447
|
-
* @note Does not copy contents of the texture
|
|
1448
|
-
* @note Mipmaps may need to be regenerated after resizing / setting new data
|
|
1449
|
-
* @todo Abort pending promise and create a texture with the new size?
|
|
2256
|
+
* Resize by cloning the underlying immutable texture.
|
|
2257
|
+
* Does not copy contents; caller may need to re-upload and/or regenerate mips.
|
|
1450
2258
|
*/
|
|
1451
2259
|
resize(size) {
|
|
1452
|
-
|
|
1453
|
-
throw new Error("Cannot resize texture before it is ready");
|
|
1454
|
-
}
|
|
2260
|
+
this._checkReady();
|
|
1455
2261
|
if (size.width === this.texture.width && size.height === this.texture.height) {
|
|
1456
2262
|
return false;
|
|
1457
2263
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
2264
|
+
const prev = this.texture;
|
|
2265
|
+
this._texture = prev.clone(size);
|
|
2266
|
+
this._sampler = this.texture.sampler;
|
|
2267
|
+
this._view = this.texture.view;
|
|
2268
|
+
prev.destroy();
|
|
2269
|
+
import_core11.log.info(`${this} resized`);
|
|
1463
2270
|
return true;
|
|
1464
2271
|
}
|
|
1465
|
-
/**
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
2272
|
+
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
2273
|
+
getCubeFaceIndex(face) {
|
|
2274
|
+
const index = TEXTURE_CUBE_FACE_MAP[face];
|
|
2275
|
+
if (index === void 0)
|
|
2276
|
+
throw new Error(`Invalid cube face: ${face}`);
|
|
2277
|
+
return index;
|
|
2278
|
+
}
|
|
2279
|
+
/** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
|
|
2280
|
+
getCubeArrayFaceIndex(cubeIndex, face) {
|
|
2281
|
+
return 6 * cubeIndex + this.getCubeFaceIndex(face);
|
|
2282
|
+
}
|
|
2283
|
+
/** @note experimental: Set multiple mip levels (1D) */
|
|
2284
|
+
setTexture1DData(data) {
|
|
2285
|
+
this._checkReady();
|
|
2286
|
+
if (this.texture.props.dimension !== "1d") {
|
|
2287
|
+
throw new Error(`${this} is not 1d`);
|
|
2288
|
+
}
|
|
2289
|
+
const subresources = getTexture1DSubresources(data);
|
|
2290
|
+
this._setTextureSubresources(subresources);
|
|
2291
|
+
}
|
|
2292
|
+
/** @note experimental: Set multiple mip levels (2D), optionally at `z`, slice (depth/array level) index */
|
|
2293
|
+
setTexture2DData(lodData, z = 0) {
|
|
2294
|
+
this._checkReady();
|
|
2295
|
+
if (this.texture.props.dimension !== "2d") {
|
|
2296
|
+
throw new Error(`${this} is not 2d`);
|
|
2297
|
+
}
|
|
2298
|
+
const subresources = getTexture2DSubresources(z, lodData);
|
|
2299
|
+
this._setTextureSubresources(subresources);
|
|
2300
|
+
}
|
|
2301
|
+
/** 3D: multiple depth slices, each may carry multiple mip levels */
|
|
2302
|
+
setTexture3DData(data) {
|
|
2303
|
+
if (this.texture.props.dimension !== "3d") {
|
|
2304
|
+
throw new Error(`${this} is not 3d`);
|
|
2305
|
+
}
|
|
2306
|
+
const subresources = getTexture3DSubresources(data);
|
|
2307
|
+
this._setTextureSubresources(subresources);
|
|
2308
|
+
}
|
|
2309
|
+
/** 2D array: multiple layers, each may carry multiple mip levels */
|
|
2310
|
+
setTextureArrayData(data) {
|
|
2311
|
+
if (this.texture.props.dimension !== "2d-array") {
|
|
2312
|
+
throw new Error(`${this} is not 2d-array`);
|
|
2313
|
+
}
|
|
2314
|
+
const subresources = getTextureArraySubresources(data);
|
|
2315
|
+
this._setTextureSubresources(subresources);
|
|
2316
|
+
}
|
|
2317
|
+
/** Cube: 6 faces, each may carry multiple mip levels */
|
|
2318
|
+
setTextureCubeData(data) {
|
|
2319
|
+
if (this.texture.props.dimension !== "cube") {
|
|
2320
|
+
throw new Error(`${this} is not cube`);
|
|
2321
|
+
}
|
|
2322
|
+
const subresources = getTextureCubeSubresources(data);
|
|
2323
|
+
this._setTextureSubresources(subresources);
|
|
2324
|
+
}
|
|
2325
|
+
/** Cube array: multiple cubes (faces×layers), each face may carry multiple mips */
|
|
2326
|
+
setTextureCubeArrayData(data) {
|
|
2327
|
+
if (this.texture.props.dimension !== "cube-array") {
|
|
2328
|
+
throw new Error(`${this} is not cube-array`);
|
|
2329
|
+
}
|
|
2330
|
+
const subresources = getTextureCubeArraySubresources(data);
|
|
2331
|
+
this._setTextureSubresources(subresources);
|
|
2332
|
+
}
|
|
2333
|
+
/** Sets multiple mip levels on different `z` slices (depth/array index) */
|
|
2334
|
+
_setTextureSubresources(subresources) {
|
|
2335
|
+
for (const subresource of subresources) {
|
|
2336
|
+
const { z, mipLevel } = subresource;
|
|
2337
|
+
switch (subresource.type) {
|
|
2338
|
+
case "external-image":
|
|
2339
|
+
const { image, flipY } = subresource;
|
|
2340
|
+
this.texture.copyExternalImage({ image, z, mipLevel, flipY });
|
|
2341
|
+
break;
|
|
2342
|
+
case "texture-data":
|
|
2343
|
+
const { data } = subresource;
|
|
2344
|
+
this.texture.writeData(getAlignedUploadData(this.texture, data), {
|
|
2345
|
+
x: 0,
|
|
2346
|
+
y: 0,
|
|
2347
|
+
z,
|
|
2348
|
+
width: data.width,
|
|
2349
|
+
height: data.height,
|
|
2350
|
+
depthOrArrayLayers: 1,
|
|
2351
|
+
mipLevel
|
|
2352
|
+
});
|
|
2353
|
+
break;
|
|
2354
|
+
default:
|
|
2355
|
+
throw new Error("Unsupported 2D mip-level payload");
|
|
1532
2356
|
}
|
|
1533
2357
|
}
|
|
1534
2358
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "3d") {
|
|
1542
|
-
throw new Error(this.id);
|
|
1543
|
-
}
|
|
1544
|
-
for (let depth = 0; depth < data.length; depth++) {
|
|
1545
|
-
this._setTexture2DData(data[depth], depth);
|
|
1546
|
-
}
|
|
2359
|
+
// ------------------ helpers ------------------
|
|
2360
|
+
/** Recursively resolve all promises in data structures */
|
|
2361
|
+
async _loadAllData(props) {
|
|
2362
|
+
const syncData = await awaitAllPromises(props.data);
|
|
2363
|
+
const dimension = props.dimension ?? "2d";
|
|
2364
|
+
return { dimension, data: syncData ?? null };
|
|
1547
2365
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
* @param data
|
|
1552
|
-
* @param index
|
|
1553
|
-
*/
|
|
1554
|
-
_setTextureCubeData(texture, data) {
|
|
1555
|
-
var _a;
|
|
1556
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "cube") {
|
|
1557
|
-
throw new Error(this.id);
|
|
1558
|
-
}
|
|
1559
|
-
for (const [face, faceData] of Object.entries(data)) {
|
|
1560
|
-
const faceDepth = CubeFaces.indexOf(face);
|
|
1561
|
-
this._setTexture2DData(faceData, faceDepth);
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
/**
|
|
1565
|
-
* Experimental: Sets texture array data, multiple levels, multiple depth slices
|
|
1566
|
-
* @param data
|
|
1567
|
-
*/
|
|
1568
|
-
_setTextureArrayData(texture, data) {
|
|
1569
|
-
var _a;
|
|
1570
|
-
if (((_a = this.texture) == null ? void 0 : _a.props.dimension) !== "2d-array") {
|
|
1571
|
-
throw new Error(this.id);
|
|
1572
|
-
}
|
|
1573
|
-
for (let depth = 0; depth < data.length; depth++) {
|
|
1574
|
-
this._setTexture2DData(data[depth], depth);
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
/**
|
|
1578
|
-
* Experimental: Sets texture cube array, multiple faces, multiple levels, multiple mip levels
|
|
1579
|
-
* @param data
|
|
1580
|
-
*/
|
|
1581
|
-
_setTextureCubeArrayData(texture, data) {
|
|
1582
|
-
throw new Error("setTextureCubeArrayData not supported in WebGL2.");
|
|
1583
|
-
}
|
|
1584
|
-
/** Experimental */
|
|
1585
|
-
_setTextureCubeFaceData(texture, lodData, face, depth = 0) {
|
|
1586
|
-
if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
|
|
1587
|
-
import_core8.log.warn(`${this.id} has mipmap and multiple LODs.`)();
|
|
2366
|
+
_checkNotDestroyed() {
|
|
2367
|
+
if (this.destroyed) {
|
|
2368
|
+
import_core11.log.warn(`${this} already destroyed`);
|
|
1588
2369
|
}
|
|
1589
|
-
const faceDepth = TextureCubeFaces.indexOf(face);
|
|
1590
|
-
this._setTexture2DData(lodData, faceDepth);
|
|
1591
2370
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
* @param options
|
|
1596
|
-
* @returns array of TextureImageData / ExternalImages
|
|
1597
|
-
*/
|
|
1598
|
-
_normalizeTextureData(data) {
|
|
1599
|
-
const options = this.texture;
|
|
1600
|
-
let mipLevelArray;
|
|
1601
|
-
if (ArrayBuffer.isView(data)) {
|
|
1602
|
-
mipLevelArray = [
|
|
1603
|
-
{
|
|
1604
|
-
// ts-expect-error does data really need to be Uint8ClampedArray?
|
|
1605
|
-
data,
|
|
1606
|
-
width: options.width,
|
|
1607
|
-
height: options.height
|
|
1608
|
-
// depth: options.depth
|
|
1609
|
-
}
|
|
1610
|
-
];
|
|
1611
|
-
} else if (!Array.isArray(data)) {
|
|
1612
|
-
mipLevelArray = [data];
|
|
1613
|
-
} else {
|
|
1614
|
-
mipLevelArray = data;
|
|
2371
|
+
_checkReady() {
|
|
2372
|
+
if (!this.isReady) {
|
|
2373
|
+
import_core11.log.warn(`${this} Cannot perform this operation before ready`);
|
|
1615
2374
|
}
|
|
1616
|
-
return mipLevelArray;
|
|
1617
2375
|
}
|
|
1618
2376
|
};
|
|
1619
|
-
var
|
|
1620
|
-
__publicField(
|
|
1621
|
-
...
|
|
2377
|
+
var DynamicTexture = _DynamicTexture;
|
|
2378
|
+
__publicField(DynamicTexture, "defaultProps", {
|
|
2379
|
+
...import_core11.Texture.defaultProps,
|
|
2380
|
+
dimension: "2d",
|
|
1622
2381
|
data: null,
|
|
1623
2382
|
mipmaps: false
|
|
1624
2383
|
});
|
|
2384
|
+
function getAlignedUploadData(texture, data) {
|
|
2385
|
+
const { width, height, data: uploadData } = data;
|
|
2386
|
+
const { bytesPerPixel } = texture.device.getTextureFormatInfo(texture.format);
|
|
2387
|
+
const bytesPerRow = width * bytesPerPixel;
|
|
2388
|
+
const alignedBytesPerRow = Math.ceil(bytesPerRow / texture.byteAlignment) * texture.byteAlignment;
|
|
2389
|
+
if (alignedBytesPerRow === bytesPerRow) {
|
|
2390
|
+
return uploadData;
|
|
2391
|
+
}
|
|
2392
|
+
const sourceBytes = new Uint8Array(uploadData.buffer, uploadData.byteOffset, uploadData.byteLength);
|
|
2393
|
+
const paddedBytes = new Uint8Array(alignedBytesPerRow * height);
|
|
2394
|
+
for (let row = 0; row < height; row++) {
|
|
2395
|
+
const sourceOffset = row * bytesPerRow;
|
|
2396
|
+
const destinationOffset = row * alignedBytesPerRow;
|
|
2397
|
+
paddedBytes.set(sourceBytes.subarray(sourceOffset, sourceOffset + bytesPerRow), destinationOffset);
|
|
2398
|
+
}
|
|
2399
|
+
return paddedBytes;
|
|
2400
|
+
}
|
|
1625
2401
|
async function awaitAllPromises(x) {
|
|
1626
2402
|
x = await x;
|
|
1627
2403
|
if (Array.isArray(x)) {
|
|
@@ -1641,19 +2417,27 @@ async function awaitAllPromises(x) {
|
|
|
1641
2417
|
}
|
|
1642
2418
|
|
|
1643
2419
|
// dist/model/model.js
|
|
1644
|
-
var
|
|
1645
|
-
var
|
|
2420
|
+
var LOG_DRAW_PRIORITY2 = 2;
|
|
2421
|
+
var LOG_DRAW_TIMEOUT2 = 1e4;
|
|
1646
2422
|
var _Model = class {
|
|
2423
|
+
/** Device that created this model */
|
|
1647
2424
|
device;
|
|
2425
|
+
/** Application provided identifier */
|
|
1648
2426
|
id;
|
|
2427
|
+
/** WGSL shader source when using unified shader */
|
|
1649
2428
|
// @ts-expect-error assigned in function called from constructor
|
|
1650
2429
|
source;
|
|
2430
|
+
/** GLSL vertex shader source */
|
|
1651
2431
|
// @ts-expect-error assigned in function called from constructor
|
|
1652
2432
|
vs;
|
|
2433
|
+
/** GLSL fragment shader source */
|
|
1653
2434
|
// @ts-expect-error assigned in function called from constructor
|
|
1654
2435
|
fs;
|
|
2436
|
+
/** Factory used to create render pipelines */
|
|
1655
2437
|
pipelineFactory;
|
|
2438
|
+
/** Factory used to create shaders */
|
|
1656
2439
|
shaderFactory;
|
|
2440
|
+
/** User-supplied per-model data */
|
|
1657
2441
|
userData = {};
|
|
1658
2442
|
// Fixed properties (change can trigger pipeline rebuild)
|
|
1659
2443
|
/** The render pipeline GPU parameters, depth testing etc */
|
|
@@ -1716,7 +2500,7 @@ var _Model = class {
|
|
|
1716
2500
|
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
1717
2501
|
const shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap, { disableWarnings: this.props.disableWarnings });
|
|
1718
2502
|
this.setShaderInputs(shaderInputs);
|
|
1719
|
-
const platformInfo =
|
|
2503
|
+
const platformInfo = getPlatformInfo2(device);
|
|
1720
2504
|
const modules = (
|
|
1721
2505
|
// @ts-ignore shaderInputs is assigned in setShaderInputs above.
|
|
1722
2506
|
(((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || []
|
|
@@ -1730,7 +2514,7 @@ var _Model = class {
|
|
|
1730
2514
|
});
|
|
1731
2515
|
this.source = source3;
|
|
1732
2516
|
this._getModuleUniforms = getUniforms2;
|
|
1733
|
-
this.props.shaderLayout ||=
|
|
2517
|
+
this.props.shaderLayout ||= device.getShaderLayout(this.source);
|
|
1734
2518
|
} else {
|
|
1735
2519
|
const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
|
|
1736
2520
|
platformInfo,
|
|
@@ -1783,7 +2567,6 @@ var _Model = class {
|
|
|
1783
2567
|
if (props.transformFeedback) {
|
|
1784
2568
|
this.transformFeedback = props.transformFeedback;
|
|
1785
2569
|
}
|
|
1786
|
-
Object.seal(this);
|
|
1787
2570
|
}
|
|
1788
2571
|
destroy() {
|
|
1789
2572
|
var _a;
|
|
@@ -1812,14 +2595,20 @@ var _Model = class {
|
|
|
1812
2595
|
setNeedsRedraw(reason) {
|
|
1813
2596
|
this._needsRedraw ||= reason;
|
|
1814
2597
|
}
|
|
2598
|
+
/** Update uniforms and pipeline state prior to drawing. */
|
|
1815
2599
|
predraw() {
|
|
1816
2600
|
this.updateShaderInputs();
|
|
1817
2601
|
this.pipeline = this._updatePipeline();
|
|
1818
2602
|
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Issue one draw call.
|
|
2605
|
+
* @param renderPass - render pass to draw into
|
|
2606
|
+
* @returns `true` if the draw call was executed, `false` if resources were not ready.
|
|
2607
|
+
*/
|
|
1819
2608
|
draw(renderPass) {
|
|
1820
2609
|
const loadingBinding = this._areBindingsLoading();
|
|
1821
2610
|
if (loadingBinding) {
|
|
1822
|
-
|
|
2611
|
+
import_core12.log.info(LOG_DRAW_PRIORITY2, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
|
|
1823
2612
|
return false;
|
|
1824
2613
|
}
|
|
1825
2614
|
try {
|
|
@@ -1947,7 +2736,7 @@ var _Model = class {
|
|
|
1947
2736
|
/** Set the shader inputs */
|
|
1948
2737
|
setShaderInputs(shaderInputs) {
|
|
1949
2738
|
this.shaderInputs = shaderInputs;
|
|
1950
|
-
this._uniformStore = new
|
|
2739
|
+
this._uniformStore = new import_core12.UniformStore(this.shaderInputs.modules);
|
|
1951
2740
|
for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
|
|
1952
2741
|
if (shaderModuleHasUniforms(module2)) {
|
|
1953
2742
|
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
@@ -1991,7 +2780,7 @@ var _Model = class {
|
|
|
1991
2780
|
setAttributes(buffers, options) {
|
|
1992
2781
|
const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
|
|
1993
2782
|
if (buffers["indices"]) {
|
|
1994
|
-
|
|
2783
|
+
import_core12.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
|
|
1995
2784
|
}
|
|
1996
2785
|
this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(this.pipeline.shaderLayout, this.bufferLayout);
|
|
1997
2786
|
const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
|
|
@@ -1999,7 +2788,7 @@ var _Model = class {
|
|
|
1999
2788
|
const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
|
|
2000
2789
|
if (!bufferLayout) {
|
|
2001
2790
|
if (!disableWarnings) {
|
|
2002
|
-
|
|
2791
|
+
import_core12.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
|
|
2003
2792
|
}
|
|
2004
2793
|
continue;
|
|
2005
2794
|
}
|
|
@@ -2014,7 +2803,7 @@ var _Model = class {
|
|
|
2014
2803
|
}
|
|
2015
2804
|
}
|
|
2016
2805
|
if (!set && !disableWarnings) {
|
|
2017
|
-
|
|
2806
|
+
import_core12.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
|
|
2018
2807
|
}
|
|
2019
2808
|
}
|
|
2020
2809
|
this.setNeedsRedraw("attributes");
|
|
@@ -2033,7 +2822,7 @@ var _Model = class {
|
|
|
2033
2822
|
if (attributeInfo) {
|
|
2034
2823
|
this.vertexArray.setConstantWebGL(attributeInfo.location, value);
|
|
2035
2824
|
} else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
|
|
2036
|
-
|
|
2825
|
+
import_core12.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
|
|
2037
2826
|
}
|
|
2038
2827
|
}
|
|
2039
2828
|
this.setNeedsRedraw("constants");
|
|
@@ -2042,7 +2831,7 @@ var _Model = class {
|
|
|
2042
2831
|
/** Check that bindings are loaded. Returns id of first binding that is still loading. */
|
|
2043
2832
|
_areBindingsLoading() {
|
|
2044
2833
|
for (const binding of Object.values(this.bindings)) {
|
|
2045
|
-
if (binding instanceof
|
|
2834
|
+
if (binding instanceof DynamicTexture && !binding.isReady) {
|
|
2046
2835
|
return binding.id;
|
|
2047
2836
|
}
|
|
2048
2837
|
}
|
|
@@ -2052,7 +2841,7 @@ var _Model = class {
|
|
|
2052
2841
|
_getBindings() {
|
|
2053
2842
|
const validBindings = {};
|
|
2054
2843
|
for (const [name, binding] of Object.entries(this.bindings)) {
|
|
2055
|
-
if (binding instanceof
|
|
2844
|
+
if (binding instanceof DynamicTexture) {
|
|
2056
2845
|
if (binding.isReady) {
|
|
2057
2846
|
validBindings[name] = binding.texture;
|
|
2058
2847
|
}
|
|
@@ -2066,16 +2855,16 @@ var _Model = class {
|
|
|
2066
2855
|
_getBindingsUpdateTimestamp() {
|
|
2067
2856
|
let timestamp = 0;
|
|
2068
2857
|
for (const binding of Object.values(this.bindings)) {
|
|
2069
|
-
if (binding instanceof
|
|
2858
|
+
if (binding instanceof import_core12.TextureView) {
|
|
2070
2859
|
timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
|
|
2071
|
-
} else if (binding instanceof
|
|
2860
|
+
} else if (binding instanceof import_core12.Buffer || binding instanceof import_core12.Texture) {
|
|
2072
2861
|
timestamp = Math.max(timestamp, binding.updateTimestamp);
|
|
2073
|
-
} else if (binding instanceof
|
|
2862
|
+
} else if (binding instanceof DynamicTexture) {
|
|
2074
2863
|
timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
|
|
2075
2864
|
// The texture will become available in the future
|
|
2076
2865
|
Infinity
|
|
2077
2866
|
);
|
|
2078
|
-
} else if (!(binding instanceof
|
|
2867
|
+
} else if (!(binding instanceof import_core12.Sampler)) {
|
|
2079
2868
|
timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
|
|
2080
2869
|
}
|
|
2081
2870
|
}
|
|
@@ -2110,7 +2899,7 @@ var _Model = class {
|
|
|
2110
2899
|
let prevShaderVs = null;
|
|
2111
2900
|
let prevShaderFs = null;
|
|
2112
2901
|
if (this.pipeline) {
|
|
2113
|
-
|
|
2902
|
+
import_core12.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
2114
2903
|
prevShaderVs = this.pipeline.vs;
|
|
2115
2904
|
prevShaderFs = this.pipeline.fs;
|
|
2116
2905
|
}
|
|
@@ -2143,7 +2932,7 @@ var _Model = class {
|
|
|
2143
2932
|
vs: vs3,
|
|
2144
2933
|
fs: fs3
|
|
2145
2934
|
});
|
|
2146
|
-
this._attributeInfos = (0,
|
|
2935
|
+
this._attributeInfos = (0, import_core12.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
|
|
2147
2936
|
if (prevShaderVs)
|
|
2148
2937
|
this.shaderFactory.release(prevShaderVs);
|
|
2149
2938
|
if (prevShaderFs)
|
|
@@ -2155,24 +2944,24 @@ var _Model = class {
|
|
|
2155
2944
|
_lastLogTime = 0;
|
|
2156
2945
|
_logOpen = false;
|
|
2157
2946
|
_logDrawCallStart() {
|
|
2158
|
-
const logDrawTimeout =
|
|
2159
|
-
if (
|
|
2947
|
+
const logDrawTimeout = import_core12.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
|
|
2948
|
+
if (import_core12.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
|
|
2160
2949
|
return;
|
|
2161
2950
|
}
|
|
2162
2951
|
this._lastLogTime = Date.now();
|
|
2163
2952
|
this._logOpen = true;
|
|
2164
|
-
|
|
2953
|
+
import_core12.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core12.log.level <= 2 })();
|
|
2165
2954
|
}
|
|
2166
2955
|
_logDrawCallEnd() {
|
|
2167
2956
|
if (this._logOpen) {
|
|
2168
2957
|
const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
|
|
2169
|
-
|
|
2958
|
+
import_core12.log.table(LOG_DRAW_PRIORITY2, shaderLayoutTable)();
|
|
2170
2959
|
const uniformTable = this.shaderInputs.getDebugTable();
|
|
2171
|
-
|
|
2960
|
+
import_core12.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
|
|
2172
2961
|
const attributeTable = this._getAttributeDebugTable();
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2962
|
+
import_core12.log.table(LOG_DRAW_PRIORITY2, this._attributeInfos)();
|
|
2963
|
+
import_core12.log.table(LOG_DRAW_PRIORITY2, attributeTable)();
|
|
2964
|
+
import_core12.log.groupEnd(LOG_DRAW_PRIORITY2)();
|
|
2176
2965
|
this._logOpen = false;
|
|
2177
2966
|
}
|
|
2178
2967
|
}
|
|
@@ -2211,14 +3000,14 @@ var _Model = class {
|
|
|
2211
3000
|
}
|
|
2212
3001
|
// TODO - fix typing of luma data types
|
|
2213
3002
|
_getBufferOrConstantValues(attribute, dataType) {
|
|
2214
|
-
const TypedArrayConstructor = (0,
|
|
2215
|
-
const typedArray = attribute instanceof
|
|
3003
|
+
const TypedArrayConstructor = (0, import_core12.getTypedArrayConstructor)(dataType);
|
|
3004
|
+
const typedArray = attribute instanceof import_core12.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
2216
3005
|
return typedArray.toString();
|
|
2217
3006
|
}
|
|
2218
3007
|
};
|
|
2219
3008
|
var Model = _Model;
|
|
2220
3009
|
__publicField(Model, "defaultProps", {
|
|
2221
|
-
...
|
|
3010
|
+
...import_core12.RenderPipeline.defaultProps,
|
|
2222
3011
|
source: void 0,
|
|
2223
3012
|
vs: null,
|
|
2224
3013
|
fs: null,
|
|
@@ -2239,14 +3028,14 @@ __publicField(Model, "defaultProps", {
|
|
|
2239
3028
|
pipelineFactory: void 0,
|
|
2240
3029
|
shaderFactory: void 0,
|
|
2241
3030
|
transformFeedback: void 0,
|
|
2242
|
-
shaderAssembler:
|
|
3031
|
+
shaderAssembler: import_shadertools3.ShaderAssembler.getDefaultShaderAssembler(),
|
|
2243
3032
|
debugShaders: void 0,
|
|
2244
3033
|
disableWarnings: void 0
|
|
2245
3034
|
});
|
|
2246
3035
|
function shaderModuleHasUniforms(module2) {
|
|
2247
3036
|
return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
|
|
2248
3037
|
}
|
|
2249
|
-
function
|
|
3038
|
+
function getPlatformInfo2(device) {
|
|
2250
3039
|
return {
|
|
2251
3040
|
type: device.type,
|
|
2252
3041
|
shaderLanguage: device.info.shadingLanguage,
|
|
@@ -2264,8 +3053,8 @@ function isObjectEmpty(obj) {
|
|
|
2264
3053
|
}
|
|
2265
3054
|
|
|
2266
3055
|
// dist/compute/buffer-transform.js
|
|
2267
|
-
var
|
|
2268
|
-
var
|
|
3056
|
+
var import_core13 = require("@luma.gl/core");
|
|
3057
|
+
var import_shadertools4 = require("@luma.gl/shadertools");
|
|
2269
3058
|
var _BufferTransform = class {
|
|
2270
3059
|
device;
|
|
2271
3060
|
model;
|
|
@@ -2281,7 +3070,7 @@ var _BufferTransform = class {
|
|
|
2281
3070
|
this.device = device;
|
|
2282
3071
|
this.model = new Model(this.device, {
|
|
2283
3072
|
id: props.id || "buffer-transform-model",
|
|
2284
|
-
fs: props.fs || (0,
|
|
3073
|
+
fs: props.fs || (0, import_shadertools4.getPassthroughFS)(),
|
|
2285
3074
|
topology: props.topology || "point-list",
|
|
2286
3075
|
varyings: props.outputs || props.varyings,
|
|
2287
3076
|
...props
|
|
@@ -2327,7 +3116,7 @@ var _BufferTransform = class {
|
|
|
2327
3116
|
if (!result) {
|
|
2328
3117
|
throw new Error("BufferTransform#getBuffer");
|
|
2329
3118
|
}
|
|
2330
|
-
if (result instanceof
|
|
3119
|
+
if (result instanceof import_core13.Buffer) {
|
|
2331
3120
|
return result.readAsync();
|
|
2332
3121
|
}
|
|
2333
3122
|
const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
|
|
@@ -2342,7 +3131,7 @@ __publicField(BufferTransform, "defaultProps", {
|
|
|
2342
3131
|
});
|
|
2343
3132
|
|
|
2344
3133
|
// dist/compute/texture-transform.js
|
|
2345
|
-
var
|
|
3134
|
+
var import_shadertools5 = require("@luma.gl/shadertools");
|
|
2346
3135
|
var FS_OUTPUT_VARIABLE = "transform_output";
|
|
2347
3136
|
var TextureTransform = class {
|
|
2348
3137
|
device;
|
|
@@ -2365,7 +3154,7 @@ var TextureTransform = class {
|
|
|
2365
3154
|
});
|
|
2366
3155
|
this.model = new Model(this.device, {
|
|
2367
3156
|
id: props.id || uid("texture-transform-model"),
|
|
2368
|
-
fs: props.fs || (0,
|
|
3157
|
+
fs: props.fs || (0, import_shadertools5.getPassthroughFS)({
|
|
2369
3158
|
input: props.targetTextureVarying,
|
|
2370
3159
|
inputChannels: props.targetTextureChannels,
|
|
2371
3160
|
output: FS_OUTPUT_VARIABLE
|
|
@@ -2604,22 +3393,31 @@ ${props.source}` };
|
|
|
2604
3393
|
};
|
|
2605
3394
|
|
|
2606
3395
|
// dist/models/billboard-texture-model.js
|
|
3396
|
+
var backgroundModule = {
|
|
3397
|
+
name: "background",
|
|
3398
|
+
uniformTypes: {
|
|
3399
|
+
scale: "vec2<f32>"
|
|
3400
|
+
}
|
|
3401
|
+
};
|
|
2607
3402
|
var BACKGROUND_FS_WGSL = (
|
|
2608
3403
|
/* wgsl */
|
|
2609
3404
|
`@group(0) @binding(0) var backgroundTexture: texture_2d<f32>;
|
|
2610
3405
|
@group(0) @binding(1) var backgroundTextureSampler: sampler;
|
|
3406
|
+
struct backgroundUniforms {
|
|
3407
|
+
scale: vec2<f32>,
|
|
3408
|
+
};
|
|
3409
|
+
@group(0) @binding(2) var<uniform> background: backgroundUniforms;
|
|
2611
3410
|
|
|
2612
3411
|
fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
}
|
|
3412
|
+
let scale: vec2<f32> = background.scale;
|
|
3413
|
+
var position: vec2<f32> = (coordinates - vec2<f32>(0.5, 0.5)) / scale + vec2<f32>(0.5, 0.5);
|
|
3414
|
+
return position;
|
|
3415
|
+
}
|
|
2618
3416
|
|
|
2619
3417
|
@fragment
|
|
2620
3418
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
2621
|
-
|
|
2622
|
-
|
|
3419
|
+
let position: vec2<f32> = billboardTexture_getTextureUV(inputs.coordinate);
|
|
3420
|
+
return textureSample(backgroundTexture, backgroundTextureSampler, position);
|
|
2623
3421
|
}
|
|
2624
3422
|
`
|
|
2625
3423
|
);
|
|
@@ -2629,27 +3427,33 @@ var BACKGROUND_FS = (
|
|
|
2629
3427
|
precision highp float;
|
|
2630
3428
|
|
|
2631
3429
|
uniform sampler2D backgroundTexture;
|
|
3430
|
+
|
|
3431
|
+
uniform backgroundUniforms {
|
|
3432
|
+
vec2 scale;
|
|
3433
|
+
} background;
|
|
3434
|
+
|
|
3435
|
+
in vec2 coordinate;
|
|
2632
3436
|
out vec4 fragColor;
|
|
2633
3437
|
|
|
2634
|
-
vec2 billboardTexture_getTextureUV() {
|
|
2635
|
-
|
|
2636
|
-
vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
|
|
2637
|
-
vec2 position = gl_FragCoord.xy / texSize;
|
|
3438
|
+
vec2 billboardTexture_getTextureUV(vec2 coord) {
|
|
3439
|
+
vec2 position = (coord - 0.5) / background.scale + 0.5;
|
|
2638
3440
|
return position;
|
|
2639
3441
|
}
|
|
2640
3442
|
|
|
2641
3443
|
void main(void) {
|
|
2642
|
-
vec2 position = billboardTexture_getTextureUV();
|
|
3444
|
+
vec2 position = billboardTexture_getTextureUV(coordinate);
|
|
2643
3445
|
fragColor = texture(backgroundTexture, position);
|
|
2644
3446
|
}
|
|
2645
3447
|
`
|
|
2646
3448
|
);
|
|
2647
3449
|
var BackgroundTextureModel = class extends ClipSpace {
|
|
3450
|
+
backgroundTexture = null;
|
|
2648
3451
|
constructor(device, props) {
|
|
2649
3452
|
super(device, {
|
|
2650
3453
|
id: props.id || "background-texture-model",
|
|
2651
3454
|
source: BACKGROUND_FS_WGSL,
|
|
2652
3455
|
fs: BACKGROUND_FS,
|
|
3456
|
+
modules: [backgroundModule],
|
|
2653
3457
|
parameters: {
|
|
2654
3458
|
depthWriteEnabled: false,
|
|
2655
3459
|
...props.blend ? {
|
|
@@ -2666,28 +3470,58 @@ var BackgroundTextureModel = class extends ClipSpace {
|
|
|
2666
3470
|
if (!props.backgroundTexture) {
|
|
2667
3471
|
throw new Error("BackgroundTextureModel requires a backgroundTexture prop");
|
|
2668
3472
|
}
|
|
2669
|
-
this.
|
|
3473
|
+
this.setProps(props);
|
|
2670
3474
|
}
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
3475
|
+
/** Update the background texture */
|
|
3476
|
+
setProps(props) {
|
|
3477
|
+
const { backgroundTexture } = props;
|
|
3478
|
+
if (backgroundTexture) {
|
|
3479
|
+
this.setBindings({ backgroundTexture });
|
|
3480
|
+
if (backgroundTexture.isReady) {
|
|
3481
|
+
const texture = backgroundTexture instanceof DynamicTexture ? backgroundTexture.texture : backgroundTexture;
|
|
3482
|
+
this.backgroundTexture = texture;
|
|
3483
|
+
this.updateScale(texture);
|
|
3484
|
+
} else {
|
|
3485
|
+
backgroundTexture.ready.then((texture) => {
|
|
3486
|
+
this.backgroundTexture = texture;
|
|
3487
|
+
this.updateScale(texture);
|
|
3488
|
+
});
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
2675
3491
|
}
|
|
2676
3492
|
predraw() {
|
|
2677
|
-
this.shaderInputs.setProps({});
|
|
2678
3493
|
super.predraw();
|
|
2679
3494
|
}
|
|
3495
|
+
updateScale(texture) {
|
|
3496
|
+
if (!texture) {
|
|
3497
|
+
this.shaderInputs.setProps({ background: { scale: [1, 1] } });
|
|
3498
|
+
return;
|
|
3499
|
+
}
|
|
3500
|
+
const [screenWidth, screenHeight] = this.device.getCanvasContext().getDrawingBufferSize();
|
|
3501
|
+
const textureWidth = texture.width;
|
|
3502
|
+
const textureHeight = texture.height;
|
|
3503
|
+
const screenAspect = screenWidth / screenHeight;
|
|
3504
|
+
const textureAspect = textureWidth / textureHeight;
|
|
3505
|
+
let scaleX = 1;
|
|
3506
|
+
let scaleY = 1;
|
|
3507
|
+
if (screenAspect > textureAspect) {
|
|
3508
|
+
scaleY = screenAspect / textureAspect;
|
|
3509
|
+
} else {
|
|
3510
|
+
scaleX = textureAspect / screenAspect;
|
|
3511
|
+
}
|
|
3512
|
+
this.shaderInputs.setProps({ background: { scale: [scaleX, scaleY] } });
|
|
3513
|
+
}
|
|
2680
3514
|
};
|
|
2681
3515
|
|
|
2682
3516
|
// dist/scenegraph/scenegraph-node.js
|
|
2683
|
-
var
|
|
3517
|
+
var import_core14 = require("@math.gl/core");
|
|
2684
3518
|
var ScenegraphNode = class {
|
|
2685
3519
|
id;
|
|
2686
|
-
matrix = new
|
|
3520
|
+
matrix = new import_core14.Matrix4();
|
|
2687
3521
|
display = true;
|
|
2688
|
-
position = new
|
|
2689
|
-
rotation = new
|
|
2690
|
-
scale = new
|
|
3522
|
+
position = new import_core14.Vector3();
|
|
3523
|
+
rotation = new import_core14.Vector3();
|
|
3524
|
+
scale = new import_core14.Vector3(1, 1, 1);
|
|
2691
3525
|
userData = {};
|
|
2692
3526
|
props = {};
|
|
2693
3527
|
constructor(props = {}) {
|
|
@@ -2772,7 +3606,7 @@ var ScenegraphNode = class {
|
|
|
2772
3606
|
}
|
|
2773
3607
|
getCoordinateUniforms(viewMatrix, modelMatrix) {
|
|
2774
3608
|
modelMatrix = modelMatrix || this.matrix;
|
|
2775
|
-
const worldMatrix = new
|
|
3609
|
+
const worldMatrix = new import_core14.Matrix4(viewMatrix).multiplyRight(modelMatrix);
|
|
2776
3610
|
const worldInverse = worldMatrix.invert();
|
|
2777
3611
|
const worldInverseTranspose = worldInverse.transpose();
|
|
2778
3612
|
return {
|
|
@@ -2824,14 +3658,14 @@ var ScenegraphNode = class {
|
|
|
2824
3658
|
};
|
|
2825
3659
|
|
|
2826
3660
|
// dist/scenegraph/group-node.js
|
|
2827
|
-
var
|
|
2828
|
-
var
|
|
3661
|
+
var import_core15 = require("@math.gl/core");
|
|
3662
|
+
var import_core16 = require("@luma.gl/core");
|
|
2829
3663
|
var GroupNode = class extends ScenegraphNode {
|
|
2830
3664
|
children;
|
|
2831
3665
|
constructor(props = {}) {
|
|
2832
3666
|
props = Array.isArray(props) ? { children: props } : props;
|
|
2833
3667
|
const { children = [] } = props;
|
|
2834
|
-
|
|
3668
|
+
import_core16.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
|
|
2835
3669
|
super(props);
|
|
2836
3670
|
this.children = children;
|
|
2837
3671
|
}
|
|
@@ -2846,12 +3680,12 @@ var GroupNode = class extends ScenegraphNode {
|
|
|
2846
3680
|
return;
|
|
2847
3681
|
}
|
|
2848
3682
|
const [min, max] = bounds;
|
|
2849
|
-
const center = new
|
|
3683
|
+
const center = new import_core15.Vector3(min).add(max).divide([2, 2, 2]);
|
|
2850
3684
|
worldMatrix.transformAsPoint(center, center);
|
|
2851
|
-
const halfSize = new
|
|
3685
|
+
const halfSize = new import_core15.Vector3(max).subtract(min).divide([2, 2, 2]);
|
|
2852
3686
|
worldMatrix.transformAsVector(halfSize, halfSize);
|
|
2853
3687
|
for (let v = 0; v < 8; v++) {
|
|
2854
|
-
const position = new
|
|
3688
|
+
const position = new import_core15.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
|
|
2855
3689
|
for (let i = 0; i < 3; i++) {
|
|
2856
3690
|
result[0][i] = Math.min(result[0][i], position[i]);
|
|
2857
3691
|
result[1][i] = Math.max(result[1][i], position[i]);
|
|
@@ -2891,8 +3725,8 @@ var GroupNode = class extends ScenegraphNode {
|
|
|
2891
3725
|
this.children = [];
|
|
2892
3726
|
return this;
|
|
2893
3727
|
}
|
|
2894
|
-
traverse(visitor, { worldMatrix = new
|
|
2895
|
-
const modelMatrix = new
|
|
3728
|
+
traverse(visitor, { worldMatrix = new import_core15.Matrix4() } = {}) {
|
|
3729
|
+
const modelMatrix = new import_core15.Matrix4(worldMatrix).multiplyRight(this.matrix);
|
|
2896
3730
|
for (const child of this.children) {
|
|
2897
3731
|
if (child instanceof GroupNode) {
|
|
2898
3732
|
child.traverse(visitor, { worldMatrix: modelMatrix });
|
|
@@ -3674,7 +4508,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
|
|
|
3674
4508
|
};
|
|
3675
4509
|
|
|
3676
4510
|
// dist/geometries/ico-sphere-geometry.js
|
|
3677
|
-
var
|
|
4511
|
+
var import_core17 = require("@math.gl/core");
|
|
3678
4512
|
var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
|
|
3679
4513
|
var ICO_INDICES = [3, 4, 5, 3, 5, 1, 3, 1, 0, 3, 0, 4, 4, 0, 2, 4, 2, 5, 2, 0, 1, 5, 2, 1];
|
|
3680
4514
|
var IcoSphereGeometry = class extends Geometry {
|
|
@@ -3772,7 +4606,7 @@ function tesselateIcosaHedron(props) {
|
|
|
3772
4606
|
const u3 = 1 - phi3 / PI2;
|
|
3773
4607
|
const vec1 = [x3 - x2, y3 - y2, z3 - z2];
|
|
3774
4608
|
const vec2 = [x1 - x2, y1 - y2, z1 - z2];
|
|
3775
|
-
const normal = new
|
|
4609
|
+
const normal = new import_core17.Vector3(vec1).cross(vec2).normalize();
|
|
3776
4610
|
let newIndex;
|
|
3777
4611
|
if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
|
|
3778
4612
|
positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
|
|
@@ -4032,17 +4866,45 @@ function fract(n) {
|
|
|
4032
4866
|
return n - Math.floor(n);
|
|
4033
4867
|
}
|
|
4034
4868
|
|
|
4869
|
+
// dist/application-utils/load-file.js
|
|
4870
|
+
var pathPrefix = "";
|
|
4871
|
+
function setPathPrefix(prefix) {
|
|
4872
|
+
pathPrefix = prefix;
|
|
4873
|
+
}
|
|
4874
|
+
async function loadImageBitmap(url, opts) {
|
|
4875
|
+
const image = new Image();
|
|
4876
|
+
image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
|
|
4877
|
+
image.src = url.startsWith("http") ? url : pathPrefix + url;
|
|
4878
|
+
await image.decode();
|
|
4879
|
+
return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
|
|
4880
|
+
}
|
|
4881
|
+
async function loadImage(url, opts) {
|
|
4882
|
+
return await new Promise((resolve, reject) => {
|
|
4883
|
+
try {
|
|
4884
|
+
const image = new Image();
|
|
4885
|
+
image.onload = () => resolve(image);
|
|
4886
|
+
image.onerror = () => reject(new Error(`Could not load image ${url}.`));
|
|
4887
|
+
image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
|
|
4888
|
+
image.src = url.startsWith("http") ? url : pathPrefix + url;
|
|
4889
|
+
} catch (error) {
|
|
4890
|
+
reject(error);
|
|
4891
|
+
}
|
|
4892
|
+
});
|
|
4893
|
+
}
|
|
4894
|
+
|
|
4035
4895
|
// dist/passes/shader-pass-renderer.js
|
|
4036
|
-
var
|
|
4896
|
+
var import_shadertools6 = require("@luma.gl/shadertools");
|
|
4037
4897
|
|
|
4038
4898
|
// dist/compute/swap.js
|
|
4039
|
-
var
|
|
4899
|
+
var import_core18 = require("@luma.gl/core");
|
|
4040
4900
|
var Swap = class {
|
|
4901
|
+
id;
|
|
4041
4902
|
/** The current resource - usually the source for renders or computations */
|
|
4042
4903
|
current;
|
|
4043
4904
|
/** The next resource - usually the target/destination for transforms / computations */
|
|
4044
4905
|
next;
|
|
4045
4906
|
constructor(props) {
|
|
4907
|
+
this.id = props.id || "swap";
|
|
4046
4908
|
this.current = props.current;
|
|
4047
4909
|
this.next = props.next;
|
|
4048
4910
|
}
|
|
@@ -4063,18 +4925,21 @@ var SwapFramebuffers = class extends Swap {
|
|
|
4063
4925
|
constructor(device, props) {
|
|
4064
4926
|
var _a, _b;
|
|
4065
4927
|
props = { ...props };
|
|
4928
|
+
const { width = 1, height = 1 } = props;
|
|
4066
4929
|
let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
|
|
4930
|
+
id: `${props.id}-texture-0`,
|
|
4067
4931
|
format: colorAttachment,
|
|
4068
|
-
usage:
|
|
4069
|
-
width
|
|
4070
|
-
height
|
|
4932
|
+
usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
|
|
4933
|
+
width,
|
|
4934
|
+
height
|
|
4071
4935
|
}));
|
|
4072
4936
|
const current = device.createFramebuffer({ ...props, colorAttachments });
|
|
4073
4937
|
colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
|
|
4938
|
+
id: `${props.id}-texture-1`,
|
|
4074
4939
|
format: colorAttachment,
|
|
4075
|
-
usage:
|
|
4076
|
-
width
|
|
4077
|
-
height
|
|
4940
|
+
usage: import_core18.Texture.SAMPLE | import_core18.Texture.RENDER | import_core18.Texture.COPY_SRC | import_core18.Texture.COPY_DST,
|
|
4941
|
+
width,
|
|
4942
|
+
height
|
|
4078
4943
|
}));
|
|
4079
4944
|
const next = device.createFramebuffer({ ...props, colorAttachments });
|
|
4080
4945
|
super({ current, next });
|
|
@@ -4138,19 +5003,23 @@ function getFilterShaderWGSL(func) {
|
|
|
4138
5003
|
`// Binding 0:1 is reserved for shader passes
|
|
4139
5004
|
// @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
|
|
4140
5005
|
@group(0) @binding(1) var texture: texture_2d<f32>;
|
|
4141
|
-
@group(0) @binding(2) var
|
|
5006
|
+
@group(0) @binding(2) var textureSampler: sampler;
|
|
4142
5007
|
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
5008
|
+
// This needs to be aligned with
|
|
5009
|
+
// struct FragmentInputs {
|
|
5010
|
+
// @location(0) fragUV: vec2f,
|
|
5011
|
+
// @location(1) fragPosition: vec4f,
|
|
5012
|
+
// @location(2) fragCoordinate: vec4f
|
|
5013
|
+
// };
|
|
4148
5014
|
|
|
4149
5015
|
@fragment
|
|
4150
5016
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
4151
|
-
let
|
|
4152
|
-
|
|
4153
|
-
|
|
5017
|
+
let fragUV = inputs.uv;
|
|
5018
|
+
let fragCoordinate = inputs.coordinate;
|
|
5019
|
+
let texSize = vec2f(textureDimensions(texture, 0));
|
|
5020
|
+
|
|
5021
|
+
var fragColor = textureSample(texture, textureSampler, fragUV);
|
|
5022
|
+
fragColor = ${func}(fragColor, texSize, fragCoordinate);
|
|
4154
5023
|
return fragColor;
|
|
4155
5024
|
}
|
|
4156
5025
|
`
|
|
@@ -4172,9 +5041,9 @@ struct FragmentInputs = {
|
|
|
4172
5041
|
|
|
4173
5042
|
@fragment
|
|
4174
5043
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
4175
|
-
let texSize = textureDimensions(texture, 0);
|
|
5044
|
+
let texSize = vec2f(textureDimensions(texture, 0));
|
|
4176
5045
|
var fragColor = textureSample(texture, sampler, fragUV);
|
|
4177
|
-
fragColor = ${func}(
|
|
5046
|
+
fragColor = ${func}(fragColor, texSize, texCoord);
|
|
4178
5047
|
return fragColor;
|
|
4179
5048
|
}
|
|
4180
5049
|
`
|
|
@@ -4239,7 +5108,7 @@ var ShaderPassRenderer = class {
|
|
|
4239
5108
|
textureModel;
|
|
4240
5109
|
constructor(device, props) {
|
|
4241
5110
|
this.device = device;
|
|
4242
|
-
props.shaderPasses.map((shaderPass) => (0,
|
|
5111
|
+
props.shaderPasses.map((shaderPass) => (0, import_shadertools6.initializeShaderModule)(shaderPass));
|
|
4243
5112
|
const modules = props.shaderPasses.reduce((object, shaderPass) => ({ ...object, [shaderPass.name]: shaderPass }), {});
|
|
4244
5113
|
this.shaderInputs = props.shaderInputs || new ShaderInputs(modules);
|
|
4245
5114
|
const size = device.getCanvasContext().getDrawingBufferSize();
|
|
@@ -4270,12 +5139,10 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
|
|
|
4270
5139
|
|
|
4271
5140
|
uniform sampler2D sourceTexture;
|
|
4272
5141
|
in vec2 uv;
|
|
4273
|
-
in vec2 coordinate;
|
|
4274
5142
|
out vec4 fragColor;
|
|
4275
5143
|
|
|
4276
5144
|
void main() {
|
|
4277
|
-
|
|
4278
|
-
fragColor = texture(sourceTexture, coordinate);
|
|
5145
|
+
fragColor = texture(sourceTexture, uv);
|
|
4279
5146
|
}
|
|
4280
5147
|
`
|
|
4281
5148
|
)
|
|
@@ -4289,9 +5156,11 @@ void main() {
|
|
|
4289
5156
|
}
|
|
4290
5157
|
this.swapFramebuffers.destroy();
|
|
4291
5158
|
this.clipSpace.destroy();
|
|
5159
|
+
this.textureModel.destroy();
|
|
4292
5160
|
}
|
|
4293
|
-
resize(
|
|
4294
|
-
this.
|
|
5161
|
+
resize(size) {
|
|
5162
|
+
size ||= this.device.getCanvasContext().getDrawingBufferSize();
|
|
5163
|
+
this.swapFramebuffers.resize({ width: size[0], height: size[1] });
|
|
4295
5164
|
}
|
|
4296
5165
|
renderToScreen(options) {
|
|
4297
5166
|
const outputTexture = this.renderToTexture(options);
|
|
@@ -4302,7 +5171,7 @@ void main() {
|
|
|
4302
5171
|
const renderPass = this.device.beginRenderPass({
|
|
4303
5172
|
id: "shader-pass-renderer-to-screen",
|
|
4304
5173
|
framebuffer,
|
|
4305
|
-
clearColor: [
|
|
5174
|
+
// clearColor: [1, 1, 0, 1],
|
|
4306
5175
|
clearDepth: 1
|
|
4307
5176
|
});
|
|
4308
5177
|
this.clipSpace.setBindings({ sourceTexture: outputTexture });
|
|
@@ -4318,14 +5187,14 @@ void main() {
|
|
|
4318
5187
|
if (!sourceTexture.isReady) {
|
|
4319
5188
|
return null;
|
|
4320
5189
|
}
|
|
4321
|
-
this.
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
});
|
|
5190
|
+
if (this.passRenderers.length === 0) {
|
|
5191
|
+
return sourceTexture.texture;
|
|
5192
|
+
}
|
|
5193
|
+
this.textureModel.setProps({ backgroundTexture: sourceTexture });
|
|
4325
5194
|
const clearTexturePass = this.device.beginRenderPass({
|
|
4326
5195
|
id: "shader-pass-renderer-clear-texture",
|
|
4327
5196
|
framebuffer: this.swapFramebuffers.current,
|
|
4328
|
-
clearColor: [
|
|
5197
|
+
clearColor: [1, 0, 0, 1]
|
|
4329
5198
|
});
|
|
4330
5199
|
this.textureModel.draw(clearTexturePass);
|
|
4331
5200
|
clearTexturePass.end();
|
|
@@ -4411,218 +5280,6 @@ var SubPassRenderer = class {
|
|
|
4411
5280
|
}
|
|
4412
5281
|
};
|
|
4413
5282
|
|
|
4414
|
-
// dist/compute/computation.js
|
|
4415
|
-
var import_core16 = require("@luma.gl/core");
|
|
4416
|
-
var import_shadertools6 = require("@luma.gl/shadertools");
|
|
4417
|
-
var import_types2 = require("@math.gl/types");
|
|
4418
|
-
var LOG_DRAW_PRIORITY2 = 2;
|
|
4419
|
-
var LOG_DRAW_TIMEOUT2 = 1e4;
|
|
4420
|
-
var _Computation = class {
|
|
4421
|
-
device;
|
|
4422
|
-
id;
|
|
4423
|
-
pipelineFactory;
|
|
4424
|
-
shaderFactory;
|
|
4425
|
-
userData = {};
|
|
4426
|
-
/** Bindings (textures, samplers, uniform buffers) */
|
|
4427
|
-
bindings = {};
|
|
4428
|
-
/** The underlying GPU pipeline. */
|
|
4429
|
-
pipeline;
|
|
4430
|
-
/** Assembled compute shader source */
|
|
4431
|
-
source;
|
|
4432
|
-
/** the underlying compiled compute shader */
|
|
4433
|
-
// @ts-ignore Set in function called from constructor
|
|
4434
|
-
shader;
|
|
4435
|
-
/** ShaderInputs instance */
|
|
4436
|
-
shaderInputs;
|
|
4437
|
-
// @ts-ignore Set in function called from constructor
|
|
4438
|
-
_uniformStore;
|
|
4439
|
-
_pipelineNeedsUpdate = "newly created";
|
|
4440
|
-
_getModuleUniforms;
|
|
4441
|
-
props;
|
|
4442
|
-
_destroyed = false;
|
|
4443
|
-
constructor(device, props) {
|
|
4444
|
-
var _a, _b, _c;
|
|
4445
|
-
if (device.type !== "webgpu") {
|
|
4446
|
-
throw new Error("Computation is only supported in WebGPU");
|
|
4447
|
-
}
|
|
4448
|
-
this.props = { ..._Computation.defaultProps, ...props };
|
|
4449
|
-
props = this.props;
|
|
4450
|
-
this.id = props.id || uid("model");
|
|
4451
|
-
this.device = device;
|
|
4452
|
-
Object.assign(this.userData, props.userData);
|
|
4453
|
-
const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
|
|
4454
|
-
this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
|
|
4455
|
-
this.setShaderInputs(this.shaderInputs);
|
|
4456
|
-
this.props.shaderLayout ||= (0, import_shadertools6.getShaderLayoutFromWGSL)(this.props.source);
|
|
4457
|
-
const platformInfo = getPlatformInfo2(device);
|
|
4458
|
-
const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
|
|
4459
|
-
this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
|
|
4460
|
-
this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
|
|
4461
|
-
const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
|
|
4462
|
-
platformInfo,
|
|
4463
|
-
...this.props,
|
|
4464
|
-
modules
|
|
4465
|
-
});
|
|
4466
|
-
this.source = source3;
|
|
4467
|
-
this._getModuleUniforms = getUniforms2;
|
|
4468
|
-
this.pipeline = this._updatePipeline();
|
|
4469
|
-
if (props.bindings) {
|
|
4470
|
-
this.setBindings(props.bindings);
|
|
4471
|
-
}
|
|
4472
|
-
Object.seal(this);
|
|
4473
|
-
}
|
|
4474
|
-
destroy() {
|
|
4475
|
-
if (this._destroyed)
|
|
4476
|
-
return;
|
|
4477
|
-
this.pipelineFactory.release(this.pipeline);
|
|
4478
|
-
this.shaderFactory.release(this.shader);
|
|
4479
|
-
this._uniformStore.destroy();
|
|
4480
|
-
this._destroyed = true;
|
|
4481
|
-
}
|
|
4482
|
-
// Draw call
|
|
4483
|
-
predraw() {
|
|
4484
|
-
this.updateShaderInputs();
|
|
4485
|
-
}
|
|
4486
|
-
dispatch(computePass, x, y, z) {
|
|
4487
|
-
try {
|
|
4488
|
-
this._logDrawCallStart();
|
|
4489
|
-
this.pipeline = this._updatePipeline();
|
|
4490
|
-
this.pipeline.setBindings(this.bindings);
|
|
4491
|
-
computePass.setPipeline(this.pipeline);
|
|
4492
|
-
computePass.setBindings([]);
|
|
4493
|
-
computePass.dispatch(x, y, z);
|
|
4494
|
-
} finally {
|
|
4495
|
-
this._logDrawCallEnd();
|
|
4496
|
-
}
|
|
4497
|
-
}
|
|
4498
|
-
// Update fixed fields (can trigger pipeline rebuild)
|
|
4499
|
-
// Update dynamic fields
|
|
4500
|
-
/**
|
|
4501
|
-
* Updates the vertex count (used in draw calls)
|
|
4502
|
-
* @note Any attributes with stepMode=vertex need to be at least this big
|
|
4503
|
-
*/
|
|
4504
|
-
setVertexCount(vertexCount) {
|
|
4505
|
-
}
|
|
4506
|
-
/**
|
|
4507
|
-
* Updates the instance count (used in draw calls)
|
|
4508
|
-
* @note Any attributes with stepMode=instance need to be at least this big
|
|
4509
|
-
*/
|
|
4510
|
-
setInstanceCount(instanceCount) {
|
|
4511
|
-
}
|
|
4512
|
-
setShaderInputs(shaderInputs) {
|
|
4513
|
-
this.shaderInputs = shaderInputs;
|
|
4514
|
-
this._uniformStore = new import_core16.UniformStore(this.shaderInputs.modules);
|
|
4515
|
-
for (const moduleName of Object.keys(this.shaderInputs.modules)) {
|
|
4516
|
-
const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
|
|
4517
|
-
this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
|
|
4518
|
-
}
|
|
4519
|
-
}
|
|
4520
|
-
/**
|
|
4521
|
-
* Updates shader module settings (which results in uniforms being set)
|
|
4522
|
-
*/
|
|
4523
|
-
setShaderModuleProps(props) {
|
|
4524
|
-
const uniforms = this._getModuleUniforms(props);
|
|
4525
|
-
const keys = Object.keys(uniforms).filter((k) => {
|
|
4526
|
-
const uniform = uniforms[k];
|
|
4527
|
-
return !(0, import_types2.isNumericArray)(uniform) && typeof uniform !== "number" && typeof uniform !== "boolean";
|
|
4528
|
-
});
|
|
4529
|
-
const bindings = {};
|
|
4530
|
-
for (const k of keys) {
|
|
4531
|
-
bindings[k] = uniforms[k];
|
|
4532
|
-
delete uniforms[k];
|
|
4533
|
-
}
|
|
4534
|
-
}
|
|
4535
|
-
updateShaderInputs() {
|
|
4536
|
-
this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
|
|
4537
|
-
}
|
|
4538
|
-
/**
|
|
4539
|
-
* Sets bindings (textures, samplers, uniform buffers)
|
|
4540
|
-
*/
|
|
4541
|
-
setBindings(bindings) {
|
|
4542
|
-
Object.assign(this.bindings, bindings);
|
|
4543
|
-
}
|
|
4544
|
-
_setPipelineNeedsUpdate(reason) {
|
|
4545
|
-
this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
|
|
4546
|
-
}
|
|
4547
|
-
_updatePipeline() {
|
|
4548
|
-
if (this._pipelineNeedsUpdate) {
|
|
4549
|
-
let prevShader = null;
|
|
4550
|
-
if (this.pipeline) {
|
|
4551
|
-
import_core16.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
|
|
4552
|
-
prevShader = this.shader;
|
|
4553
|
-
}
|
|
4554
|
-
this._pipelineNeedsUpdate = false;
|
|
4555
|
-
this.shader = this.shaderFactory.createShader({
|
|
4556
|
-
id: `${this.id}-fragment`,
|
|
4557
|
-
stage: "compute",
|
|
4558
|
-
source: this.source,
|
|
4559
|
-
debugShaders: this.props.debugShaders
|
|
4560
|
-
});
|
|
4561
|
-
this.pipeline = this.pipelineFactory.createComputePipeline({
|
|
4562
|
-
...this.props,
|
|
4563
|
-
shader: this.shader
|
|
4564
|
-
});
|
|
4565
|
-
if (prevShader) {
|
|
4566
|
-
this.shaderFactory.release(prevShader);
|
|
4567
|
-
}
|
|
4568
|
-
}
|
|
4569
|
-
return this.pipeline;
|
|
4570
|
-
}
|
|
4571
|
-
/** Throttle draw call logging */
|
|
4572
|
-
_lastLogTime = 0;
|
|
4573
|
-
_logOpen = false;
|
|
4574
|
-
_logDrawCallStart() {
|
|
4575
|
-
const logDrawTimeout = import_core16.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
|
|
4576
|
-
if (import_core16.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
|
|
4577
|
-
return;
|
|
4578
|
-
}
|
|
4579
|
-
this._lastLogTime = Date.now();
|
|
4580
|
-
this._logOpen = true;
|
|
4581
|
-
import_core16.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core16.log.level <= 2 })();
|
|
4582
|
-
}
|
|
4583
|
-
_logDrawCallEnd() {
|
|
4584
|
-
if (this._logOpen) {
|
|
4585
|
-
const uniformTable = this.shaderInputs.getDebugTable();
|
|
4586
|
-
import_core16.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
|
|
4587
|
-
import_core16.log.groupEnd(LOG_DRAW_PRIORITY2)();
|
|
4588
|
-
this._logOpen = false;
|
|
4589
|
-
}
|
|
4590
|
-
}
|
|
4591
|
-
_drawCount = 0;
|
|
4592
|
-
// TODO - fix typing of luma data types
|
|
4593
|
-
_getBufferOrConstantValues(attribute, dataType) {
|
|
4594
|
-
const TypedArrayConstructor = (0, import_core16.getTypedArrayConstructor)(dataType);
|
|
4595
|
-
const typedArray = attribute instanceof import_core16.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
|
|
4596
|
-
return typedArray.toString();
|
|
4597
|
-
}
|
|
4598
|
-
};
|
|
4599
|
-
var Computation = _Computation;
|
|
4600
|
-
__publicField(Computation, "defaultProps", {
|
|
4601
|
-
...import_core16.ComputePipeline.defaultProps,
|
|
4602
|
-
id: "unnamed",
|
|
4603
|
-
handle: void 0,
|
|
4604
|
-
userData: {},
|
|
4605
|
-
source: "",
|
|
4606
|
-
modules: [],
|
|
4607
|
-
defines: {},
|
|
4608
|
-
bindings: void 0,
|
|
4609
|
-
shaderInputs: void 0,
|
|
4610
|
-
pipelineFactory: void 0,
|
|
4611
|
-
shaderFactory: void 0,
|
|
4612
|
-
shaderAssembler: import_shadertools6.ShaderAssembler.getDefaultShaderAssembler(),
|
|
4613
|
-
debugShaders: void 0
|
|
4614
|
-
});
|
|
4615
|
-
function getPlatformInfo2(device) {
|
|
4616
|
-
return {
|
|
4617
|
-
type: device.type,
|
|
4618
|
-
shaderLanguage: device.info.shadingLanguage,
|
|
4619
|
-
shaderLanguageVersion: device.info.shadingLanguageVersion,
|
|
4620
|
-
gpu: device.info.gpu,
|
|
4621
|
-
// HACK - we pretend that the DeviceFeatures is a Set, it has a similar API
|
|
4622
|
-
features: device.features
|
|
4623
|
-
};
|
|
4624
|
-
}
|
|
4625
|
-
|
|
4626
5283
|
// dist/modules/picking/picking-uniforms.js
|
|
4627
5284
|
var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
|
|
4628
5285
|
var INVALID_INDEX = -1;
|
|
@@ -5161,4 +5818,7 @@ var LegacyPickingManager = class {
|
|
|
5161
5818
|
return [pickX, pickY];
|
|
5162
5819
|
}
|
|
5163
5820
|
};
|
|
5821
|
+
|
|
5822
|
+
// dist/index.js
|
|
5823
|
+
var AsyncTexture = DynamicTexture;
|
|
5164
5824
|
//# sourceMappingURL=index.cjs.map
|