@luma.gl/engine 9.2.6 → 9.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/animation-loop/animation-loop.d.ts +3 -1
  2. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  3. package/dist/animation-loop/animation-loop.js +10 -4
  4. package/dist/animation-loop/animation-loop.js.map +1 -1
  5. package/dist/compute/computation.d.ts.map +1 -1
  6. package/dist/compute/computation.js +3 -2
  7. package/dist/compute/computation.js.map +1 -1
  8. package/dist/compute/swap.d.ts +2 -0
  9. package/dist/compute/swap.d.ts.map +1 -1
  10. package/dist/compute/swap.js +10 -5
  11. package/dist/compute/swap.js.map +1 -1
  12. package/dist/dist.dev.js +554 -358
  13. package/dist/dist.min.js +59 -50
  14. package/dist/dynamic-texture/dynamic-texture.d.ts +95 -0
  15. package/dist/dynamic-texture/dynamic-texture.d.ts.map +1 -0
  16. package/dist/dynamic-texture/dynamic-texture.js +356 -0
  17. package/dist/dynamic-texture/dynamic-texture.js.map +1 -0
  18. package/dist/dynamic-texture/texture-data.d.ts +137 -0
  19. package/dist/dynamic-texture/texture-data.d.ts.map +1 -0
  20. package/dist/dynamic-texture/texture-data.js +183 -0
  21. package/dist/dynamic-texture/texture-data.js.map +1 -0
  22. package/dist/factories/pipeline-factory.d.ts.map +1 -1
  23. package/dist/factories/pipeline-factory.js +3 -3
  24. package/dist/factories/pipeline-factory.js.map +1 -1
  25. package/dist/factories/shader-factory.d.ts.map +1 -1
  26. package/dist/factories/shader-factory.js +3 -2
  27. package/dist/factories/shader-factory.js.map +1 -1
  28. package/dist/index.cjs +566 -370
  29. package/dist/index.cjs.map +4 -4
  30. package/dist/index.d.ts +8 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/model/model.d.ts +31 -10
  35. package/dist/model/model.d.ts.map +1 -1
  36. package/dist/model/model.js +34 -14
  37. package/dist/model/model.js.map +1 -1
  38. package/dist/models/billboard-texture-model.d.ts +8 -5
  39. package/dist/models/billboard-texture-model.d.ts.map +1 -1
  40. package/dist/models/billboard-texture-model.js +70 -18
  41. package/dist/models/billboard-texture-model.js.map +1 -1
  42. package/dist/passes/get-fragment-shader.js +15 -11
  43. package/dist/passes/get-fragment-shader.js.map +1 -1
  44. package/dist/passes/shader-pass-renderer.d.ts +5 -5
  45. package/dist/passes/shader-pass-renderer.d.ts.map +1 -1
  46. package/dist/passes/shader-pass-renderer.js +13 -12
  47. package/dist/passes/shader-pass-renderer.js.map +1 -1
  48. package/dist/types.d.ts +7 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +5 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +4 -4
  53. package/src/animation-loop/animation-loop.ts +11 -4
  54. package/src/compute/computation.ts +3 -2
  55. package/src/compute/swap.ts +13 -7
  56. package/src/dynamic-texture/dynamic-texture.ts +451 -0
  57. package/src/dynamic-texture/texture-data.ts +301 -0
  58. package/src/factories/pipeline-factory.ts +4 -3
  59. package/src/factories/shader-factory.ts +4 -2
  60. package/src/index.ts +9 -4
  61. package/src/model/model.ts +37 -18
  62. package/src/models/billboard-texture-model.ts +81 -22
  63. package/src/passes/get-fragment-shader.ts +15 -11
  64. package/src/passes/shader-pass-renderer.ts +22 -16
  65. package/src/types.ts +11 -0
  66. package/dist/async-texture/async-texture.d.ts +0 -166
  67. package/dist/async-texture/async-texture.d.ts.map +0 -1
  68. package/dist/async-texture/async-texture.js +0 -386
  69. package/dist/async-texture/async-texture.js.map +0 -1
  70. package/src/async-texture/async-texture.ts +0 -551
  71. /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
- needsRedraw = "initialized";
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.needsRedraw = this.needsRedraw || reason;
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.needsRedraw = false;
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.needsRedraw;
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,7 +677,7 @@ function clearError(device) {
670
677
  }
671
678
 
672
679
  // dist/model/model.js
673
- var import_core9 = require("@luma.gl/core");
680
+ var import_core10 = require("@luma.gl/core");
674
681
  var import_shadertools2 = require("@luma.gl/shadertools");
675
682
 
676
683
  // dist/geometry/gpu-geometry.js
@@ -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
- device._lumaData["defaultPipelineFactory"] = device._lumaData["defaultPipelineFactory"] || new _PipelineFactory(device);
790
- return device._lumaData["defaultPipelineFactory"];
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._lumaData["defaultShaderFactory"] ||= new _ShaderFactory(device);
956
- return device._lumaData["defaultShaderFactory"];
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;
@@ -1306,49 +1315,160 @@ var ShaderInputs = class {
1306
1315
  }
1307
1316
  };
1308
1317
 
1309
- // dist/async-texture/async-texture.js
1310
- var import_core8 = require("@luma.gl/core");
1318
+ // dist/dynamic-texture/dynamic-texture.js
1319
+ var import_core9 = require("@luma.gl/core");
1311
1320
 
1312
- // dist/application-utils/load-file.js
1313
- var pathPrefix = "";
1314
- function setPathPrefix(prefix) {
1315
- pathPrefix = prefix;
1321
+ // dist/dynamic-texture/texture-data.js
1322
+ var import_core8 = require("@luma.gl/core");
1323
+ var TEXTURE_CUBE_FACE_MAP = { "+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5 };
1324
+ function getFirstMipLevel(layer) {
1325
+ if (!layer)
1326
+ return null;
1327
+ return Array.isArray(layer) ? layer[0] ?? null : layer;
1316
1328
  }
1317
- async function loadImageBitmap(url, opts) {
1318
- const image = new Image();
1319
- image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
1320
- image.src = url.startsWith("http") ? url : pathPrefix + url;
1321
- await image.decode();
1322
- return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
1329
+ function getTextureSizeFromData(props) {
1330
+ const { dimension, data } = props;
1331
+ if (!data) {
1332
+ return null;
1333
+ }
1334
+ switch (dimension) {
1335
+ case "1d": {
1336
+ const mipLevel = getFirstMipLevel(data);
1337
+ if (!mipLevel)
1338
+ return null;
1339
+ const { width } = getTextureMipLevelSize(mipLevel);
1340
+ return { width, height: 1 };
1341
+ }
1342
+ case "2d": {
1343
+ const mipLevel = getFirstMipLevel(data);
1344
+ return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
1345
+ }
1346
+ case "3d":
1347
+ case "2d-array": {
1348
+ if (!Array.isArray(data) || data.length === 0)
1349
+ return null;
1350
+ const mipLevel = getFirstMipLevel(data[0]);
1351
+ return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
1352
+ }
1353
+ case "cube": {
1354
+ const face = Object.keys(data)[0] ?? null;
1355
+ if (!face)
1356
+ return null;
1357
+ const faceData = data[face];
1358
+ const mipLevel = getFirstMipLevel(faceData);
1359
+ return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
1360
+ }
1361
+ case "cube-array": {
1362
+ if (!Array.isArray(data) || data.length === 0)
1363
+ return null;
1364
+ const firstCube = data[0];
1365
+ const face = Object.keys(firstCube)[0] ?? null;
1366
+ if (!face)
1367
+ return null;
1368
+ const mipLevel = getFirstMipLevel(firstCube[face]);
1369
+ return mipLevel ? getTextureMipLevelSize(mipLevel) : null;
1370
+ }
1371
+ default:
1372
+ return null;
1373
+ }
1323
1374
  }
1324
- async function loadImage(url, opts) {
1325
- return await new Promise((resolve, reject) => {
1326
- try {
1327
- const image = new Image();
1328
- image.onload = () => resolve(image);
1329
- image.onerror = () => reject(new Error(`Could not load image ${url}.`));
1330
- image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
1331
- image.src = url.startsWith("http") ? url : pathPrefix + url;
1332
- } catch (error) {
1333
- reject(error);
1375
+ function getTextureMipLevelSize(data) {
1376
+ if ((0, import_core8.isExternalImage)(data)) {
1377
+ return (0, import_core8.getExternalImageSize)(data);
1378
+ }
1379
+ if (typeof data === "object" && "width" in data && "height" in data) {
1380
+ return { width: data.width, height: data.height };
1381
+ }
1382
+ throw new Error("Unsupported mip-level data");
1383
+ }
1384
+ function isTextureImageData(data) {
1385
+ return typeof data === "object" && data !== null && "data" in data && "width" in data && "height" in data;
1386
+ }
1387
+ function getCubeFaceIndex(face) {
1388
+ const idx = TEXTURE_CUBE_FACE_MAP[face];
1389
+ if (idx === void 0)
1390
+ throw new Error(`Invalid cube face: ${face}`);
1391
+ return idx;
1392
+ }
1393
+ function getCubeArrayFaceIndex(cubeIndex, face) {
1394
+ return 6 * cubeIndex + getCubeFaceIndex(face);
1395
+ }
1396
+ function getTexture1DSubresources(data) {
1397
+ throw new Error("setTexture1DData not supported in WebGL.");
1398
+ }
1399
+ function _normalizeTexture2DData(data) {
1400
+ return Array.isArray(data) ? data : [data];
1401
+ }
1402
+ function getTexture2DSubresources(slice, lodData) {
1403
+ const lodArray = _normalizeTexture2DData(lodData);
1404
+ const z = slice;
1405
+ const subresources = [];
1406
+ for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
1407
+ const imageData = lodArray[mipLevel];
1408
+ if ((0, import_core8.isExternalImage)(imageData)) {
1409
+ subresources.push({
1410
+ type: "external-image",
1411
+ image: imageData,
1412
+ z,
1413
+ mipLevel
1414
+ });
1415
+ } else if (isTextureImageData(imageData)) {
1416
+ subresources.push({
1417
+ type: "texture-data",
1418
+ data: imageData,
1419
+ z,
1420
+ mipLevel
1421
+ });
1422
+ } else {
1423
+ throw new Error("Unsupported 2D mip-level payload");
1424
+ }
1425
+ }
1426
+ return subresources;
1427
+ }
1428
+ function getTexture3DSubresources(data) {
1429
+ const subresources = [];
1430
+ for (let depth = 0; depth < data.length; depth++) {
1431
+ subresources.push(...getTexture2DSubresources(depth, data[depth]));
1432
+ }
1433
+ return subresources;
1434
+ }
1435
+ function getTextureArraySubresources(data) {
1436
+ const subresources = [];
1437
+ for (let layer = 0; layer < data.length; layer++) {
1438
+ subresources.push(...getTexture2DSubresources(layer, data[layer]));
1439
+ }
1440
+ return subresources;
1441
+ }
1442
+ function getTextureCubeSubresources(data) {
1443
+ const subresources = [];
1444
+ for (const [face, faceData] of Object.entries(data)) {
1445
+ const faceDepth = getCubeFaceIndex(face);
1446
+ subresources.push(...getTexture2DSubresources(faceDepth, faceData));
1447
+ }
1448
+ return subresources;
1449
+ }
1450
+ function getTextureCubeArraySubresources(data) {
1451
+ const subresources = [];
1452
+ data.forEach((cubeData, cubeIndex) => {
1453
+ for (const [face, faceData] of Object.entries(cubeData)) {
1454
+ const faceDepth = getCubeArrayFaceIndex(cubeIndex, face);
1455
+ getTexture2DSubresources(faceDepth, faceData);
1334
1456
  }
1335
1457
  });
1458
+ return subresources;
1336
1459
  }
1337
1460
 
1338
- // dist/async-texture/async-texture.js
1339
- var TextureCubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
1340
- var CubeFaces = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
1341
- var _AsyncTexture = class {
1461
+ // dist/dynamic-texture/dynamic-texture.js
1462
+ var _DynamicTexture = class {
1342
1463
  device;
1343
1464
  id;
1465
+ /** Props with defaults resolved (except `data` which is processed separately) */
1344
1466
  props;
1345
- // TODO - should we type these as possibly `null`? It will make usage harder?
1346
- // @ts-expect-error
1347
- texture;
1348
- // @ts-expect-error
1349
- sampler;
1350
- // @ts-expect-error
1351
- view;
1467
+ /** Created resources */
1468
+ _texture = null;
1469
+ _sampler = null;
1470
+ _view = null;
1471
+ /** Ready when GPU texture has been created and data (if any) uploaded */
1352
1472
  ready;
1353
1473
  isReady = false;
1354
1474
  destroyed = false;
@@ -1356,269 +1476,249 @@ var _AsyncTexture = class {
1356
1476
  };
1357
1477
  rejectReady = () => {
1358
1478
  };
1479
+ get texture() {
1480
+ if (!this._texture)
1481
+ throw new Error("Texture not initialized yet");
1482
+ return this._texture;
1483
+ }
1484
+ get sampler() {
1485
+ if (!this._sampler)
1486
+ throw new Error("Sampler not initialized yet");
1487
+ return this._sampler;
1488
+ }
1489
+ get view() {
1490
+ if (!this._view)
1491
+ throw new Error("View not initialized yet");
1492
+ return this._view;
1493
+ }
1359
1494
  get [Symbol.toStringTag]() {
1360
- return "AsyncTexture";
1495
+ return "DynamicTexture";
1361
1496
  }
1362
1497
  toString() {
1363
- return `AsyncTexture:"${this.id}"(${this.isReady ? "ready" : "loading"})`;
1498
+ return `DynamicTexture:"${this.id}":${this.texture.width}x${this.texture.height}px:(${this.isReady ? "ready" : "loading..."})`;
1364
1499
  }
1365
1500
  constructor(device, props) {
1366
1501
  this.device = device;
1367
- const id = uid("async-texture");
1368
- this.props = { ..._AsyncTexture.defaultProps, id, ...props };
1502
+ const id = uid("dynamic-texture");
1503
+ const originalPropsWithAsyncData = props;
1504
+ this.props = { ..._DynamicTexture.defaultProps, id, ...props, data: null };
1369
1505
  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
1506
  this.ready = new Promise((resolve, reject) => {
1378
- this.resolveReady = () => {
1379
- this.isReady = true;
1380
- resolve();
1381
- };
1507
+ this.resolveReady = resolve;
1382
1508
  this.rejectReady = reject;
1383
1509
  });
1384
- this.initAsync(props);
1510
+ this.initAsync(originalPropsWithAsyncData);
1385
1511
  }
1386
- async initAsync(props) {
1387
- const asyncData = props.data;
1388
- const data = await awaitAllPromises(asyncData).then(void 0, this.rejectReady);
1389
- if (this.destroyed) {
1390
- return;
1391
- }
1392
- const size = this.props.width && this.props.height ? { width: this.props.width, height: this.props.height } : this.getTextureDataSize(data);
1393
- if (!size) {
1394
- throw new Error("Texture size could not be determined");
1395
- }
1396
- const syncProps = { ...size, ...props, data: void 0, mipLevels: 1 };
1397
- const maxMips = this.device.getMipLevelCount(syncProps.width, syncProps.height);
1398
- syncProps.mipLevels = this.props.mipLevels === "auto" ? maxMips : Math.min(maxMips, this.props.mipLevels);
1399
- this.texture = this.device.createTexture(syncProps);
1400
- this.sampler = this.texture.sampler;
1401
- this.view = this.texture.view;
1402
- if (props.data) {
1403
- switch (this.props.dimension) {
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;
1512
+ /** @note Fire and forget; caller can await `ready` */
1513
+ async initAsync(originalPropsWithAsyncData) {
1514
+ try {
1515
+ const propsWithSyncData = await this._loadAllData(originalPropsWithAsyncData);
1516
+ this._checkNotDestroyed();
1517
+ const deduceSize = () => {
1518
+ if (this.props.width && this.props.height) {
1519
+ return { width: this.props.width, height: this.props.height };
1520
+ }
1521
+ const size2 = getTextureSizeFromData(propsWithSyncData);
1522
+ if (size2) {
1523
+ return size2;
1524
+ }
1525
+ return { width: this.props.width || 1, height: this.props.height || 1 };
1526
+ };
1527
+ const size = deduceSize();
1528
+ if (!size || size.width <= 0 || size.height <= 0) {
1529
+ throw new Error(`${this} size could not be determined or was zero`);
1422
1530
  }
1531
+ const baseTextureProps = {
1532
+ ...this.props,
1533
+ ...size,
1534
+ mipLevels: 1,
1535
+ // temporary; updated below
1536
+ data: void 0
1537
+ };
1538
+ const maxMips = this.device.getMipLevelCount(baseTextureProps.width, baseTextureProps.height);
1539
+ const desired = this.props.mipLevels === "auto" ? maxMips : Math.max(1, Math.min(maxMips, this.props.mipLevels ?? 1));
1540
+ const finalTextureProps = { ...baseTextureProps, mipLevels: desired };
1541
+ this._texture = this.device.createTexture(finalTextureProps);
1542
+ this._sampler = this.texture.sampler;
1543
+ this._view = this.texture.view;
1544
+ if (propsWithSyncData.data) {
1545
+ switch (propsWithSyncData.dimension) {
1546
+ case "1d":
1547
+ this.setTexture1DData(propsWithSyncData.data);
1548
+ break;
1549
+ case "2d":
1550
+ this.setTexture2DData(propsWithSyncData.data);
1551
+ break;
1552
+ case "3d":
1553
+ this.setTexture3DData(propsWithSyncData.data);
1554
+ break;
1555
+ case "2d-array":
1556
+ this.setTextureArrayData(propsWithSyncData.data);
1557
+ break;
1558
+ case "cube":
1559
+ this.setTextureCubeData(propsWithSyncData.data);
1560
+ break;
1561
+ case "cube-array":
1562
+ this.setTextureCubeArrayData(propsWithSyncData.data);
1563
+ break;
1564
+ default: {
1565
+ throw new Error(`Unhandled dimension ${propsWithSyncData.dimension}`);
1566
+ }
1567
+ }
1568
+ }
1569
+ if (this.props.mipmaps) {
1570
+ this.generateMipmaps();
1571
+ }
1572
+ this.isReady = true;
1573
+ this.resolveReady(this.texture);
1574
+ import_core9.log.info(0, `${this} created`)();
1575
+ } catch (e) {
1576
+ const err = e instanceof Error ? e : new Error(String(e));
1577
+ this.rejectReady(err);
1578
+ throw err;
1423
1579
  }
1424
- if (this.props.mipmaps) {
1425
- this.generateMipmaps();
1426
- }
1427
- import_core8.log.info(1, `${this} loaded`);
1428
- this.resolveReady();
1429
1580
  }
1430
1581
  destroy() {
1431
- if (this.texture) {
1432
- this.texture.destroy();
1433
- this.texture = null;
1582
+ if (this._texture) {
1583
+ this._texture.destroy();
1584
+ this._texture = null;
1585
+ this._sampler = null;
1586
+ this._view = null;
1434
1587
  }
1435
1588
  this.destroyed = true;
1436
1589
  }
1437
1590
  generateMipmaps() {
1438
- this.texture.generateMipmapsWebGL();
1591
+ if (this.device.type === "webgl") {
1592
+ this.texture.generateMipmapsWebGL();
1593
+ } else {
1594
+ import_core9.log.warn("Mipmap generation not yet implemented on WebGPU: your texture data will not be correctly initialized");
1595
+ }
1439
1596
  }
1440
- /** Set sampler or create and set new Sampler from SamplerProps */
1597
+ /** Set sampler or create one from props */
1441
1598
  setSampler(sampler = {}) {
1442
- this.texture.setSampler(sampler instanceof import_core8.Sampler ? sampler : this.device.createSampler(sampler));
1599
+ this._checkReady();
1600
+ const s = sampler instanceof import_core9.Sampler ? sampler : this.device.createSampler(sampler);
1601
+ this.texture.setSampler(s);
1602
+ this._sampler = s;
1443
1603
  }
1444
1604
  /**
1445
- * Textures are immutable and cannot be resized after creation,
1446
- * but we can create a similar texture with the same parameters but a new size.
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?
1605
+ * Resize by cloning the underlying immutable texture.
1606
+ * Does not copy contents; caller may need to re-upload and/or regenerate mips.
1450
1607
  */
1451
1608
  resize(size) {
1452
- if (!this.isReady) {
1453
- throw new Error("Cannot resize texture before it is ready");
1454
- }
1609
+ this._checkReady();
1455
1610
  if (size.width === this.texture.width && size.height === this.texture.height) {
1456
1611
  return false;
1457
1612
  }
1458
- if (this.texture) {
1459
- const texture = this.texture;
1460
- this.texture = texture.clone(size);
1461
- texture.destroy();
1462
- }
1613
+ const prev = this.texture;
1614
+ this._texture = prev.clone(size);
1615
+ this._sampler = this.texture.sampler;
1616
+ this._view = this.texture.view;
1617
+ prev.destroy();
1618
+ import_core9.log.info(`${this} resized`);
1463
1619
  return true;
1464
1620
  }
1465
- /** Check if texture data is a typed array */
1466
- isTextureLevelData(data) {
1467
- const typedArray = data == null ? void 0 : data.data;
1468
- return ArrayBuffer.isView(typedArray);
1469
- }
1470
- /** Get the size of the texture described by the provided TextureData */
1471
- getTextureDataSize(data) {
1472
- if (!data) {
1473
- return null;
1474
- }
1475
- if (ArrayBuffer.isView(data)) {
1476
- return null;
1477
- }
1478
- if (Array.isArray(data)) {
1479
- return this.getTextureDataSize(data[0]);
1480
- }
1481
- if (this.device.isExternalImage(data)) {
1482
- return this.device.getExternalImageSize(data);
1483
- }
1484
- if (data && typeof data === "object" && data.constructor === Object) {
1485
- const textureDataArray = Object.values(data);
1486
- const untypedData = textureDataArray[0];
1487
- return { width: untypedData.width, height: untypedData.height };
1488
- }
1489
- throw new Error("texture size deduction failed");
1490
- }
1491
- /** Convert luma.gl cubemap face constants to depth index */
1492
- getCubeFaceDepth(face) {
1493
- switch (face) {
1494
- case "+X":
1495
- return 0;
1496
- case "-X":
1497
- return 1;
1498
- case "+Y":
1499
- return 2;
1500
- case "-Y":
1501
- return 3;
1502
- case "+Z":
1503
- return 4;
1504
- case "-Z":
1505
- return 5;
1506
- default:
1507
- throw new Error(face);
1508
- }
1509
- }
1510
- // EXPERIMENTAL
1511
- setTextureData(data) {
1512
- }
1513
- /** Experimental: Set multiple mip levels */
1514
- _setTexture1DData(texture, data) {
1515
- throw new Error("setTexture1DData not supported in WebGL.");
1516
- }
1517
- /** Experimental: Set multiple mip levels */
1518
- _setTexture2DData(lodData, depth = 0) {
1519
- if (!this.texture) {
1520
- throw new Error("Texture not initialized");
1521
- }
1522
- const lodArray = this._normalizeTextureData(lodData);
1523
- if (lodArray.length > 1 && this.props.mipmaps !== false) {
1524
- import_core8.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
1525
- }
1526
- for (let mipLevel = 0; mipLevel < lodArray.length; mipLevel++) {
1527
- const imageData = lodArray[mipLevel];
1528
- if (this.device.isExternalImage(imageData)) {
1529
- this.texture.copyExternalImage({ image: imageData, depth, mipLevel, flipY: true });
1530
- } else {
1531
- this.texture.copyImageData({ data: imageData.data, mipLevel });
1621
+ /** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
1622
+ getCubeFaceIndex(face) {
1623
+ const index = TEXTURE_CUBE_FACE_MAP[face];
1624
+ if (index === void 0)
1625
+ throw new Error(`Invalid cube face: ${face}`);
1626
+ return index;
1627
+ }
1628
+ /** Convert cube face label to texture slice index. Index can be used with `setTexture2DData()`. */
1629
+ getCubeArrayFaceIndex(cubeIndex, face) {
1630
+ return 6 * cubeIndex + this.getCubeFaceIndex(face);
1631
+ }
1632
+ /** @note experimental: Set multiple mip levels (1D) */
1633
+ setTexture1DData(data) {
1634
+ this._checkReady();
1635
+ if (this.texture.props.dimension !== "1d") {
1636
+ throw new Error(`${this} is not 1d`);
1637
+ }
1638
+ const subresources = getTexture1DSubresources(data);
1639
+ this._setTextureSubresources(subresources);
1640
+ }
1641
+ /** @note experimental: Set multiple mip levels (2D), optionally at `z`, slice (depth/array level) index */
1642
+ setTexture2DData(lodData, z = 0) {
1643
+ this._checkReady();
1644
+ if (this.texture.props.dimension !== "2d") {
1645
+ throw new Error(`${this} is not 2d`);
1646
+ }
1647
+ const subresources = getTexture2DSubresources(z, lodData);
1648
+ this._setTextureSubresources(subresources);
1649
+ }
1650
+ /** 3D: multiple depth slices, each may carry multiple mip levels */
1651
+ setTexture3DData(data) {
1652
+ if (this.texture.props.dimension !== "3d") {
1653
+ throw new Error(`${this} is not 3d`);
1654
+ }
1655
+ const subresources = getTexture3DSubresources(data);
1656
+ this._setTextureSubresources(subresources);
1657
+ }
1658
+ /** 2D array: multiple layers, each may carry multiple mip levels */
1659
+ setTextureArrayData(data) {
1660
+ if (this.texture.props.dimension !== "2d-array") {
1661
+ throw new Error(`${this} is not 2d-array`);
1662
+ }
1663
+ const subresources = getTextureArraySubresources(data);
1664
+ this._setTextureSubresources(subresources);
1665
+ }
1666
+ /** Cube: 6 faces, each may carry multiple mip levels */
1667
+ setTextureCubeData(data) {
1668
+ if (this.texture.props.dimension !== "cube") {
1669
+ throw new Error(`${this} is not cube`);
1670
+ }
1671
+ const subresources = getTextureCubeSubresources(data);
1672
+ this._setTextureSubresources(subresources);
1673
+ }
1674
+ /** Cube array: multiple cubes (faces×layers), each face may carry multiple mips */
1675
+ setTextureCubeArrayData(data) {
1676
+ if (this.texture.props.dimension !== "cube-array") {
1677
+ throw new Error(`${this} is not cube-array`);
1678
+ }
1679
+ const subresources = getTextureCubeArraySubresources(data);
1680
+ this._setTextureSubresources(subresources);
1681
+ }
1682
+ /** Sets multiple mip levels on different `z` slices (depth/array index) */
1683
+ _setTextureSubresources(subresources) {
1684
+ for (const subresource of subresources) {
1685
+ const { z, mipLevel } = subresource;
1686
+ switch (subresource.type) {
1687
+ case "external-image":
1688
+ const { image, flipY } = subresource;
1689
+ this.texture.copyExternalImage({ image, z, mipLevel, flipY });
1690
+ break;
1691
+ case "texture-data":
1692
+ const { data } = subresource;
1693
+ this.texture.copyImageData({ data: data.data, z, mipLevel });
1694
+ break;
1695
+ default:
1696
+ throw new Error("Unsupported 2D mip-level payload");
1532
1697
  }
1533
1698
  }
1534
1699
  }
1535
- /**
1536
- * Experimental: Sets 3D texture data: multiple depth slices, multiple mip levels
1537
- * @param data
1538
- */
1539
- _setTexture3DData(texture, data) {
1540
- var _a;
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
- }
1700
+ // ------------------ helpers ------------------
1701
+ /** Recursively resolve all promises in data structures */
1702
+ async _loadAllData(props) {
1703
+ const syncData = await awaitAllPromises(props.data);
1704
+ const dimension = props.dimension ?? "2d";
1705
+ return { dimension, data: syncData ?? null };
1547
1706
  }
1548
- /**
1549
- * Experimental: Set Cube texture data, multiple faces, multiple mip levels
1550
- * @todo - could support TextureCubeArray with depth
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.`)();
1707
+ _checkNotDestroyed() {
1708
+ if (this.destroyed) {
1709
+ import_core9.log.warn(`${this} already destroyed`);
1588
1710
  }
1589
- const faceDepth = TextureCubeFaces.indexOf(face);
1590
- this._setTexture2DData(lodData, faceDepth);
1591
1711
  }
1592
- /**
1593
- * Normalize TextureData to an array of TextureImageData / ExternalImages
1594
- * @param data
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;
1712
+ _checkReady() {
1713
+ if (!this.isReady) {
1714
+ import_core9.log.warn(`${this} Cannot perform this operation before ready`);
1615
1715
  }
1616
- return mipLevelArray;
1617
1716
  }
1618
1717
  };
1619
- var AsyncTexture = _AsyncTexture;
1620
- __publicField(AsyncTexture, "defaultProps", {
1621
- ...import_core8.Texture.defaultProps,
1718
+ var DynamicTexture = _DynamicTexture;
1719
+ __publicField(DynamicTexture, "defaultProps", {
1720
+ ...import_core9.Texture.defaultProps,
1721
+ dimension: "2d",
1622
1722
  data: null,
1623
1723
  mipmaps: false
1624
1724
  });
@@ -1644,16 +1744,24 @@ async function awaitAllPromises(x) {
1644
1744
  var LOG_DRAW_PRIORITY = 2;
1645
1745
  var LOG_DRAW_TIMEOUT = 1e4;
1646
1746
  var _Model = class {
1747
+ /** Device that created this model */
1647
1748
  device;
1749
+ /** Application provided identifier */
1648
1750
  id;
1751
+ /** WGSL shader source when using unified shader */
1649
1752
  // @ts-expect-error assigned in function called from constructor
1650
1753
  source;
1754
+ /** GLSL vertex shader source */
1651
1755
  // @ts-expect-error assigned in function called from constructor
1652
1756
  vs;
1757
+ /** GLSL fragment shader source */
1653
1758
  // @ts-expect-error assigned in function called from constructor
1654
1759
  fs;
1760
+ /** Factory used to create render pipelines */
1655
1761
  pipelineFactory;
1762
+ /** Factory used to create shaders */
1656
1763
  shaderFactory;
1764
+ /** User-supplied per-model data */
1657
1765
  userData = {};
1658
1766
  // Fixed properties (change can trigger pipeline rebuild)
1659
1767
  /** The render pipeline GPU parameters, depth testing etc */
@@ -1730,7 +1838,7 @@ var _Model = class {
1730
1838
  });
1731
1839
  this.source = source3;
1732
1840
  this._getModuleUniforms = getUniforms2;
1733
- this.props.shaderLayout ||= (0, import_shadertools2.getShaderLayoutFromWGSL)(this.source);
1841
+ this.props.shaderLayout ||= device.getShaderLayout(this.source);
1734
1842
  } else {
1735
1843
  const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
1736
1844
  platformInfo,
@@ -1783,7 +1891,6 @@ var _Model = class {
1783
1891
  if (props.transformFeedback) {
1784
1892
  this.transformFeedback = props.transformFeedback;
1785
1893
  }
1786
- Object.seal(this);
1787
1894
  }
1788
1895
  destroy() {
1789
1896
  var _a;
@@ -1812,14 +1919,20 @@ var _Model = class {
1812
1919
  setNeedsRedraw(reason) {
1813
1920
  this._needsRedraw ||= reason;
1814
1921
  }
1922
+ /** Update uniforms and pipeline state prior to drawing. */
1815
1923
  predraw() {
1816
1924
  this.updateShaderInputs();
1817
1925
  this.pipeline = this._updatePipeline();
1818
1926
  }
1927
+ /**
1928
+ * Issue one draw call.
1929
+ * @param renderPass - render pass to draw into
1930
+ * @returns `true` if the draw call was executed, `false` if resources were not ready.
1931
+ */
1819
1932
  draw(renderPass) {
1820
1933
  const loadingBinding = this._areBindingsLoading();
1821
1934
  if (loadingBinding) {
1822
- import_core9.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1935
+ import_core10.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1823
1936
  return false;
1824
1937
  }
1825
1938
  try {
@@ -1947,7 +2060,7 @@ var _Model = class {
1947
2060
  /** Set the shader inputs */
1948
2061
  setShaderInputs(shaderInputs) {
1949
2062
  this.shaderInputs = shaderInputs;
1950
- this._uniformStore = new import_core9.UniformStore(this.shaderInputs.modules);
2063
+ this._uniformStore = new import_core10.UniformStore(this.shaderInputs.modules);
1951
2064
  for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
1952
2065
  if (shaderModuleHasUniforms(module2)) {
1953
2066
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
@@ -1991,7 +2104,7 @@ var _Model = class {
1991
2104
  setAttributes(buffers, options) {
1992
2105
  const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
1993
2106
  if (buffers["indices"]) {
1994
- import_core9.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
2107
+ import_core10.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
1995
2108
  }
1996
2109
  this.bufferLayout = sortedBufferLayoutByShaderSourceLocations(this.pipeline.shaderLayout, this.bufferLayout);
1997
2110
  const bufferLayoutHelper = new BufferLayoutHelper(this.bufferLayout);
@@ -1999,7 +2112,7 @@ var _Model = class {
1999
2112
  const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
2000
2113
  if (!bufferLayout) {
2001
2114
  if (!disableWarnings) {
2002
- import_core9.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2115
+ import_core10.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
2003
2116
  }
2004
2117
  continue;
2005
2118
  }
@@ -2014,7 +2127,7 @@ var _Model = class {
2014
2127
  }
2015
2128
  }
2016
2129
  if (!set && !disableWarnings) {
2017
- import_core9.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
2130
+ import_core10.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
2018
2131
  }
2019
2132
  }
2020
2133
  this.setNeedsRedraw("attributes");
@@ -2033,7 +2146,7 @@ var _Model = class {
2033
2146
  if (attributeInfo) {
2034
2147
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
2035
2148
  } else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
2036
- import_core9.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
2149
+ import_core10.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
2037
2150
  }
2038
2151
  }
2039
2152
  this.setNeedsRedraw("constants");
@@ -2042,7 +2155,7 @@ var _Model = class {
2042
2155
  /** Check that bindings are loaded. Returns id of first binding that is still loading. */
2043
2156
  _areBindingsLoading() {
2044
2157
  for (const binding of Object.values(this.bindings)) {
2045
- if (binding instanceof AsyncTexture && !binding.isReady) {
2158
+ if (binding instanceof DynamicTexture && !binding.isReady) {
2046
2159
  return binding.id;
2047
2160
  }
2048
2161
  }
@@ -2052,7 +2165,7 @@ var _Model = class {
2052
2165
  _getBindings() {
2053
2166
  const validBindings = {};
2054
2167
  for (const [name, binding] of Object.entries(this.bindings)) {
2055
- if (binding instanceof AsyncTexture) {
2168
+ if (binding instanceof DynamicTexture) {
2056
2169
  if (binding.isReady) {
2057
2170
  validBindings[name] = binding.texture;
2058
2171
  }
@@ -2066,16 +2179,16 @@ var _Model = class {
2066
2179
  _getBindingsUpdateTimestamp() {
2067
2180
  let timestamp = 0;
2068
2181
  for (const binding of Object.values(this.bindings)) {
2069
- if (binding instanceof import_core9.TextureView) {
2182
+ if (binding instanceof import_core10.TextureView) {
2070
2183
  timestamp = Math.max(timestamp, binding.texture.updateTimestamp);
2071
- } else if (binding instanceof import_core9.Buffer || binding instanceof import_core9.Texture) {
2184
+ } else if (binding instanceof import_core10.Buffer || binding instanceof import_core10.Texture) {
2072
2185
  timestamp = Math.max(timestamp, binding.updateTimestamp);
2073
- } else if (binding instanceof AsyncTexture) {
2186
+ } else if (binding instanceof DynamicTexture) {
2074
2187
  timestamp = binding.texture ? Math.max(timestamp, binding.texture.updateTimestamp) : (
2075
2188
  // The texture will become available in the future
2076
2189
  Infinity
2077
2190
  );
2078
- } else if (!(binding instanceof import_core9.Sampler)) {
2191
+ } else if (!(binding instanceof import_core10.Sampler)) {
2079
2192
  timestamp = Math.max(timestamp, binding.buffer.updateTimestamp);
2080
2193
  }
2081
2194
  }
@@ -2110,7 +2223,7 @@ var _Model = class {
2110
2223
  let prevShaderVs = null;
2111
2224
  let prevShaderFs = null;
2112
2225
  if (this.pipeline) {
2113
- import_core9.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
2226
+ import_core10.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
2114
2227
  prevShaderVs = this.pipeline.vs;
2115
2228
  prevShaderFs = this.pipeline.fs;
2116
2229
  }
@@ -2143,7 +2256,7 @@ var _Model = class {
2143
2256
  vs: vs3,
2144
2257
  fs: fs3
2145
2258
  });
2146
- this._attributeInfos = (0, import_core9.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
2259
+ this._attributeInfos = (0, import_core10.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
2147
2260
  if (prevShaderVs)
2148
2261
  this.shaderFactory.release(prevShaderVs);
2149
2262
  if (prevShaderFs)
@@ -2155,24 +2268,24 @@ var _Model = class {
2155
2268
  _lastLogTime = 0;
2156
2269
  _logOpen = false;
2157
2270
  _logDrawCallStart() {
2158
- const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2159
- if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2271
+ const logDrawTimeout = import_core10.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
2272
+ if (import_core10.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
2160
2273
  return;
2161
2274
  }
2162
2275
  this._lastLogTime = Date.now();
2163
2276
  this._logOpen = true;
2164
- import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
2277
+ import_core10.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core10.log.level <= 2 })();
2165
2278
  }
2166
2279
  _logDrawCallEnd() {
2167
2280
  if (this._logOpen) {
2168
2281
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
2169
- import_core9.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
2282
+ import_core10.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
2170
2283
  const uniformTable = this.shaderInputs.getDebugTable();
2171
- import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
2284
+ import_core10.log.table(LOG_DRAW_PRIORITY, uniformTable)();
2172
2285
  const attributeTable = this._getAttributeDebugTable();
2173
- import_core9.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2174
- import_core9.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2175
- import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
2286
+ import_core10.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
2287
+ import_core10.log.table(LOG_DRAW_PRIORITY, attributeTable)();
2288
+ import_core10.log.groupEnd(LOG_DRAW_PRIORITY)();
2176
2289
  this._logOpen = false;
2177
2290
  }
2178
2291
  }
@@ -2211,14 +2324,14 @@ var _Model = class {
2211
2324
  }
2212
2325
  // TODO - fix typing of luma data types
2213
2326
  _getBufferOrConstantValues(attribute, dataType) {
2214
- const TypedArrayConstructor = (0, import_core9.getTypedArrayConstructor)(dataType);
2215
- const typedArray = attribute instanceof import_core9.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2327
+ const TypedArrayConstructor = (0, import_core10.getTypedArrayConstructor)(dataType);
2328
+ const typedArray = attribute instanceof import_core10.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
2216
2329
  return typedArray.toString();
2217
2330
  }
2218
2331
  };
2219
2332
  var Model = _Model;
2220
2333
  __publicField(Model, "defaultProps", {
2221
- ...import_core9.RenderPipeline.defaultProps,
2334
+ ...import_core10.RenderPipeline.defaultProps,
2222
2335
  source: void 0,
2223
2336
  vs: null,
2224
2337
  fs: null,
@@ -2264,7 +2377,7 @@ function isObjectEmpty(obj) {
2264
2377
  }
2265
2378
 
2266
2379
  // dist/compute/buffer-transform.js
2267
- var import_core10 = require("@luma.gl/core");
2380
+ var import_core11 = require("@luma.gl/core");
2268
2381
  var import_shadertools3 = require("@luma.gl/shadertools");
2269
2382
  var _BufferTransform = class {
2270
2383
  device;
@@ -2327,7 +2440,7 @@ var _BufferTransform = class {
2327
2440
  if (!result) {
2328
2441
  throw new Error("BufferTransform#getBuffer");
2329
2442
  }
2330
- if (result instanceof import_core10.Buffer) {
2443
+ if (result instanceof import_core11.Buffer) {
2331
2444
  return result.readAsync();
2332
2445
  }
2333
2446
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
@@ -2604,22 +2717,31 @@ ${props.source}` };
2604
2717
  };
2605
2718
 
2606
2719
  // dist/models/billboard-texture-model.js
2720
+ var backgroundModule = {
2721
+ name: "background",
2722
+ uniformTypes: {
2723
+ scale: "vec2<f32>"
2724
+ }
2725
+ };
2607
2726
  var BACKGROUND_FS_WGSL = (
2608
2727
  /* wgsl */
2609
2728
  `@group(0) @binding(0) var backgroundTexture: texture_2d<f32>;
2610
2729
  @group(0) @binding(1) var backgroundTextureSampler: sampler;
2730
+ struct backgroundUniforms {
2731
+ scale: vec2<f32>,
2732
+ };
2733
+ @group(0) @binding(2) var<uniform> background: backgroundUniforms;
2611
2734
 
2612
2735
  fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
2613
- let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0);
2614
- let texSize: vec2<f32> = vec2<f32>(f32(iTexSize.x), f32(iTexSize.y));
2615
- var position: vec2<f32> = coordinates.xy / texSize;
2616
- return position;
2617
- }
2736
+ let scale: vec2<f32> = background.scale;
2737
+ var position: vec2<f32> = (coordinates - vec2<f32>(0.5, 0.5)) / scale + vec2<f32>(0.5, 0.5);
2738
+ return position;
2739
+ }
2618
2740
 
2619
2741
  @fragment
2620
2742
  fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
2621
- let position: vec2<f32> = billboardTexture_getTextureUV(inputs.coordinate);
2622
- return textureSample(backgroundTexture, backgroundTextureSampler, position);
2743
+ let position: vec2<f32> = billboardTexture_getTextureUV(inputs.coordinate);
2744
+ return textureSample(backgroundTexture, backgroundTextureSampler, position);
2623
2745
  }
2624
2746
  `
2625
2747
  );
@@ -2629,27 +2751,33 @@ var BACKGROUND_FS = (
2629
2751
  precision highp float;
2630
2752
 
2631
2753
  uniform sampler2D backgroundTexture;
2754
+
2755
+ uniform backgroundUniforms {
2756
+ vec2 scale;
2757
+ } background;
2758
+
2759
+ in vec2 coordinate;
2632
2760
  out vec4 fragColor;
2633
2761
 
2634
- vec2 billboardTexture_getTextureUV() {
2635
- ivec2 iTexSize = textureSize(backgroundTexture, 0);
2636
- vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
2637
- vec2 position = gl_FragCoord.xy / texSize;
2762
+ vec2 billboardTexture_getTextureUV(vec2 coord) {
2763
+ vec2 position = (coord - 0.5) / background.scale + 0.5;
2638
2764
  return position;
2639
2765
  }
2640
2766
 
2641
2767
  void main(void) {
2642
- vec2 position = billboardTexture_getTextureUV();
2768
+ vec2 position = billboardTexture_getTextureUV(coordinate);
2643
2769
  fragColor = texture(backgroundTexture, position);
2644
2770
  }
2645
2771
  `
2646
2772
  );
2647
2773
  var BackgroundTextureModel = class extends ClipSpace {
2774
+ backgroundTexture = null;
2648
2775
  constructor(device, props) {
2649
2776
  super(device, {
2650
2777
  id: props.id || "background-texture-model",
2651
2778
  source: BACKGROUND_FS_WGSL,
2652
2779
  fs: BACKGROUND_FS,
2780
+ modules: [backgroundModule],
2653
2781
  parameters: {
2654
2782
  depthWriteEnabled: false,
2655
2783
  ...props.blend ? {
@@ -2666,28 +2794,58 @@ var BackgroundTextureModel = class extends ClipSpace {
2666
2794
  if (!props.backgroundTexture) {
2667
2795
  throw new Error("BackgroundTextureModel requires a backgroundTexture prop");
2668
2796
  }
2669
- this.setTexture(props.backgroundTexture);
2797
+ this.setProps(props);
2670
2798
  }
2671
- setTexture(backgroundTexture) {
2672
- this.setBindings({
2673
- backgroundTexture
2674
- });
2799
+ /** Update the background texture */
2800
+ setProps(props) {
2801
+ const { backgroundTexture } = props;
2802
+ if (backgroundTexture) {
2803
+ this.setBindings({ backgroundTexture });
2804
+ if (backgroundTexture.isReady) {
2805
+ const texture = backgroundTexture instanceof DynamicTexture ? backgroundTexture.texture : backgroundTexture;
2806
+ this.backgroundTexture = texture;
2807
+ this.updateScale(texture);
2808
+ } else {
2809
+ backgroundTexture.ready.then((texture) => {
2810
+ this.backgroundTexture = texture;
2811
+ this.updateScale(texture);
2812
+ });
2813
+ }
2814
+ }
2675
2815
  }
2676
2816
  predraw() {
2677
- this.shaderInputs.setProps({});
2678
2817
  super.predraw();
2679
2818
  }
2819
+ updateScale(texture) {
2820
+ if (!texture) {
2821
+ this.shaderInputs.setProps({ background: { scale: [1, 1] } });
2822
+ return;
2823
+ }
2824
+ const [screenWidth, screenHeight] = this.device.getCanvasContext().getDrawingBufferSize();
2825
+ const textureWidth = texture.width;
2826
+ const textureHeight = texture.height;
2827
+ const screenAspect = screenWidth / screenHeight;
2828
+ const textureAspect = textureWidth / textureHeight;
2829
+ let scaleX = 1;
2830
+ let scaleY = 1;
2831
+ if (screenAspect > textureAspect) {
2832
+ scaleY = screenAspect / textureAspect;
2833
+ } else {
2834
+ scaleX = textureAspect / screenAspect;
2835
+ }
2836
+ this.shaderInputs.setProps({ background: { scale: [scaleX, scaleY] } });
2837
+ }
2680
2838
  };
2681
2839
 
2682
2840
  // dist/scenegraph/scenegraph-node.js
2683
- var import_core11 = require("@math.gl/core");
2841
+ var import_core12 = require("@math.gl/core");
2684
2842
  var ScenegraphNode = class {
2685
2843
  id;
2686
- matrix = new import_core11.Matrix4();
2844
+ matrix = new import_core12.Matrix4();
2687
2845
  display = true;
2688
- position = new import_core11.Vector3();
2689
- rotation = new import_core11.Vector3();
2690
- scale = new import_core11.Vector3(1, 1, 1);
2846
+ position = new import_core12.Vector3();
2847
+ rotation = new import_core12.Vector3();
2848
+ scale = new import_core12.Vector3(1, 1, 1);
2691
2849
  userData = {};
2692
2850
  props = {};
2693
2851
  constructor(props = {}) {
@@ -2772,7 +2930,7 @@ var ScenegraphNode = class {
2772
2930
  }
2773
2931
  getCoordinateUniforms(viewMatrix, modelMatrix) {
2774
2932
  modelMatrix = modelMatrix || this.matrix;
2775
- const worldMatrix = new import_core11.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2933
+ const worldMatrix = new import_core12.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2776
2934
  const worldInverse = worldMatrix.invert();
2777
2935
  const worldInverseTranspose = worldInverse.transpose();
2778
2936
  return {
@@ -2824,14 +2982,14 @@ var ScenegraphNode = class {
2824
2982
  };
2825
2983
 
2826
2984
  // dist/scenegraph/group-node.js
2827
- var import_core12 = require("@math.gl/core");
2828
- var import_core13 = require("@luma.gl/core");
2985
+ var import_core13 = require("@math.gl/core");
2986
+ var import_core14 = require("@luma.gl/core");
2829
2987
  var GroupNode = class extends ScenegraphNode {
2830
2988
  children;
2831
2989
  constructor(props = {}) {
2832
2990
  props = Array.isArray(props) ? { children: props } : props;
2833
2991
  const { children = [] } = props;
2834
- import_core13.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2992
+ import_core14.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2835
2993
  super(props);
2836
2994
  this.children = children;
2837
2995
  }
@@ -2846,12 +3004,12 @@ var GroupNode = class extends ScenegraphNode {
2846
3004
  return;
2847
3005
  }
2848
3006
  const [min, max] = bounds;
2849
- const center = new import_core12.Vector3(min).add(max).divide([2, 2, 2]);
3007
+ const center = new import_core13.Vector3(min).add(max).divide([2, 2, 2]);
2850
3008
  worldMatrix.transformAsPoint(center, center);
2851
- const halfSize = new import_core12.Vector3(max).subtract(min).divide([2, 2, 2]);
3009
+ const halfSize = new import_core13.Vector3(max).subtract(min).divide([2, 2, 2]);
2852
3010
  worldMatrix.transformAsVector(halfSize, halfSize);
2853
3011
  for (let v = 0; v < 8; v++) {
2854
- const position = new import_core12.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
3012
+ const position = new import_core13.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
2855
3013
  for (let i = 0; i < 3; i++) {
2856
3014
  result[0][i] = Math.min(result[0][i], position[i]);
2857
3015
  result[1][i] = Math.max(result[1][i], position[i]);
@@ -2891,8 +3049,8 @@ var GroupNode = class extends ScenegraphNode {
2891
3049
  this.children = [];
2892
3050
  return this;
2893
3051
  }
2894
- traverse(visitor, { worldMatrix = new import_core12.Matrix4() } = {}) {
2895
- const modelMatrix = new import_core12.Matrix4(worldMatrix).multiplyRight(this.matrix);
3052
+ traverse(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
3053
+ const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
2896
3054
  for (const child of this.children) {
2897
3055
  if (child instanceof GroupNode) {
2898
3056
  child.traverse(visitor, { worldMatrix: modelMatrix });
@@ -3674,7 +3832,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
3674
3832
  };
3675
3833
 
3676
3834
  // dist/geometries/ico-sphere-geometry.js
3677
- var import_core14 = require("@math.gl/core");
3835
+ var import_core15 = require("@math.gl/core");
3678
3836
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
3679
3837
  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
3838
  var IcoSphereGeometry = class extends Geometry {
@@ -3772,7 +3930,7 @@ function tesselateIcosaHedron(props) {
3772
3930
  const u3 = 1 - phi3 / PI2;
3773
3931
  const vec1 = [x3 - x2, y3 - y2, z3 - z2];
3774
3932
  const vec2 = [x1 - x2, y1 - y2, z1 - z2];
3775
- const normal = new import_core14.Vector3(vec1).cross(vec2).normalize();
3933
+ const normal = new import_core15.Vector3(vec1).cross(vec2).normalize();
3776
3934
  let newIndex;
3777
3935
  if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
3778
3936
  positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
@@ -4032,17 +4190,45 @@ function fract(n) {
4032
4190
  return n - Math.floor(n);
4033
4191
  }
4034
4192
 
4193
+ // dist/application-utils/load-file.js
4194
+ var pathPrefix = "";
4195
+ function setPathPrefix(prefix) {
4196
+ pathPrefix = prefix;
4197
+ }
4198
+ async function loadImageBitmap(url, opts) {
4199
+ const image = new Image();
4200
+ image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
4201
+ image.src = url.startsWith("http") ? url : pathPrefix + url;
4202
+ await image.decode();
4203
+ return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
4204
+ }
4205
+ async function loadImage(url, opts) {
4206
+ return await new Promise((resolve, reject) => {
4207
+ try {
4208
+ const image = new Image();
4209
+ image.onload = () => resolve(image);
4210
+ image.onerror = () => reject(new Error(`Could not load image ${url}.`));
4211
+ image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
4212
+ image.src = url.startsWith("http") ? url : pathPrefix + url;
4213
+ } catch (error) {
4214
+ reject(error);
4215
+ }
4216
+ });
4217
+ }
4218
+
4035
4219
  // dist/passes/shader-pass-renderer.js
4036
4220
  var import_shadertools5 = require("@luma.gl/shadertools");
4037
4221
 
4038
4222
  // dist/compute/swap.js
4039
- var import_core15 = require("@luma.gl/core");
4223
+ var import_core16 = require("@luma.gl/core");
4040
4224
  var Swap = class {
4225
+ id;
4041
4226
  /** The current resource - usually the source for renders or computations */
4042
4227
  current;
4043
4228
  /** The next resource - usually the target/destination for transforms / computations */
4044
4229
  next;
4045
4230
  constructor(props) {
4231
+ this.id = props.id || "swap";
4046
4232
  this.current = props.current;
4047
4233
  this.next = props.next;
4048
4234
  }
@@ -4063,18 +4249,21 @@ var SwapFramebuffers = class extends Swap {
4063
4249
  constructor(device, props) {
4064
4250
  var _a, _b;
4065
4251
  props = { ...props };
4252
+ const { width = 1, height = 1 } = props;
4066
4253
  let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
4254
+ id: `${props.id}-texture-0`,
4067
4255
  format: colorAttachment,
4068
- usage: import_core15.Texture.SAMPLE | import_core15.Texture.RENDER | import_core15.Texture.COPY_SRC | import_core15.Texture.COPY_DST,
4069
- width: 1,
4070
- height: 1
4256
+ usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
4257
+ width,
4258
+ height
4071
4259
  }));
4072
4260
  const current = device.createFramebuffer({ ...props, colorAttachments });
4073
4261
  colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
4262
+ id: `${props.id}-texture-1`,
4074
4263
  format: colorAttachment,
4075
- usage: import_core15.Texture.TEXTURE | import_core15.Texture.COPY_SRC | import_core15.Texture.COPY_DST | import_core15.Texture.RENDER_ATTACHMENT,
4076
- width: 1,
4077
- height: 1
4264
+ usage: import_core16.Texture.SAMPLE | import_core16.Texture.RENDER | import_core16.Texture.COPY_SRC | import_core16.Texture.COPY_DST,
4265
+ width,
4266
+ height
4078
4267
  }));
4079
4268
  const next = device.createFramebuffer({ ...props, colorAttachments });
4080
4269
  super({ current, next });
@@ -4138,19 +4327,23 @@ function getFilterShaderWGSL(func) {
4138
4327
  `// Binding 0:1 is reserved for shader passes
4139
4328
  // @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
4140
4329
  @group(0) @binding(1) var texture: texture_2d<f32>;
4141
- @group(0) @binding(2) var sampler: sampler;
4330
+ @group(0) @binding(2) var textureSampler: sampler;
4142
4331
 
4143
- struct FragmentInputs {
4144
- @location(0) fragUV: vec2f,
4145
- @location(1) fragPosition: vec4f,
4146
- @location(2) fragCoordinate: vec4f
4147
- };
4332
+ // This needs to be aligned with
4333
+ // struct FragmentInputs {
4334
+ // @location(0) fragUV: vec2f,
4335
+ // @location(1) fragPosition: vec4f,
4336
+ // @location(2) fragCoordinate: vec4f
4337
+ // };
4148
4338
 
4149
4339
  @fragment
4150
4340
  fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
4151
- let texSize = textureDimensions(texture, 0);
4152
- var fragColor = textureSample(texture, sampler, fragUV);
4153
- fragColor = ${func}(gl_FragColor, texSize, texCoord);
4341
+ let fragUV = inputs.uv;
4342
+ let fragCoordinate = inputs.coordinate;
4343
+ let texSize = vec2f(textureDimensions(texture, 0));
4344
+
4345
+ var fragColor = textureSample(texture, textureSampler, fragUV);
4346
+ fragColor = ${func}(fragColor, texSize, fragCoordinate);
4154
4347
  return fragColor;
4155
4348
  }
4156
4349
  `
@@ -4172,9 +4365,9 @@ struct FragmentInputs = {
4172
4365
 
4173
4366
  @fragment
4174
4367
  fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
4175
- let texSize = textureDimensions(texture, 0);
4368
+ let texSize = vec2f(textureDimensions(texture, 0));
4176
4369
  var fragColor = textureSample(texture, sampler, fragUV);
4177
- fragColor = ${func}(gl_FragColor, texSize, texCoord);
4370
+ fragColor = ${func}(fragColor, texSize, texCoord);
4178
4371
  return fragColor;
4179
4372
  }
4180
4373
  `
@@ -4270,12 +4463,10 @@ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
4270
4463
 
4271
4464
  uniform sampler2D sourceTexture;
4272
4465
  in vec2 uv;
4273
- in vec2 coordinate;
4274
4466
  out vec4 fragColor;
4275
4467
 
4276
4468
  void main() {
4277
- vec2 texCoord = coordinate;
4278
- fragColor = texture(sourceTexture, coordinate);
4469
+ fragColor = texture(sourceTexture, uv);
4279
4470
  }
4280
4471
  `
4281
4472
  )
@@ -4289,9 +4480,11 @@ void main() {
4289
4480
  }
4290
4481
  this.swapFramebuffers.destroy();
4291
4482
  this.clipSpace.destroy();
4483
+ this.textureModel.destroy();
4292
4484
  }
4293
- resize(width, height) {
4294
- this.swapFramebuffers.resize({ width, height });
4485
+ resize(size) {
4486
+ size ||= this.device.getCanvasContext().getDrawingBufferSize();
4487
+ this.swapFramebuffers.resize({ width: size[0], height: size[1] });
4295
4488
  }
4296
4489
  renderToScreen(options) {
4297
4490
  const outputTexture = this.renderToTexture(options);
@@ -4302,7 +4495,7 @@ void main() {
4302
4495
  const renderPass = this.device.beginRenderPass({
4303
4496
  id: "shader-pass-renderer-to-screen",
4304
4497
  framebuffer,
4305
- clearColor: [0, 0, 0, 1],
4498
+ // clearColor: [1, 1, 0, 1],
4306
4499
  clearDepth: 1
4307
4500
  });
4308
4501
  this.clipSpace.setBindings({ sourceTexture: outputTexture });
@@ -4318,14 +4511,14 @@ void main() {
4318
4511
  if (!sourceTexture.isReady) {
4319
4512
  return null;
4320
4513
  }
4321
- this.textureModel.destroy();
4322
- this.textureModel = new BackgroundTextureModel(this.device, {
4323
- backgroundTexture: sourceTexture
4324
- });
4514
+ if (this.passRenderers.length === 0) {
4515
+ return sourceTexture.texture;
4516
+ }
4517
+ this.textureModel.setProps({ backgroundTexture: sourceTexture });
4325
4518
  const clearTexturePass = this.device.beginRenderPass({
4326
4519
  id: "shader-pass-renderer-clear-texture",
4327
4520
  framebuffer: this.swapFramebuffers.current,
4328
- clearColor: [0, 0, 0, 1]
4521
+ clearColor: [1, 0, 0, 1]
4329
4522
  });
4330
4523
  this.textureModel.draw(clearTexturePass);
4331
4524
  clearTexturePass.end();
@@ -4412,7 +4605,7 @@ var SubPassRenderer = class {
4412
4605
  };
4413
4606
 
4414
4607
  // dist/compute/computation.js
4415
- var import_core16 = require("@luma.gl/core");
4608
+ var import_core17 = require("@luma.gl/core");
4416
4609
  var import_shadertools6 = require("@luma.gl/shadertools");
4417
4610
  var import_types2 = require("@math.gl/types");
4418
4611
  var LOG_DRAW_PRIORITY2 = 2;
@@ -4453,7 +4646,7 @@ var _Computation = class {
4453
4646
  const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
4454
4647
  this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
4455
4648
  this.setShaderInputs(this.shaderInputs);
4456
- this.props.shaderLayout ||= (0, import_shadertools6.getShaderLayoutFromWGSL)(this.props.source);
4649
+ this.props.shaderLayout ||= device.getShaderLayout(this.props.source);
4457
4650
  const platformInfo = getPlatformInfo2(device);
4458
4651
  const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
4459
4652
  this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
@@ -4511,7 +4704,7 @@ var _Computation = class {
4511
4704
  }
4512
4705
  setShaderInputs(shaderInputs) {
4513
4706
  this.shaderInputs = shaderInputs;
4514
- this._uniformStore = new import_core16.UniformStore(this.shaderInputs.modules);
4707
+ this._uniformStore = new import_core17.UniformStore(this.shaderInputs.modules);
4515
4708
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
4516
4709
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
4517
4710
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -4548,7 +4741,7 @@ var _Computation = class {
4548
4741
  if (this._pipelineNeedsUpdate) {
4549
4742
  let prevShader = null;
4550
4743
  if (this.pipeline) {
4551
- import_core16.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
4744
+ import_core17.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
4552
4745
  prevShader = this.shader;
4553
4746
  }
4554
4747
  this._pipelineNeedsUpdate = false;
@@ -4572,33 +4765,33 @@ var _Computation = class {
4572
4765
  _lastLogTime = 0;
4573
4766
  _logOpen = false;
4574
4767
  _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) {
4768
+ const logDrawTimeout = import_core17.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
4769
+ if (import_core17.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
4577
4770
  return;
4578
4771
  }
4579
4772
  this._lastLogTime = Date.now();
4580
4773
  this._logOpen = true;
4581
- import_core16.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core16.log.level <= 2 })();
4774
+ import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
4582
4775
  }
4583
4776
  _logDrawCallEnd() {
4584
4777
  if (this._logOpen) {
4585
4778
  const uniformTable = this.shaderInputs.getDebugTable();
4586
- import_core16.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
4587
- import_core16.log.groupEnd(LOG_DRAW_PRIORITY2)();
4779
+ import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
4780
+ import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
4588
4781
  this._logOpen = false;
4589
4782
  }
4590
4783
  }
4591
4784
  _drawCount = 0;
4592
4785
  // TODO - fix typing of luma data types
4593
4786
  _getBufferOrConstantValues(attribute, dataType) {
4594
- const TypedArrayConstructor = (0, import_core16.getTypedArrayConstructor)(dataType);
4595
- const typedArray = attribute instanceof import_core16.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
4787
+ const TypedArrayConstructor = (0, import_core17.getTypedArrayConstructor)(dataType);
4788
+ const typedArray = attribute instanceof import_core17.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
4596
4789
  return typedArray.toString();
4597
4790
  }
4598
4791
  };
4599
4792
  var Computation = _Computation;
4600
4793
  __publicField(Computation, "defaultProps", {
4601
- ...import_core16.ComputePipeline.defaultProps,
4794
+ ...import_core17.ComputePipeline.defaultProps,
4602
4795
  id: "unnamed",
4603
4796
  handle: void 0,
4604
4797
  userData: {},
@@ -5161,4 +5354,7 @@ var LegacyPickingManager = class {
5161
5354
  return [pickX, pickY];
5162
5355
  }
5163
5356
  };
5357
+
5358
+ // dist/index.js
5359
+ var AsyncTexture = DynamicTexture;
5164
5360
  //# sourceMappingURL=index.cjs.map