@luma.gl/engine 9.1.0-alpha.9 → 9.1.0-beta.11

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 (194) hide show
  1. package/dist/animation/key-frames.js +1 -0
  2. package/dist/animation/key-frames.js.map +1 -0
  3. package/dist/animation/timeline.js +1 -0
  4. package/dist/animation/timeline.js.map +1 -0
  5. package/dist/animation-loop/animation-loop-template.js +1 -0
  6. package/dist/animation-loop/animation-loop-template.js.map +1 -0
  7. package/dist/animation-loop/animation-loop.d.ts +2 -0
  8. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  9. package/dist/animation-loop/animation-loop.js +24 -6
  10. package/dist/animation-loop/animation-loop.js.map +1 -0
  11. package/dist/animation-loop/animation-props.js +1 -0
  12. package/dist/animation-loop/animation-props.js.map +1 -0
  13. package/dist/animation-loop/make-animation-loop.d.ts +5 -1
  14. package/dist/animation-loop/make-animation-loop.d.ts.map +1 -1
  15. package/dist/animation-loop/make-animation-loop.js +3 -1
  16. package/dist/animation-loop/make-animation-loop.js.map +1 -0
  17. package/dist/animation-loop/request-animation-frame.d.ts +4 -2
  18. package/dist/animation-loop/request-animation-frame.d.ts.map +1 -1
  19. package/dist/animation-loop/request-animation-frame.js +5 -3
  20. package/dist/animation-loop/request-animation-frame.js.map +1 -0
  21. package/dist/application-utils/load-file.d.ts +1 -1
  22. package/dist/application-utils/load-file.d.ts.map +1 -1
  23. package/dist/application-utils/load-file.js +2 -2
  24. package/dist/application-utils/load-file.js.map +1 -0
  25. package/dist/application-utils/random.js +1 -0
  26. package/dist/application-utils/random.js.map +1 -0
  27. package/dist/async-texture/async-texture.d.ts +14 -2
  28. package/dist/async-texture/async-texture.d.ts.map +1 -1
  29. package/dist/async-texture/async-texture.js +31 -0
  30. package/dist/async-texture/async-texture.js.map +1 -0
  31. package/dist/compute/buffer-transform.d.ts +41 -0
  32. package/dist/compute/buffer-transform.d.ts.map +1 -0
  33. package/dist/{transform → compute}/buffer-transform.js +19 -12
  34. package/dist/compute/buffer-transform.js.map +1 -0
  35. package/dist/{computation.d.ts → compute/computation.d.ts} +3 -3
  36. package/dist/compute/computation.d.ts.map +1 -0
  37. package/dist/{computation.js → compute/computation.js} +7 -8
  38. package/dist/compute/computation.js.map +1 -0
  39. package/dist/compute/swap.d.ts +48 -0
  40. package/dist/compute/swap.d.ts.map +1 -0
  41. package/dist/compute/swap.js +91 -0
  42. package/dist/compute/swap.js.map +1 -0
  43. package/dist/{transform → compute}/texture-transform.d.ts +0 -6
  44. package/dist/compute/texture-transform.d.ts.map +1 -0
  45. package/dist/{transform → compute}/texture-transform.js +7 -13
  46. package/dist/compute/texture-transform.js.map +1 -0
  47. package/dist/debug/copy-texture-to-image.js +1 -0
  48. package/dist/debug/copy-texture-to-image.js.map +1 -0
  49. package/dist/debug/debug-framebuffer.js +2 -1
  50. package/dist/debug/debug-framebuffer.js.map +1 -0
  51. package/dist/debug/debug-shader-layout.js +2 -1
  52. package/dist/debug/debug-shader-layout.js.map +1 -0
  53. package/dist/debug/pixel-data-utils.js +1 -0
  54. package/dist/debug/pixel-data-utils.js.map +1 -0
  55. package/dist/dist.dev.js +2588 -5862
  56. package/dist/dist.min.js +420 -103
  57. package/dist/factories/pipeline-factory.d.ts.map +1 -0
  58. package/dist/{lib → factories}/pipeline-factory.js +1 -0
  59. package/dist/factories/pipeline-factory.js.map +1 -0
  60. package/dist/factories/shader-factory.d.ts.map +1 -0
  61. package/dist/{lib → factories}/shader-factory.js +1 -0
  62. package/dist/factories/shader-factory.js.map +1 -0
  63. package/dist/geometries/cone-geometry.js +1 -0
  64. package/dist/geometries/cone-geometry.js.map +1 -0
  65. package/dist/geometries/cube-geometry.js +1 -0
  66. package/dist/geometries/cube-geometry.js.map +1 -0
  67. package/dist/geometries/cylinder-geometry.js +1 -0
  68. package/dist/geometries/cylinder-geometry.js.map +1 -0
  69. package/dist/geometries/ico-sphere-geometry.js +1 -0
  70. package/dist/geometries/ico-sphere-geometry.js.map +1 -0
  71. package/dist/geometries/plane-geometry.js +1 -0
  72. package/dist/geometries/plane-geometry.js.map +1 -0
  73. package/dist/geometries/sphere-geometry.js +1 -0
  74. package/dist/geometries/sphere-geometry.js.map +1 -0
  75. package/dist/geometries/truncated-cone-geometry.js +1 -0
  76. package/dist/geometries/truncated-cone-geometry.js.map +1 -0
  77. package/dist/geometry/geometry-table.js +1 -0
  78. package/dist/geometry/geometry-table.js.map +1 -0
  79. package/dist/geometry/geometry-utils.js +1 -0
  80. package/dist/geometry/geometry-utils.js.map +1 -0
  81. package/dist/geometry/geometry.js +1 -0
  82. package/dist/geometry/geometry.js.map +1 -0
  83. package/dist/geometry/gpu-geometry.js +1 -0
  84. package/dist/geometry/gpu-geometry.js.map +1 -0
  85. package/dist/geometry/gpu-table.js +1 -0
  86. package/dist/geometry/gpu-table.js.map +1 -0
  87. package/dist/index.cjs +1268 -173
  88. package/dist/index.cjs.map +4 -4
  89. package/dist/index.d.ts +23 -12
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +19 -9
  92. package/dist/index.js.map +1 -0
  93. package/dist/model/model.d.ts +11 -10
  94. package/dist/model/model.d.ts.map +1 -1
  95. package/dist/model/model.js +77 -58
  96. package/dist/model/model.js.map +1 -0
  97. package/dist/model/split-uniforms-and-bindings.d.ts +1 -1
  98. package/dist/model/split-uniforms-and-bindings.d.ts.map +1 -1
  99. package/dist/model/split-uniforms-and-bindings.js +2 -1
  100. package/dist/model/split-uniforms-and-bindings.js.map +1 -0
  101. package/dist/models/billboard-texture-model.d.ts +23 -0
  102. package/dist/models/billboard-texture-model.d.ts.map +1 -0
  103. package/dist/models/billboard-texture-model.js +78 -0
  104. package/dist/models/billboard-texture-model.js.map +1 -0
  105. package/dist/models/billboard-texture-module.d.ts +10 -0
  106. package/dist/models/billboard-texture-module.d.ts.map +1 -0
  107. package/dist/models/billboard-texture-module.js +37 -0
  108. package/dist/models/billboard-texture-module.js.map +1 -0
  109. package/dist/{lib → models}/clip-space.d.ts +3 -1
  110. package/dist/models/clip-space.d.ts.map +1 -0
  111. package/dist/models/clip-space.js +77 -0
  112. package/dist/models/clip-space.js.map +1 -0
  113. package/dist/modules/picking/color-picking.d.ts +28 -0
  114. package/dist/modules/picking/color-picking.d.ts.map +1 -0
  115. package/dist/modules/picking/color-picking.js +177 -0
  116. package/dist/modules/picking/color-picking.js.map +1 -0
  117. package/dist/modules/picking/index-picking.d.ts +32 -0
  118. package/dist/modules/picking/index-picking.d.ts.map +1 -0
  119. package/dist/modules/picking/index-picking.js +148 -0
  120. package/dist/modules/picking/index-picking.js.map +1 -0
  121. package/dist/modules/picking/legacy-picking-manager.d.ts +27 -0
  122. package/dist/modules/picking/legacy-picking-manager.d.ts.map +1 -0
  123. package/dist/modules/picking/legacy-picking-manager.js +76 -0
  124. package/dist/modules/picking/legacy-picking-manager.js.map +1 -0
  125. package/dist/modules/picking/picking-manager.d.ts +45 -0
  126. package/dist/modules/picking/picking-manager.d.ts.map +1 -0
  127. package/dist/modules/picking/picking-manager.js +101 -0
  128. package/dist/modules/picking/picking-manager.js.map +1 -0
  129. package/dist/modules/picking/picking-uniforms.d.ts +79 -0
  130. package/dist/modules/picking/picking-uniforms.d.ts.map +1 -0
  131. package/dist/modules/picking/picking-uniforms.js +109 -0
  132. package/dist/modules/picking/picking-uniforms.js.map +1 -0
  133. package/dist/passes/get-fragment-shader.d.ts +12 -0
  134. package/dist/passes/get-fragment-shader.d.ts.map +1 -0
  135. package/dist/passes/get-fragment-shader.js +117 -0
  136. package/dist/passes/get-fragment-shader.js.map +1 -0
  137. package/dist/passes/shader-pass-renderer.d.ts +63 -0
  138. package/dist/passes/shader-pass-renderer.d.ts.map +1 -0
  139. package/dist/passes/shader-pass-renderer.js +197 -0
  140. package/dist/passes/shader-pass-renderer.js.map +1 -0
  141. package/dist/scenegraph/group-node.js +1 -0
  142. package/dist/scenegraph/group-node.js.map +1 -0
  143. package/dist/scenegraph/model-node.js +1 -0
  144. package/dist/scenegraph/model-node.js.map +1 -0
  145. package/dist/scenegraph/scenegraph-node.js +1 -0
  146. package/dist/scenegraph/scenegraph-node.js.map +1 -0
  147. package/dist/shader-inputs.d.ts +8 -21
  148. package/dist/shader-inputs.d.ts.map +1 -1
  149. package/dist/shader-inputs.js +15 -11
  150. package/dist/shader-inputs.js.map +1 -0
  151. package/dist/utils/deep-equal.js +1 -0
  152. package/dist/utils/deep-equal.js.map +1 -0
  153. package/dist/utils/uid.js +1 -0
  154. package/dist/utils/uid.js.map +1 -0
  155. package/package.json +6 -6
  156. package/src/animation-loop/animation-loop.ts +27 -6
  157. package/src/animation-loop/make-animation-loop.ts +8 -3
  158. package/src/animation-loop/request-animation-frame.ts +4 -3
  159. package/src/application-utils/load-file.ts +2 -4
  160. package/src/async-texture/async-texture.ts +39 -7
  161. package/src/{transform → compute}/buffer-transform.ts +30 -14
  162. package/src/{computation.ts → compute/computation.ts} +14 -8
  163. package/src/compute/swap.ts +116 -0
  164. package/src/{transform → compute}/texture-transform.ts +6 -16
  165. package/src/debug/debug-framebuffer.ts +1 -1
  166. package/src/debug/debug-shader-layout.ts +1 -1
  167. package/src/index.ts +35 -16
  168. package/src/model/model.ts +116 -66
  169. package/src/model/split-uniforms-and-bindings.ts +4 -4
  170. package/src/models/billboard-texture-model.ts +98 -0
  171. package/src/models/billboard-texture-module.ts +49 -0
  172. package/src/models/clip-space.ts +88 -0
  173. package/src/modules/picking/README.md +88 -0
  174. package/src/modules/picking/color-picking.ts +190 -0
  175. package/src/modules/picking/index-picking.ts +156 -0
  176. package/src/modules/picking/legacy-picking-manager.ts +99 -0
  177. package/src/modules/picking/picking-manager.ts +137 -0
  178. package/src/modules/picking/picking-uniforms.ts +179 -0
  179. package/src/passes/get-fragment-shader.ts +129 -0
  180. package/src/passes/shader-pass-renderer.ts +252 -0
  181. package/src/shader-inputs.ts +27 -48
  182. package/dist/computation.d.ts.map +0 -1
  183. package/dist/lib/clip-space.d.ts.map +0 -1
  184. package/dist/lib/clip-space.js +0 -46
  185. package/dist/lib/pipeline-factory.d.ts.map +0 -1
  186. package/dist/lib/shader-factory.d.ts.map +0 -1
  187. package/dist/transform/buffer-transform.d.ts +0 -35
  188. package/dist/transform/buffer-transform.d.ts.map +0 -1
  189. package/dist/transform/texture-transform.d.ts.map +0 -1
  190. package/src/lib/clip-space.ts +0 -53
  191. /package/dist/{lib → factories}/pipeline-factory.d.ts +0 -0
  192. /package/dist/{lib → factories}/shader-factory.d.ts +0 -0
  193. /package/src/{lib → factories}/pipeline-factory.ts +0 -0
  194. /package/src/{lib → factories}/shader-factory.ts +0 -0
package/dist/index.cjs CHANGED
@@ -28,6 +28,7 @@ __export(dist_exports, {
28
28
  AnimationLoop: () => AnimationLoop,
29
29
  AnimationLoopTemplate: () => AnimationLoopTemplate,
30
30
  AsyncTexture: () => AsyncTexture,
31
+ BackgroundTextureModel: () => BackgroundTextureModel,
31
32
  BufferTransform: () => BufferTransform,
32
33
  ClipSpace: () => ClipSpace,
33
34
  Computation: () => Computation,
@@ -39,23 +40,31 @@ __export(dist_exports, {
39
40
  GroupNode: () => GroupNode,
40
41
  IcoSphereGeometry: () => IcoSphereGeometry,
41
42
  KeyFrames: () => KeyFrames,
43
+ LegacyPickingManager: () => LegacyPickingManager,
42
44
  Model: () => Model,
43
45
  ModelNode: () => ModelNode,
46
+ PickingManager: () => PickingManager,
44
47
  PipelineFactory: () => PipelineFactory,
45
48
  PlaneGeometry: () => PlaneGeometry,
46
49
  ScenegraphNode: () => ScenegraphNode,
47
50
  ShaderFactory: () => ShaderFactory,
51
+ ShaderInputs: () => ShaderInputs,
52
+ ShaderPassRenderer: () => ShaderPassRenderer,
48
53
  SphereGeometry: () => SphereGeometry,
54
+ Swap: () => Swap,
55
+ SwapBuffers: () => SwapBuffers,
56
+ SwapFramebuffers: () => SwapFramebuffers,
49
57
  TextureTransform: () => TextureTransform,
50
58
  Timeline: () => Timeline,
51
59
  TruncatedConeGeometry: () => TruncatedConeGeometry,
52
- _ShaderInputs: () => ShaderInputs,
53
- cancelAnimationFrame: () => cancelAnimationFrame,
60
+ cancelAnimationFramePolyfill: () => cancelAnimationFramePolyfill,
61
+ colorPicking: () => picking2,
62
+ indexPicking: () => picking,
54
63
  loadImage: () => loadImage,
55
64
  loadImageBitmap: () => loadImageBitmap,
56
65
  makeAnimationLoop: () => makeAnimationLoop,
57
66
  makeRandomGenerator: () => makeRandomGenerator,
58
- requestAnimationFrame: () => requestAnimationFrame,
67
+ requestAnimationFramePolyfill: () => requestAnimationFramePolyfill,
59
68
  setPathPrefix: () => setPathPrefix
60
69
  });
61
70
  module.exports = __toCommonJS(dist_exports);
@@ -235,10 +244,10 @@ var AnimationLoopTemplate = class {
235
244
  var import_core = require("@luma.gl/core");
236
245
 
237
246
  // dist/animation-loop/request-animation-frame.js
238
- function requestAnimationFrame(callback) {
247
+ function requestAnimationFramePolyfill(callback) {
239
248
  return typeof window !== "undefined" && window.requestAnimationFrame ? window.requestAnimationFrame(callback) : setTimeout(callback, 1e3 / 60);
240
249
  }
241
- function cancelAnimationFrame(timerId) {
250
+ function cancelAnimationFramePolyfill(timerId) {
242
251
  return typeof window !== "undefined" && window.cancelAnimationFrame ? window.cancelAnimationFrame(timerId) : clearTimeout(timerId);
243
252
  }
244
253
 
@@ -281,6 +290,7 @@ var AnimationLoop = class {
281
290
  _nextFramePromise = null;
282
291
  _resolveNextFrame = null;
283
292
  _cpuStartTime = 0;
293
+ _error = null;
284
294
  // _gpuTimeQuery: Query | null = null;
285
295
  /*
286
296
  * @param {HTMLCanvasElement} canvas - if provided, width and height will be passed to context
@@ -314,6 +324,22 @@ var AnimationLoop = class {
314
324
  delete() {
315
325
  this.destroy();
316
326
  }
327
+ setError(error) {
328
+ var _a, _b;
329
+ this.props.onError(error);
330
+ this._error = Error();
331
+ const canvas2 = (_b = (_a = this.device) == null ? void 0 : _a.canvasContext) == null ? void 0 : _b.canvas;
332
+ if (canvas2 instanceof HTMLCanvasElement) {
333
+ const errorDiv = document.createElement("h1");
334
+ errorDiv.innerHTML = error.message;
335
+ errorDiv.style.position = "absolute";
336
+ errorDiv.style.top = "20%";
337
+ errorDiv.style.left = "10px";
338
+ errorDiv.style.color = "black";
339
+ errorDiv.style.backgroundColor = "red";
340
+ document.body.appendChild(errorDiv);
341
+ }
342
+ }
317
343
  /** Flags this animation loop as needing redraw */
318
344
  setNeedsRedraw(reason) {
319
345
  this.needsRedraw = this.needsRedraw || reason;
@@ -363,7 +389,7 @@ var AnimationLoop = class {
363
389
  /** Stops a render loop if already running, finalizing */
364
390
  stop() {
365
391
  if (this._running) {
366
- if (this.animationProps) {
392
+ if (this.animationProps && !this._error) {
367
393
  this.props.onFinalize(this.animationProps);
368
394
  }
369
395
  this._cancelAnimationFrame();
@@ -376,7 +402,7 @@ var AnimationLoop = class {
376
402
  /** Explicitly draw a frame */
377
403
  redraw() {
378
404
  var _a;
379
- if ((_a = this.device) == null ? void 0 : _a.isLost) {
405
+ if (((_a = this.device) == null ? void 0 : _a.isLost) || this._error) {
380
406
  return this;
381
407
  }
382
408
  this._beginFrameTimers();
@@ -442,13 +468,13 @@ var AnimationLoop = class {
442
468
  if (!this._running) {
443
469
  return;
444
470
  }
445
- this._animationFrameId = requestAnimationFrame(this._animationFrame.bind(this));
471
+ this._animationFrameId = requestAnimationFramePolyfill(this._animationFrame.bind(this));
446
472
  }
447
473
  _cancelAnimationFrame() {
448
474
  if (this._animationFrameId === null) {
449
475
  return;
450
476
  }
451
- cancelAnimationFrame(this._animationFrameId);
477
+ cancelAnimationFramePolyfill(this._animationFrameId);
452
478
  this._animationFrameId = null;
453
479
  }
454
480
  _animationFrame() {
@@ -633,7 +659,7 @@ var AnimationLoop = class {
633
659
  var import_core2 = require("@luma.gl/core");
634
660
  function makeAnimationLoop(AnimationLoopTemplateCtor, props) {
635
661
  let renderLoop = null;
636
- const device = (props == null ? void 0 : props.device) || import_core2.luma.createDevice({ id: "animation-loop" });
662
+ const device = (props == null ? void 0 : props.device) || import_core2.luma.createDevice({ id: "animation-loop", adapters: props == null ? void 0 : props.adapters, createCanvasContext: true });
637
663
  const animationLoop = new AnimationLoop({
638
664
  ...props,
639
665
  device,
@@ -652,9 +678,6 @@ function makeAnimationLoop(AnimationLoopTemplateCtor, props) {
652
678
 
653
679
  // dist/model/model.js
654
680
  var import_core7 = require("@luma.gl/core");
655
- var import_core8 = require("@luma.gl/core");
656
- var import_core9 = require("@luma.gl/core");
657
- var import_core10 = require("@luma.gl/core");
658
681
  var import_shadertools2 = require("@luma.gl/shadertools");
659
682
 
660
683
  // dist/geometry/gpu-geometry.js
@@ -765,7 +788,7 @@ function getAttributeBuffersFromGeometry(device, geometry) {
765
788
  return { attributes, bufferLayout, vertexCount };
766
789
  }
767
790
 
768
- // dist/lib/pipeline-factory.js
791
+ // dist/factories/pipeline-factory.js
769
792
  var import_core4 = require("@luma.gl/core");
770
793
  var _PipelineFactory = class {
771
794
  /** Get the singleton default pipeline factory for the specified device */
@@ -852,7 +875,7 @@ var _PipelineFactory = class {
852
875
  var PipelineFactory = _PipelineFactory;
853
876
  __publicField(PipelineFactory, "defaultProps", { ...import_core4.RenderPipeline.defaultProps });
854
877
 
855
- // dist/lib/shader-factory.js
878
+ // dist/factories/shader-factory.js
856
879
  var import_core5 = require("@luma.gl/core");
857
880
  var _ShaderFactory = class {
858
881
  /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
@@ -920,7 +943,7 @@ function getDebugTableForShaderLayout(layout, name) {
920
943
  }
921
944
  for (const varyingDeclaration of layout.varyings || []) {
922
945
  const glslDeclaration = `${varyingDeclaration.location} ${varyingDeclaration.name}`;
923
- table[`out ${glslDeclaration}`] = { [header]: JSON.stringify(varyingDeclaration.accessor) };
946
+ table[`out ${glslDeclaration}`] = { [header]: JSON.stringify(varyingDeclaration) };
924
947
  }
925
948
  return table;
926
949
  }
@@ -937,7 +960,7 @@ function debugFramebuffer(fbo, { id, minimap, opaque, top = "0", left = "0", rgb
937
960
  canvas.style.position = "absolute";
938
961
  canvas.style.top = top;
939
962
  canvas.style.left = left;
940
- canvas.style.border = "blue 1px solid";
963
+ canvas.style.border = "blue 5px solid";
941
964
  canvas.style.transform = "scaleY(-1)";
942
965
  document.body.appendChild(canvas);
943
966
  ctx = canvas.getContext("2d");
@@ -1003,10 +1026,14 @@ function deepEqual(a, b, depth) {
1003
1026
  return false;
1004
1027
  }
1005
1028
 
1029
+ // dist/shader-inputs.js
1030
+ var import_core6 = require("@luma.gl/core");
1031
+ var import_shadertools = require("@luma.gl/shadertools");
1032
+
1006
1033
  // dist/model/split-uniforms-and-bindings.js
1007
1034
  var import_types = require("@math.gl/types");
1008
1035
  function isUniformValue(value) {
1009
- return (0, import_types.isNumericArray)(value) !== null || typeof value === "number" || typeof value === "boolean";
1036
+ return (0, import_types.isNumericArray)(value) || typeof value === "number" || typeof value === "boolean";
1010
1037
  }
1011
1038
  function splitUniformsAndBindings(uniforms) {
1012
1039
  const result = { bindings: {}, uniforms: {} };
@@ -1022,8 +1049,6 @@ function splitUniformsAndBindings(uniforms) {
1022
1049
  }
1023
1050
 
1024
1051
  // dist/shader-inputs.js
1025
- var import_core6 = require("@luma.gl/core");
1026
- var import_shadertools = require("@luma.gl/shadertools");
1027
1052
  var ShaderInputs = class {
1028
1053
  /**
1029
1054
  * The map of modules
@@ -1052,9 +1077,10 @@ var ShaderInputs = class {
1052
1077
  this.moduleUniforms = {};
1053
1078
  this.moduleBindings = {};
1054
1079
  for (const [name, module2] of Object.entries(modules)) {
1055
- const moduleName = name;
1056
- this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
1057
- this.moduleBindings[moduleName] = {};
1080
+ this._addModule(module2);
1081
+ if (module2.name && name !== module2.name) {
1082
+ import_core6.log.warn(`Module name: ${name} vs ${module2.name}`)();
1083
+ }
1058
1084
  }
1059
1085
  }
1060
1086
  /** Destroy */
@@ -1075,17 +1101,12 @@ var ShaderInputs = class {
1075
1101
  }
1076
1102
  const oldUniforms = this.moduleUniforms[moduleName];
1077
1103
  const oldBindings = this.moduleBindings[moduleName];
1078
- let uniformsAndBindings = (_a = module2.getUniforms) == null ? void 0 : _a.call(module2, moduleProps, this.moduleUniforms[moduleName]);
1079
- uniformsAndBindings ||= { ...this.moduleUniforms[moduleName], ...moduleProps };
1104
+ const uniformsAndBindings = ((_a = module2.getUniforms) == null ? void 0 : _a.call(module2, moduleProps, oldUniforms)) || moduleProps;
1080
1105
  const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings);
1081
1106
  this.moduleUniforms[moduleName] = { ...oldUniforms, ...uniforms };
1082
1107
  this.moduleBindings[moduleName] = { ...oldBindings, ...bindings };
1083
1108
  }
1084
1109
  }
1085
- /** Merges all bindings for the shader (from the various modules) */
1086
- // getUniformBlocks(): Record<string, Texture | Sampler> {
1087
- // return this.moduleUniforms;
1088
- // }
1089
1110
  /**
1090
1111
  * Return the map of modules
1091
1112
  * @todo should should this include the resolved dependencies?
@@ -1098,13 +1119,15 @@ var ShaderInputs = class {
1098
1119
  return this.moduleUniforms;
1099
1120
  }
1100
1121
  /** Merges all bindings for the shader (from the various modules) */
1101
- getBindings() {
1122
+ getBindingValues() {
1102
1123
  const bindings = {};
1103
1124
  for (const moduleBindings of Object.values(this.moduleBindings)) {
1104
1125
  Object.assign(bindings, moduleBindings);
1105
1126
  }
1106
1127
  return bindings;
1107
1128
  }
1129
+ // INTERNAL
1130
+ /** Return a debug table that can be used for console.table() or log.table() */
1108
1131
  getDebugTable() {
1109
1132
  var _a;
1110
1133
  const table = {};
@@ -1118,6 +1141,11 @@ var ShaderInputs = class {
1118
1141
  }
1119
1142
  return table;
1120
1143
  }
1144
+ _addModule(module2) {
1145
+ const moduleName = module2.name;
1146
+ this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
1147
+ this.moduleBindings[moduleName] = {};
1148
+ }
1121
1149
  };
1122
1150
 
1123
1151
  // dist/application-utils/load-file.js
@@ -1130,7 +1158,7 @@ async function loadImageBitmap(url, opts) {
1130
1158
  image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
1131
1159
  image.src = url.startsWith("http") ? url : pathPrefix + url;
1132
1160
  await image.decode();
1133
- return await createImageBitmap(image);
1161
+ return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
1134
1162
  }
1135
1163
  async function loadImage(url, opts) {
1136
1164
  return await new Promise((resolve, reject) => {
@@ -1149,6 +1177,7 @@ async function loadImage(url, opts) {
1149
1177
  // dist/async-texture/async-texture.js
1150
1178
  var AsyncTexture = class {
1151
1179
  device;
1180
+ id;
1152
1181
  // TODO - should we type these as possibly `null`? It will make usage harder?
1153
1182
  // @ts-expect-error
1154
1183
  texture;
@@ -1163,8 +1192,15 @@ var AsyncTexture = class {
1163
1192
  };
1164
1193
  rejectReady = () => {
1165
1194
  };
1195
+ get [Symbol.toStringTag]() {
1196
+ return "AsyncTexture";
1197
+ }
1198
+ toString() {
1199
+ return `AsyncTexture:"${this.id}"(${this.isReady ? "ready" : "loading"})`;
1200
+ }
1166
1201
  constructor(device, props) {
1167
1202
  this.device = device;
1203
+ this.id = props.id || uid("async-texture");
1168
1204
  if (typeof (props == null ? void 0 : props.data) === "string" && props.dimension === "2d") {
1169
1205
  props = { ...props, data: loadImageBitmap(props.data) };
1170
1206
  }
@@ -1198,6 +1234,26 @@ var AsyncTexture = class {
1198
1234
  }
1199
1235
  this.destroyed = true;
1200
1236
  }
1237
+ /**
1238
+ * Textures are immutable and cannot be resized after creation,
1239
+ * but we can create a similar texture with the same parameters but a new size.
1240
+ * @note Does not copy contents of the texture
1241
+ * @todo Abort pending promise and create a texture with the new size?
1242
+ */
1243
+ resize(size) {
1244
+ if (!this.isReady) {
1245
+ throw new Error("Cannot resize texture before it is ready");
1246
+ }
1247
+ if (size.width === this.texture.width && size.height === this.texture.height) {
1248
+ return false;
1249
+ }
1250
+ if (this.texture) {
1251
+ const texture = this.texture;
1252
+ this.texture = texture.clone(size);
1253
+ texture.destroy();
1254
+ }
1255
+ return true;
1256
+ }
1201
1257
  };
1202
1258
  async function awaitAllPromises(x) {
1203
1259
  x = await x;
@@ -1280,6 +1336,12 @@ var _Model = class {
1280
1336
  _destroyed = false;
1281
1337
  /** "Time" of last draw. Monotonically increasing timestamp */
1282
1338
  _lastDrawTimestamp = -1;
1339
+ get [Symbol.toStringTag]() {
1340
+ return "Model";
1341
+ }
1342
+ toString() {
1343
+ return `Model(${this.id})`;
1344
+ }
1283
1345
  constructor(device, props) {
1284
1346
  var _a, _b, _c;
1285
1347
  this.props = { ..._Model.defaultProps, ...props };
@@ -1297,22 +1359,22 @@ var _Model = class {
1297
1359
  const isWebGPU = this.device.type === "webgpu";
1298
1360
  if (isWebGPU && this.props.source) {
1299
1361
  this.props.shaderLayout ||= (0, import_shadertools2.getShaderLayoutFromWGSL)(this.props.source);
1300
- const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
1362
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
1301
1363
  platformInfo,
1302
1364
  ...this.props,
1303
1365
  modules
1304
1366
  });
1305
- this.source = source;
1306
- this._getModuleUniforms = getUniforms;
1367
+ this.source = source3;
1368
+ this._getModuleUniforms = getUniforms2;
1307
1369
  } else {
1308
- const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleGLSLShaderPair({
1370
+ const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
1309
1371
  platformInfo,
1310
1372
  ...this.props,
1311
1373
  modules
1312
1374
  });
1313
- this.vs = vs;
1314
- this.fs = fs;
1315
- this._getModuleUniforms = getUniforms;
1375
+ this.vs = vs3;
1376
+ this.fs = fs3;
1377
+ this._getModuleUniforms = getUniforms2;
1316
1378
  }
1317
1379
  this.vertexCount = this.props.vertexCount;
1318
1380
  this.instanceCount = this.props.instanceCount;
@@ -1353,10 +1415,10 @@ var _Model = class {
1353
1415
  this.setBindings(props.bindings);
1354
1416
  }
1355
1417
  if (props.uniforms) {
1356
- this.setUniforms(props.uniforms);
1418
+ this.setUniformsWebGL(props.uniforms);
1357
1419
  }
1358
1420
  if (props.moduleSettings) {
1359
- this.updateModuleSettings(props.moduleSettings);
1421
+ this.updateModuleSettingsWebGL(props.moduleSettings);
1360
1422
  }
1361
1423
  if (props.transformFeedback) {
1362
1424
  this.transformFeedback = props.transformFeedback;
@@ -1395,9 +1457,20 @@ var _Model = class {
1395
1457
  this.pipeline = this._updatePipeline();
1396
1458
  }
1397
1459
  draw(renderPass) {
1398
- this.predraw();
1460
+ const loadingBinding = this._areBindingsLoading();
1461
+ if (loadingBinding) {
1462
+ import_core7.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1463
+ return false;
1464
+ }
1465
+ try {
1466
+ renderPass.pushDebugGroup(`${this}.predraw(${renderPass})`);
1467
+ this.predraw();
1468
+ } finally {
1469
+ renderPass.popDebugGroup();
1470
+ }
1399
1471
  let drawSuccess;
1400
1472
  try {
1473
+ renderPass.pushDebugGroup(`${this}.draw(${renderPass})`);
1401
1474
  this._logDrawCallStart();
1402
1475
  this.pipeline = this._updatePipeline();
1403
1476
  const syncBindings = this._getBindings();
@@ -1424,6 +1497,7 @@ var _Model = class {
1424
1497
  topology: this.topology
1425
1498
  });
1426
1499
  } finally {
1500
+ renderPass.popDebugGroup();
1427
1501
  this._logDrawCallEnd();
1428
1502
  }
1429
1503
  this._logFramebuffer(renderPass);
@@ -1447,7 +1521,8 @@ var _Model = class {
1447
1521
  const gpuGeometry = geometry && makeGPUGeometry(this.device, geometry);
1448
1522
  if (gpuGeometry) {
1449
1523
  this.setTopology(gpuGeometry.topology || "triangle-list");
1450
- this.bufferLayout = mergeBufferLayouts(gpuGeometry.bufferLayout, this.bufferLayout);
1524
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1525
+ this.bufferLayout = bufferLayoutHelper.mergeBufferLayouts(gpuGeometry.bufferLayout, this.bufferLayout);
1451
1526
  if (this.vertexArray) {
1452
1527
  this._setGeometryAttributes(gpuGeometry);
1453
1528
  }
@@ -1469,7 +1544,8 @@ var _Model = class {
1469
1544
  * @note Triggers a pipeline rebuild / pipeline cache fetch
1470
1545
  */
1471
1546
  setBufferLayout(bufferLayout) {
1472
- this.bufferLayout = this._gpuGeometry ? mergeBufferLayouts(bufferLayout, this._gpuGeometry.bufferLayout) : bufferLayout;
1547
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1548
+ this.bufferLayout = this._gpuGeometry ? bufferLayoutHelper.mergeBufferLayouts(bufferLayout, this._gpuGeometry.bufferLayout) : bufferLayout;
1473
1549
  this._setPipelineNeedsUpdate("bufferLayout");
1474
1550
  this.pipeline = this._updatePipeline();
1475
1551
  this.vertexArray = this.device.createVertexArray({
@@ -1513,17 +1589,19 @@ var _Model = class {
1513
1589
  /** Set the shader inputs */
1514
1590
  setShaderInputs(shaderInputs) {
1515
1591
  this.shaderInputs = shaderInputs;
1516
- this._uniformStore = new import_core8.UniformStore(this.shaderInputs.modules);
1517
- for (const moduleName of Object.keys(this.shaderInputs.modules)) {
1518
- const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
1519
- this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
1592
+ this._uniformStore = new import_core7.UniformStore(this.shaderInputs.modules);
1593
+ for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
1594
+ if (shaderModuleHasUniforms(module2)) {
1595
+ const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
1596
+ this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
1597
+ }
1520
1598
  }
1521
1599
  this.setNeedsRedraw("shaderInputs");
1522
1600
  }
1523
1601
  /** Update uniform buffers from the model's shader inputs */
1524
1602
  updateShaderInputs() {
1525
1603
  this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
1526
- this.setBindings(this.shaderInputs.getBindings());
1604
+ this.setBindings(this.shaderInputs.getBindingValues());
1527
1605
  this.setNeedsRedraw("shaderInputs");
1528
1606
  }
1529
1607
  /**
@@ -1553,16 +1631,20 @@ var _Model = class {
1553
1631
  * @note Overrides any attributes previously set with the same name
1554
1632
  */
1555
1633
  setAttributes(buffers, options) {
1634
+ const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
1556
1635
  if (buffers.indices) {
1557
- import_core9.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
1636
+ import_core7.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
1558
1637
  }
1638
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1559
1639
  for (const [bufferName, buffer] of Object.entries(buffers)) {
1560
- const bufferLayout = this.bufferLayout.find((layout) => getAttributeNames(layout).includes(bufferName));
1640
+ const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
1561
1641
  if (!bufferLayout) {
1562
- import_core9.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
1642
+ if (!disableWarnings) {
1643
+ import_core7.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
1644
+ }
1563
1645
  continue;
1564
1646
  }
1565
- const attributeNames = getAttributeNames(bufferLayout);
1647
+ const attributeNames = bufferLayoutHelper.getAttributeNamesForBuffer(bufferLayout);
1566
1648
  let set = false;
1567
1649
  for (const attributeName of attributeNames) {
1568
1650
  const attributeInfo = this._attributeInfos[attributeName];
@@ -1571,8 +1653,8 @@ var _Model = class {
1571
1653
  set = true;
1572
1654
  }
1573
1655
  }
1574
- if (!set && !((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
1575
- import_core9.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
1656
+ if (!set && !disableWarnings) {
1657
+ import_core7.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
1576
1658
  }
1577
1659
  }
1578
1660
  this.setNeedsRedraw("attributes");
@@ -1591,7 +1673,7 @@ var _Model = class {
1591
1673
  if (attributeInfo) {
1592
1674
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
1593
1675
  } else if (!((options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings)) {
1594
- import_core9.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
1676
+ import_core7.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
1595
1677
  }
1596
1678
  }
1597
1679
  this.setNeedsRedraw("constants");
@@ -1602,7 +1684,7 @@ var _Model = class {
1602
1684
  * @deprecated WebGL only, use uniform buffers for portability
1603
1685
  * @param uniforms
1604
1686
  */
1605
- setUniforms(uniforms) {
1687
+ setUniformsWebGL(uniforms) {
1606
1688
  if (!isObjectEmpty(uniforms)) {
1607
1689
  this.pipeline.setUniformsWebGL(uniforms);
1608
1690
  Object.assign(this.uniforms, uniforms);
@@ -1612,25 +1694,35 @@ var _Model = class {
1612
1694
  /**
1613
1695
  * @deprecated Updates shader module settings (which results in uniforms being set)
1614
1696
  */
1615
- updateModuleSettings(props) {
1697
+ updateModuleSettingsWebGL(props) {
1616
1698
  const { bindings, uniforms } = splitUniformsAndBindings(this._getModuleUniforms(props));
1617
1699
  Object.assign(this.bindings, bindings);
1618
1700
  Object.assign(this.uniforms, uniforms);
1619
1701
  this.setNeedsRedraw("moduleSettings");
1620
1702
  }
1621
1703
  // Internal methods
1622
- /** Get texture / texture view from any async textures */
1704
+ /** Check that bindings are loaded. Returns id of first binding that is still loading. */
1705
+ _areBindingsLoading() {
1706
+ for (const binding of Object.values(this.bindings)) {
1707
+ if (binding instanceof AsyncTexture && !binding.isReady) {
1708
+ return binding.id;
1709
+ }
1710
+ }
1711
+ return false;
1712
+ }
1713
+ /** Extracts texture view from loaded async textures. Returns null if any textures have not yet been loaded. */
1623
1714
  _getBindings() {
1624
- return Object.entries(this.bindings).reduce((acc, [name, binding]) => {
1715
+ const validBindings = {};
1716
+ for (const [name, binding] of Object.entries(this.bindings)) {
1625
1717
  if (binding instanceof AsyncTexture) {
1626
1718
  if (binding.isReady) {
1627
- acc[name] = binding.texture;
1719
+ validBindings[name] = binding.texture;
1628
1720
  }
1629
1721
  } else {
1630
- acc[name] = binding;
1722
+ validBindings[name] = binding;
1631
1723
  }
1632
- return acc;
1633
- }, {});
1724
+ }
1725
+ return validBindings;
1634
1726
  }
1635
1727
  /** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
1636
1728
  _getBindingsUpdateTimestamp() {
@@ -1680,26 +1772,26 @@ var _Model = class {
1680
1772
  let prevShaderVs = null;
1681
1773
  let prevShaderFs = null;
1682
1774
  if (this.pipeline) {
1683
- import_core9.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1775
+ import_core7.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1684
1776
  prevShaderVs = this.pipeline.vs;
1685
1777
  prevShaderFs = this.pipeline.fs;
1686
1778
  }
1687
1779
  this._pipelineNeedsUpdate = false;
1688
- const vs = this.shaderFactory.createShader({
1780
+ const vs3 = this.shaderFactory.createShader({
1689
1781
  id: `${this.id}-vertex`,
1690
1782
  stage: "vertex",
1691
1783
  source: this.source || this.vs,
1692
- debug: this.props.debugShaders
1784
+ debugShaders: this.props.debugShaders
1693
1785
  });
1694
- let fs = null;
1786
+ let fs3 = null;
1695
1787
  if (this.source) {
1696
- fs = vs;
1788
+ fs3 = vs3;
1697
1789
  } else if (this.fs) {
1698
- fs = this.shaderFactory.createShader({
1790
+ fs3 = this.shaderFactory.createShader({
1699
1791
  id: `${this.id}-fragment`,
1700
1792
  stage: "fragment",
1701
1793
  source: this.source || this.fs,
1702
- debug: this.props.debugShaders
1794
+ debugShaders: this.props.debugShaders
1703
1795
  });
1704
1796
  }
1705
1797
  this.pipeline = this.pipelineFactory.createRenderPipeline({
@@ -1710,10 +1802,10 @@ var _Model = class {
1710
1802
  // TODO - why set bindings here when we reset them every frame?
1711
1803
  // Should we expose a BindGroup abstraction?
1712
1804
  bindings: this._getBindings(),
1713
- vs,
1714
- fs
1805
+ vs: vs3,
1806
+ fs: fs3
1715
1807
  });
1716
- this._attributeInfos = (0, import_core10.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
1808
+ this._attributeInfos = (0, import_core7.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
1717
1809
  if (prevShaderVs)
1718
1810
  this.shaderFactory.release(prevShaderVs);
1719
1811
  if (prevShaderFs)
@@ -1725,35 +1817,35 @@ var _Model = class {
1725
1817
  _lastLogTime = 0;
1726
1818
  _logOpen = false;
1727
1819
  _logDrawCallStart() {
1728
- const logDrawTimeout = import_core9.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
1729
- if (import_core9.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
1820
+ const logDrawTimeout = import_core7.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
1821
+ if (import_core7.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
1730
1822
  return;
1731
1823
  }
1732
1824
  this._lastLogTime = Date.now();
1733
1825
  this._logOpen = true;
1734
- import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
1826
+ import_core7.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core7.log.level <= 2 })();
1735
1827
  }
1736
1828
  _logDrawCallEnd() {
1737
1829
  if (this._logOpen) {
1738
1830
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
1739
- import_core9.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
1831
+ import_core7.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
1740
1832
  const uniformTable = this.shaderInputs.getDebugTable();
1741
1833
  for (const [name, value] of Object.entries(this.uniforms)) {
1742
1834
  uniformTable[name] = { value };
1743
1835
  }
1744
- import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1836
+ import_core7.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1745
1837
  const attributeTable = this._getAttributeDebugTable();
1746
- import_core9.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
1747
- import_core9.log.table(LOG_DRAW_PRIORITY, attributeTable)();
1748
- import_core9.log.groupEnd(LOG_DRAW_PRIORITY)();
1838
+ import_core7.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
1839
+ import_core7.log.table(LOG_DRAW_PRIORITY, attributeTable)();
1840
+ import_core7.log.groupEnd(LOG_DRAW_PRIORITY)();
1749
1841
  this._logOpen = false;
1750
1842
  }
1751
1843
  }
1752
1844
  _drawCount = 0;
1753
1845
  _logFramebuffer(renderPass) {
1754
- const debugFramebuffers = import_core9.log.get("framebuffer");
1846
+ const debugFramebuffers = this.device.props.debugFramebuffers;
1755
1847
  this._drawCount++;
1756
- if (!debugFramebuffers || this._drawCount++ > 3 && this._drawCount % 60) {
1848
+ if (!debugFramebuffers) {
1757
1849
  return;
1758
1850
  }
1759
1851
  const framebuffer = renderPass.props.framebuffer;
@@ -1784,14 +1876,14 @@ var _Model = class {
1784
1876
  }
1785
1877
  // TODO - fix typing of luma data types
1786
1878
  _getBufferOrConstantValues(attribute, dataType) {
1787
- const TypedArrayConstructor = (0, import_core10.getTypedArrayFromDataType)(dataType);
1879
+ const TypedArrayConstructor = (0, import_core7.getTypedArrayFromDataType)(dataType);
1788
1880
  const typedArray = attribute instanceof import_core7.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
1789
1881
  return typedArray.toString();
1790
1882
  }
1791
1883
  };
1792
1884
  var Model = _Model;
1793
1885
  __publicField(Model, "defaultProps", {
1794
- ...import_core8.RenderPipeline.defaultProps,
1886
+ ...import_core7.RenderPipeline.defaultProps,
1795
1887
  source: void 0,
1796
1888
  vs: null,
1797
1889
  fs: null,
@@ -1817,17 +1909,8 @@ __publicField(Model, "defaultProps", {
1817
1909
  debugShaders: void 0,
1818
1910
  disableWarnings: void 0
1819
1911
  });
1820
- function mergeBufferLayouts(layouts1, layouts2) {
1821
- const layouts = [...layouts1];
1822
- for (const attribute of layouts2) {
1823
- const index = layouts.findIndex((attribute2) => attribute2.name === attribute.name);
1824
- if (index < 0) {
1825
- layouts.push(attribute);
1826
- } else {
1827
- layouts[index] = attribute;
1828
- }
1829
- }
1830
- return layouts;
1912
+ function shaderModuleHasUniforms(module2) {
1913
+ return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
1831
1914
  }
1832
1915
  function getPlatformInfo(device) {
1833
1916
  return {
@@ -1839,33 +1922,26 @@ function getPlatformInfo(device) {
1839
1922
  features: device.features
1840
1923
  };
1841
1924
  }
1842
- function getAttributeNames(bufferLayout) {
1843
- var _a;
1844
- return bufferLayout.attributes ? (_a = bufferLayout.attributes) == null ? void 0 : _a.map((layout) => layout.attribute) : [bufferLayout.name];
1845
- }
1846
1925
  function isObjectEmpty(obj) {
1847
- let isEmpty = true;
1848
1926
  for (const key in obj) {
1849
- isEmpty = false;
1850
- break;
1927
+ return false;
1851
1928
  }
1852
- return isEmpty;
1929
+ return true;
1853
1930
  }
1854
1931
 
1855
- // dist/transform/buffer-transform.js
1856
- var import_core11 = require("@luma.gl/core");
1932
+ // dist/compute/buffer-transform.js
1933
+ var import_core8 = require("@luma.gl/core");
1857
1934
  var import_shadertools3 = require("@luma.gl/shadertools");
1858
- var BufferTransform = class {
1935
+ var _BufferTransform = class {
1859
1936
  device;
1860
1937
  model;
1861
1938
  transformFeedback;
1862
- /** @deprecated Use device feature test. */
1863
1939
  static isSupported(device) {
1864
1940
  var _a;
1865
1941
  return ((_a = device == null ? void 0 : device.info) == null ? void 0 : _a.type) === "webgl";
1866
1942
  }
1867
- constructor(device, props = Model.defaultProps) {
1868
- if (!BufferTransform.isSupported(device)) {
1943
+ constructor(device, props = _BufferTransform.defaultProps) {
1944
+ if (!_BufferTransform.isSupported(device)) {
1869
1945
  throw new Error("BufferTransform not yet implemented on WebGPU");
1870
1946
  }
1871
1947
  this.device = device;
@@ -1873,6 +1949,7 @@ var BufferTransform = class {
1873
1949
  id: props.id || "buffer-transform-model",
1874
1950
  fs: props.fs || (0, import_shadertools3.getPassthroughFS)(),
1875
1951
  topology: props.topology || "point-list",
1952
+ varyings: props.outputs || props.varyings,
1876
1953
  ...props
1877
1954
  });
1878
1955
  this.transformFeedback = this.device.createTransformFeedback({
@@ -1895,32 +1972,42 @@ var BufferTransform = class {
1895
1972
  }
1896
1973
  /** Run one transform loop. */
1897
1974
  run(options) {
1975
+ if (options == null ? void 0 : options.inputBuffers) {
1976
+ this.model.setAttributes(options.inputBuffers);
1977
+ }
1978
+ if (options == null ? void 0 : options.outputBuffers) {
1979
+ this.transformFeedback.setBuffers(options.outputBuffers);
1980
+ }
1898
1981
  const renderPass = this.device.beginRenderPass(options);
1899
1982
  this.model.draw(renderPass);
1900
1983
  renderPass.end();
1901
1984
  }
1902
- /** @deprecated */
1903
- update(...args) {
1904
- console.warn("TextureTransform#update() not implemented");
1905
- }
1906
- /** Returns the {@link Buffer} or {@link BufferRange} for given varying name. */
1985
+ // DEPRECATED METHODS
1986
+ /** @deprecated App knows what buffers it is passing in - Returns the {@link Buffer} or {@link BufferRange} for given varying name. */
1907
1987
  getBuffer(varyingName) {
1908
1988
  return this.transformFeedback.getBuffer(varyingName);
1909
1989
  }
1990
+ /** @deprecated App knows what buffers it is passing in - Reads the {@link Buffer} or {@link BufferRange} for given varying name. */
1910
1991
  readAsync(varyingName) {
1911
1992
  const result = this.getBuffer(varyingName);
1912
1993
  if (!result) {
1913
1994
  throw new Error("BufferTransform#getBuffer");
1914
1995
  }
1915
- if (result instanceof import_core11.Buffer) {
1996
+ if (result instanceof import_core8.Buffer) {
1916
1997
  return result.readAsync();
1917
1998
  }
1918
1999
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
1919
2000
  return buffer.readAsync(byteOffset, byteLength);
1920
2001
  }
1921
2002
  };
2003
+ var BufferTransform = _BufferTransform;
2004
+ __publicField(BufferTransform, "defaultProps", {
2005
+ ...Model.defaultProps,
2006
+ outputs: void 0,
2007
+ feedbackBuffers: void 0
2008
+ });
1922
2009
 
1923
- // dist/transform/texture-transform.js
2010
+ // dist/compute/texture-transform.js
1924
2011
  var import_shadertools4 = require("@luma.gl/shadertools");
1925
2012
  var FS_OUTPUT_VARIABLE = "transform_output";
1926
2013
  var TextureTransform = class {
@@ -1958,6 +2045,11 @@ var TextureTransform = class {
1958
2045
  }
1959
2046
  // Delete owned resources.
1960
2047
  destroy() {
2048
+ var _a;
2049
+ this.model.destroy();
2050
+ for (const binding of this.bindings) {
2051
+ (_a = binding.framebuffer) == null ? void 0 : _a.destroy();
2052
+ }
1961
2053
  }
1962
2054
  /** @deprecated Use {@link destroy}. */
1963
2055
  delete() {
@@ -1969,13 +2061,6 @@ var TextureTransform = class {
1969
2061
  this.model.draw(renderPass);
1970
2062
  renderPass.end();
1971
2063
  }
1972
- /** @deprecated */
1973
- update(...args) {
1974
- console.warn("TextureTransform#update() not implemented");
1975
- }
1976
- getData({ packed = false } = {}) {
1977
- throw new Error("getData() not implemented");
1978
- }
1979
2064
  getTargetTexture() {
1980
2065
  const { targetTexture } = this.bindings[this.currentIndex];
1981
2066
  return targetTexture;
@@ -2111,56 +2196,161 @@ var Geometry = class {
2111
2196
  }
2112
2197
  };
2113
2198
 
2114
- // dist/lib/clip-space.js
2199
+ // dist/models/clip-space.js
2200
+ var CLIPSPACE_VERTEX_SHADER_WGSL = (
2201
+ /* wgsl */
2202
+ `struct VertexInputs {
2203
+ @location(0) clipSpacePosition: vec2<f32>,
2204
+ @location(1) texCoord: vec2<f32>,
2205
+ @location(2) coordinate: vec2<f32>
2206
+ }
2207
+
2208
+ struct FragmentInputs {
2209
+ @builtin(position) Position : vec4<f32>,
2210
+ @location(0) position : vec2<f32>,
2211
+ @location(1) coordinate : vec2<f32>,
2212
+ @location(2) uv : vec2<f32>
2213
+ };
2214
+
2215
+ @vertex
2216
+ fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
2217
+ var outputs: FragmentInputs;
2218
+ outputs.Position = vec4(inputs.clipSpacePosition, 0., 1.);
2219
+ outputs.position = inputs.clipSpacePosition;
2220
+ outputs.coordinate = inputs.coordinate;
2221
+ outputs.uv = inputs.texCoord;
2222
+ return outputs;
2223
+ }
2224
+ `
2225
+ );
2115
2226
  var CLIPSPACE_VERTEX_SHADER = (
2116
2227
  /* glsl */
2117
2228
  `#version 300 es
2118
- in vec2 aClipSpacePosition;
2119
- in vec2 aTexCoord;
2120
- in vec2 aCoordinate;
2229
+ in vec2 clipSpacePositions;
2230
+ in vec2 texCoords;
2231
+ in vec2 coordinates;
2121
2232
 
2122
2233
  out vec2 position;
2123
2234
  out vec2 coordinate;
2124
2235
  out vec2 uv;
2125
2236
 
2126
2237
  void main(void) {
2127
- gl_Position = vec4(aClipSpacePosition, 0., 1.);
2128
- position = aClipSpacePosition;
2129
- coordinate = aCoordinate;
2130
- uv = aTexCoord;
2238
+ gl_Position = vec4(clipSpacePositions, 0., 1.);
2239
+ position = clipSpacePositions;
2240
+ coordinate = coordinates;
2241
+ uv = texCoords;
2131
2242
  }
2132
2243
  `
2133
2244
  );
2134
2245
  var POSITIONS = [-1, -1, 1, -1, -1, 1, 1, 1];
2135
2246
  var ClipSpace = class extends Model {
2136
- constructor(device, opts) {
2247
+ constructor(device, props) {
2137
2248
  const TEX_COORDS = POSITIONS.map((coord) => coord === -1 ? 0 : coord);
2249
+ if (props.source) {
2250
+ props = { ...props, source: `${CLIPSPACE_VERTEX_SHADER_WGSL}
2251
+ ${props.source}` };
2252
+ }
2138
2253
  super(device, {
2139
- ...opts,
2254
+ id: props.id || uid("clip-space"),
2255
+ ...props,
2140
2256
  vs: CLIPSPACE_VERTEX_SHADER,
2141
2257
  vertexCount: 4,
2142
2258
  geometry: new Geometry({
2143
2259
  topology: "triangle-strip",
2144
2260
  vertexCount: 4,
2145
2261
  attributes: {
2146
- aClipSpacePosition: { size: 2, value: new Float32Array(POSITIONS) },
2147
- aTexCoord: { size: 2, value: new Float32Array(TEX_COORDS) },
2148
- aCoordinate: { size: 2, value: new Float32Array(TEX_COORDS) }
2262
+ clipSpacePositions: { size: 2, value: new Float32Array(POSITIONS) },
2263
+ texCoords: { size: 2, value: new Float32Array(TEX_COORDS) },
2264
+ coordinates: { size: 2, value: new Float32Array(TEX_COORDS) }
2149
2265
  }
2150
2266
  })
2151
2267
  });
2152
2268
  }
2153
2269
  };
2154
2270
 
2271
+ // dist/models/billboard-texture-model.js
2272
+ var BACKGROUND_FS_WGSL = (
2273
+ /* wgsl */
2274
+ `@group(0) @binding(0) var backgroundTexture: texture_2d<f32>;
2275
+ @group(0) @binding(1) var backgroundTextureSampler: sampler;
2276
+
2277
+ fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
2278
+ let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0) * 2;
2279
+ let texSize: vec2<f32> = vec2<f32>(f32(iTexSize.x), f32(iTexSize.y));
2280
+ var position: vec2<f32> = coordinates.xy / texSize;
2281
+ return position;
2282
+ }
2283
+
2284
+ @fragment
2285
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
2286
+ let position: vec2<f32> = billboardTexture_getTextureUV(inputs.coordinate);
2287
+ return textureSample(backgroundTexture, backgroundTextureSampler, position);
2288
+ }
2289
+ `
2290
+ );
2291
+ var BACKGROUND_FS = (
2292
+ /* glsl */
2293
+ `#version 300 es
2294
+ precision highp float;
2295
+
2296
+ uniform sampler2D backgroundTexture;
2297
+ out vec4 fragColor;
2298
+
2299
+ vec2 billboardTexture_getTextureUV() {
2300
+ ivec2 iTexSize = textureDimensions(backgroundTexture, 0) * 2;
2301
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
2302
+ vec2 position = gl_FragCoord.xy / texSize;
2303
+ return position;
2304
+ }
2305
+
2306
+ void main(void) {
2307
+ vec2 position = billboardTexture_getTextureUV();
2308
+ fragColor = texture(backgroundTexture, position);
2309
+ }
2310
+ `
2311
+ );
2312
+ var BackgroundTextureModel = class extends ClipSpace {
2313
+ constructor(device, props) {
2314
+ super(device, {
2315
+ id: props.id || "background-texture-model",
2316
+ source: BACKGROUND_FS_WGSL,
2317
+ fs: BACKGROUND_FS,
2318
+ parameters: {
2319
+ depthWriteEnabled: false,
2320
+ depthCompare: "always",
2321
+ ...props.blend ? {
2322
+ blend: true,
2323
+ blendColorOperation: "add",
2324
+ blendAlphaOperation: "add",
2325
+ blendColorSrcFactor: "one",
2326
+ blendColorDstFactor: "one-minus-src-color",
2327
+ blendAlphaSrcFactor: "one",
2328
+ blendAlphaDstFactor: "one-minus-src-alpha"
2329
+ } : {}
2330
+ }
2331
+ });
2332
+ this.setTexture(props.backgroundTexture);
2333
+ }
2334
+ setTexture(backgroundTexture) {
2335
+ this.setBindings({
2336
+ backgroundTexture
2337
+ });
2338
+ }
2339
+ predraw() {
2340
+ this.shaderInputs.setProps({});
2341
+ super.predraw();
2342
+ }
2343
+ };
2344
+
2155
2345
  // dist/scenegraph/scenegraph-node.js
2156
- var import_core12 = require("@math.gl/core");
2346
+ var import_core9 = require("@math.gl/core");
2157
2347
  var ScenegraphNode = class {
2158
2348
  id;
2159
- matrix = new import_core12.Matrix4();
2349
+ matrix = new import_core9.Matrix4();
2160
2350
  display = true;
2161
- position = new import_core12.Vector3();
2162
- rotation = new import_core12.Vector3();
2163
- scale = new import_core12.Vector3(1, 1, 1);
2351
+ position = new import_core9.Vector3();
2352
+ rotation = new import_core9.Vector3();
2353
+ scale = new import_core9.Vector3(1, 1, 1);
2164
2354
  userData = {};
2165
2355
  props = {};
2166
2356
  constructor(props = {}) {
@@ -2245,7 +2435,7 @@ var ScenegraphNode = class {
2245
2435
  }
2246
2436
  getCoordinateUniforms(viewMatrix, modelMatrix) {
2247
2437
  modelMatrix = modelMatrix || this.matrix;
2248
- const worldMatrix = new import_core12.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2438
+ const worldMatrix = new import_core9.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2249
2439
  const worldInverse = worldMatrix.invert();
2250
2440
  const worldInverseTranspose = worldInverse.transpose();
2251
2441
  return {
@@ -2297,14 +2487,14 @@ var ScenegraphNode = class {
2297
2487
  };
2298
2488
 
2299
2489
  // dist/scenegraph/group-node.js
2300
- var import_core13 = require("@math.gl/core");
2301
- var import_core14 = require("@luma.gl/core");
2490
+ var import_core10 = require("@math.gl/core");
2491
+ var import_core11 = require("@luma.gl/core");
2302
2492
  var GroupNode = class extends ScenegraphNode {
2303
2493
  children;
2304
2494
  constructor(props = {}) {
2305
2495
  props = Array.isArray(props) ? { children: props } : props;
2306
2496
  const { children = [] } = props;
2307
- import_core14.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2497
+ import_core11.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2308
2498
  super(props);
2309
2499
  this.children = children;
2310
2500
  }
@@ -2319,12 +2509,12 @@ var GroupNode = class extends ScenegraphNode {
2319
2509
  return;
2320
2510
  }
2321
2511
  const [min, max] = bounds;
2322
- const center = new import_core13.Vector3(min).add(max).divide([2, 2, 2]);
2512
+ const center = new import_core10.Vector3(min).add(max).divide([2, 2, 2]);
2323
2513
  worldMatrix.transformAsPoint(center, center);
2324
- const halfSize = new import_core13.Vector3(max).subtract(min).divide([2, 2, 2]);
2514
+ const halfSize = new import_core10.Vector3(max).subtract(min).divide([2, 2, 2]);
2325
2515
  worldMatrix.transformAsVector(halfSize, halfSize);
2326
2516
  for (let v = 0; v < 8; v++) {
2327
- const position = new import_core13.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
2517
+ const position = new import_core10.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
2328
2518
  for (let i = 0; i < 3; i++) {
2329
2519
  result[0][i] = Math.min(result[0][i], position[i]);
2330
2520
  result[1][i] = Math.max(result[1][i], position[i]);
@@ -2364,8 +2554,8 @@ var GroupNode = class extends ScenegraphNode {
2364
2554
  this.children = [];
2365
2555
  return this;
2366
2556
  }
2367
- traverse(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
2368
- const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
2557
+ traverse(visitor, { worldMatrix = new import_core10.Matrix4() } = {}) {
2558
+ const modelMatrix = new import_core10.Matrix4(worldMatrix).multiplyRight(this.matrix);
2369
2559
  for (const child of this.children) {
2370
2560
  if (child instanceof GroupNode) {
2371
2561
  child.traverse(visitor, { worldMatrix: modelMatrix });
@@ -3147,7 +3337,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
3147
3337
  };
3148
3338
 
3149
3339
  // dist/geometries/ico-sphere-geometry.js
3150
- var import_core15 = require("@math.gl/core");
3340
+ var import_core12 = require("@math.gl/core");
3151
3341
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
3152
3342
  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];
3153
3343
  var IcoSphereGeometry = class extends Geometry {
@@ -3245,7 +3435,7 @@ function tesselateIcosaHedron(props) {
3245
3435
  const u3 = 1 - phi3 / PI2;
3246
3436
  const vec1 = [x3 - x2, y3 - y2, z3 - z2];
3247
3437
  const vec2 = [x1 - x2, y1 - y2, z1 - z2];
3248
- const normal = new import_core15.Vector3(vec1).cross(vec2).normalize();
3438
+ const normal = new import_core12.Vector3(vec1).cross(vec2).normalize();
3249
3439
  let newIndex;
3250
3440
  if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
3251
3441
  positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
@@ -3505,11 +3695,377 @@ function fract(n) {
3505
3695
  return n - Math.floor(n);
3506
3696
  }
3507
3697
 
3508
- // dist/computation.js
3509
- var import_core16 = require("@luma.gl/core");
3510
- var import_core17 = require("@luma.gl/core");
3511
- var import_core18 = require("@luma.gl/core");
3698
+ // dist/passes/shader-pass-renderer.js
3512
3699
  var import_shadertools5 = require("@luma.gl/shadertools");
3700
+
3701
+ // dist/compute/swap.js
3702
+ var import_core13 = require("@luma.gl/core");
3703
+ var Swap = class {
3704
+ /** The current resource - usually the source for renders or computations */
3705
+ current;
3706
+ /** The next resource - usually the target/destination for transforms / computations */
3707
+ next;
3708
+ constructor(props) {
3709
+ this.current = props.current;
3710
+ this.next = props.next;
3711
+ }
3712
+ /** Destroys the two managed resources */
3713
+ destroy() {
3714
+ var _a, _b;
3715
+ (_a = this.current) == null ? void 0 : _a.destroy();
3716
+ (_b = this.next) == null ? void 0 : _b.destroy();
3717
+ }
3718
+ /** Make the next resource into the current resource, and reuse the current resource as the next resource */
3719
+ swap() {
3720
+ const current = this.current;
3721
+ this.current = this.next;
3722
+ this.next = current;
3723
+ }
3724
+ };
3725
+ var SwapFramebuffers = class extends Swap {
3726
+ constructor(device, props) {
3727
+ var _a, _b;
3728
+ props = { ...props };
3729
+ let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
3730
+ format: colorAttachment,
3731
+ usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
3732
+ }));
3733
+ const current = device.createFramebuffer({ ...props, colorAttachments });
3734
+ colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
3735
+ format: colorAttachment,
3736
+ usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
3737
+ }));
3738
+ const next = device.createFramebuffer({ ...props, colorAttachments });
3739
+ super({ current, next });
3740
+ }
3741
+ /**
3742
+ * Resizes the Framebuffers.
3743
+ * @returns true if the size changed, otherwise exiting framebuffers were preserved
3744
+ * @note any contents are not preserved!
3745
+ */
3746
+ resize(size) {
3747
+ if (size.width === this.current.width && size.height === this.current.height) {
3748
+ return false;
3749
+ }
3750
+ const { current, next } = this;
3751
+ this.current = current.clone(size);
3752
+ current.destroy();
3753
+ this.next = next.clone(size);
3754
+ next.destroy();
3755
+ return true;
3756
+ }
3757
+ };
3758
+ var SwapBuffers = class extends Swap {
3759
+ constructor(device, props) {
3760
+ super({ current: device.createBuffer(props), next: device.createBuffer(props) });
3761
+ }
3762
+ /**
3763
+ * Resizes the Buffers.
3764
+ * @returns true if the size changed, otherwise exiting buffers were preserved.
3765
+ * @note any contents are not preserved!
3766
+ */
3767
+ resize(props) {
3768
+ if (props.byteLength === this.current.byteLength) {
3769
+ return false;
3770
+ }
3771
+ const { current, next } = this;
3772
+ this.current = current.clone(props);
3773
+ current.destroy();
3774
+ this.next = next.clone(props);
3775
+ next.destroy();
3776
+ return true;
3777
+ }
3778
+ };
3779
+
3780
+ // dist/passes/get-fragment-shader.js
3781
+ function getFragmentShaderForRenderPass(options) {
3782
+ const { shaderPass, action, shadingLanguage } = options;
3783
+ switch (action) {
3784
+ case "filter":
3785
+ const filterFunc = `${shaderPass.name}_filterColor_ext`;
3786
+ return shadingLanguage === "wgsl" ? getFilterShaderWGSL(filterFunc) : getFilterShaderGLSL(filterFunc);
3787
+ case "sample":
3788
+ const samplerFunc = `${shaderPass.name}_sampleColor`;
3789
+ return shadingLanguage === "wgsl" ? getSamplerShaderWGSL(samplerFunc) : getSamplerShaderGLSL(samplerFunc);
3790
+ default:
3791
+ throw new Error(`${shaderPass.name} no fragment shader generated for shader pass`);
3792
+ }
3793
+ }
3794
+ function getFilterShaderWGSL(func) {
3795
+ return (
3796
+ /* wgsl */
3797
+ `// Binding 0:1 is reserved for shader passes
3798
+ @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
3799
+ @group(0) @binding(1) var texture: texture_2d<f32>;
3800
+ @group(0) @binding(2) var sampler: sampler;
3801
+
3802
+ struct FragmentInputs = {
3803
+ @location(0) fragUV: vec2f,
3804
+ @location(1) fragPosition: vec4f,
3805
+ @location(2) fragCoordinate: vec4f
3806
+ };
3807
+
3808
+ @fragment
3809
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
3810
+ let texSize = textureDimensions(texture, 0);
3811
+ var fragColor = textureSample(texture, sampler, fragUV);
3812
+ fragColor = ${func}(gl_FragColor, texSize, texCoord);
3813
+ return fragColor;
3814
+ }
3815
+ `
3816
+ );
3817
+ }
3818
+ function getSamplerShaderWGSL(func) {
3819
+ return (
3820
+ /* wgsl */
3821
+ `// Binding 0:1 is reserved for shader passes
3822
+ @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
3823
+ @group(0) @binding(1) var texture: texture_2d<f32>;
3824
+ @group(0) @binding(2) var sampler: sampler;
3825
+
3826
+ struct FragmentInputs = {
3827
+ @location(0) fragUV: vec2f,
3828
+ @location(1) fragPosition: vec4f,
3829
+ @location(2) fragCoordinate: vec4f
3830
+ };
3831
+
3832
+ @fragment
3833
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
3834
+ let texSize = textureDimensions(texture, 0);
3835
+ var fragColor = textureSample(texture, sampler, fragUV);
3836
+ fragColor = ${func}(gl_FragColor, texSize, texCoord);
3837
+ return fragColor;
3838
+ }
3839
+ `
3840
+ );
3841
+ }
3842
+ function getFilterShaderGLSL(func) {
3843
+ return (
3844
+ /* glsl */
3845
+ `#version 300 es
3846
+
3847
+ uniform sampler2D sourceTexture;
3848
+
3849
+ in vec2 position;
3850
+ in vec2 coordinate;
3851
+ in vec2 uv;
3852
+
3853
+ out vec4 fragColor;
3854
+
3855
+ void main() {
3856
+ vec2 texCoord = coordinate;
3857
+ ivec2 iTexSize = textureSize(sourceTexture, 0);
3858
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
3859
+
3860
+ fragColor = texture(sourceTexture, texCoord);
3861
+ fragColor = ${func}(fragColor, texSize, texCoord);
3862
+ }
3863
+ `
3864
+ );
3865
+ }
3866
+ function getSamplerShaderGLSL(func) {
3867
+ return (
3868
+ /* glsl */
3869
+ `#version 300 es
3870
+
3871
+ uniform sampler2D sourceTexture;
3872
+
3873
+ in vec2 position;
3874
+ in vec2 coordinate;
3875
+ in vec2 uv;
3876
+
3877
+ out vec4 fragColor;
3878
+
3879
+ void main() {
3880
+ vec2 texCoord = coordinate;
3881
+ ivec2 iTexSize = textureSize(sourceTexture, 0);
3882
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
3883
+
3884
+ fragColor = ${func}(sourceTexture, texSize, texCoord);
3885
+ }
3886
+ `
3887
+ );
3888
+ }
3889
+
3890
+ // dist/passes/shader-pass-renderer.js
3891
+ var ShaderPassRenderer = class {
3892
+ device;
3893
+ shaderInputs;
3894
+ passRenderers;
3895
+ swapFramebuffers;
3896
+ /** For rendering to the screen */
3897
+ clipSpace;
3898
+ textureModel;
3899
+ constructor(device, props) {
3900
+ this.device = device;
3901
+ props.shaderPasses.map((shaderPass) => (0, import_shadertools5.initializeShaderModule)(shaderPass));
3902
+ const modules = props.shaderPasses.reduce((object, shaderPass) => ({ ...object, [shaderPass.name]: shaderPass }), {});
3903
+ this.shaderInputs = props.shaderInputs || new ShaderInputs(modules);
3904
+ const size = device.getCanvasContext().getPixelSize();
3905
+ this.swapFramebuffers = new SwapFramebuffers(device, {
3906
+ colorAttachments: ["rgba8unorm"],
3907
+ width: size[0],
3908
+ height: size[1]
3909
+ });
3910
+ this.textureModel = new BackgroundTextureModel(device, {
3911
+ backgroundTexture: this.swapFramebuffers.current.colorAttachments[0].texture
3912
+ });
3913
+ this.clipSpace = new ClipSpace(device, {
3914
+ source: (
3915
+ /* wgsl */
3916
+ ` @group(0) @binding(0) var sourceTexture: texture_2d<f32>;
3917
+ @group(0) @binding(1) var sourceTextureSampler: sampler;
3918
+
3919
+ @fragment
3920
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
3921
+ let texCoord: vec2<f32> = inputs.coordinate;
3922
+ return textureSample(sourceTexture, sourceTextureSampler, texCoord);
3923
+ }
3924
+ `
3925
+ ),
3926
+ fs: (
3927
+ /* glsl */
3928
+ `#version 300 es
3929
+
3930
+ uniform sampler2D sourceTexture;
3931
+ in vec2 uv;
3932
+ in vec2 coordinate;
3933
+ out vec4 fragColor;
3934
+
3935
+ void main() {
3936
+ vec2 texCoord = coordinate;
3937
+ fragColor = texture(sourceTexture, coordinate);
3938
+ }
3939
+ `
3940
+ )
3941
+ });
3942
+ this.passRenderers = props.shaderPasses.map((shaderPass) => new PassRenderer(device, shaderPass));
3943
+ }
3944
+ /** Destroys resources created by this ShaderPassRenderer */
3945
+ destroy() {
3946
+ for (const subPassRenderer of this.passRenderers) {
3947
+ subPassRenderer.destroy();
3948
+ }
3949
+ this.swapFramebuffers.destroy();
3950
+ this.clipSpace.destroy();
3951
+ }
3952
+ resize(width, height) {
3953
+ this.swapFramebuffers.resize({ width, height });
3954
+ }
3955
+ renderToScreen(options) {
3956
+ const outputTexture = this.renderToTexture(options);
3957
+ if (!outputTexture) {
3958
+ return false;
3959
+ }
3960
+ const renderPass = this.device.beginRenderPass({ clearColor: [0, 0, 0, 1], clearDepth: 1 });
3961
+ this.clipSpace.setBindings({ sourceTexture: outputTexture });
3962
+ this.clipSpace.draw(renderPass);
3963
+ renderPass.end();
3964
+ return true;
3965
+ }
3966
+ /** Runs the shaderPasses in sequence on the sourceTexture and returns a texture with the results.
3967
+ * @returns null if the the sourceTexture has not yet been loaded
3968
+ */
3969
+ renderToTexture(options) {
3970
+ const { sourceTexture } = options;
3971
+ if (!sourceTexture.isReady) {
3972
+ return null;
3973
+ }
3974
+ this.textureModel.destroy();
3975
+ this.textureModel = new BackgroundTextureModel(this.device, {
3976
+ backgroundTexture: sourceTexture
3977
+ });
3978
+ const clearTexturePass = this.device.beginRenderPass({
3979
+ framebuffer: this.swapFramebuffers.current,
3980
+ clearColor: [0, 0, 0, 1]
3981
+ });
3982
+ this.textureModel.draw(clearTexturePass);
3983
+ clearTexturePass.end();
3984
+ let first = true;
3985
+ for (const passRenderer of this.passRenderers) {
3986
+ for (const subPassRenderer of passRenderer.subPassRenderers) {
3987
+ if (!first) {
3988
+ this.swapFramebuffers.swap();
3989
+ }
3990
+ first = false;
3991
+ const swapBufferTexture = this.swapFramebuffers.current.colorAttachments[0].texture;
3992
+ const bindings = {
3993
+ sourceTexture: swapBufferTexture
3994
+ // texSize: [sourceTextures.width, sourceTextures.height]
3995
+ };
3996
+ const renderPass = this.device.beginRenderPass({
3997
+ framebuffer: this.swapFramebuffers.next,
3998
+ clearColor: [0, 0, 0, 1],
3999
+ clearDepth: 1
4000
+ });
4001
+ subPassRenderer.render({ renderPass, bindings });
4002
+ renderPass.end();
4003
+ }
4004
+ }
4005
+ this.swapFramebuffers.swap();
4006
+ const outputTexture = this.swapFramebuffers.current.colorAttachments[0].texture;
4007
+ return outputTexture;
4008
+ }
4009
+ };
4010
+ var PassRenderer = class {
4011
+ shaderPass;
4012
+ subPassRenderers;
4013
+ constructor(device, shaderPass, props = {}) {
4014
+ this.shaderPass = shaderPass;
4015
+ const subPasses = shaderPass.passes || [];
4016
+ this.subPassRenderers = subPasses.map((subPass) => {
4017
+ return new SubPassRenderer(device, shaderPass, subPass);
4018
+ });
4019
+ }
4020
+ destroy() {
4021
+ for (const subPassRenderer of this.subPassRenderers) {
4022
+ subPassRenderer.destroy();
4023
+ }
4024
+ }
4025
+ };
4026
+ var SubPassRenderer = class {
4027
+ model;
4028
+ shaderPass;
4029
+ subPass;
4030
+ constructor(device, shaderPass, subPass) {
4031
+ this.shaderPass = shaderPass;
4032
+ this.subPass = subPass;
4033
+ const action = subPass.action || subPass.filter && "filter" || subPass.sampler && "sample" || "filter";
4034
+ const fs3 = getFragmentShaderForRenderPass({
4035
+ shaderPass,
4036
+ action,
4037
+ shadingLanguage: device.info.shadingLanguage
4038
+ });
4039
+ this.model = new ClipSpace(device, {
4040
+ id: `${shaderPass.name}-subpass`,
4041
+ source: fs3,
4042
+ fs: fs3,
4043
+ modules: [shaderPass],
4044
+ parameters: {
4045
+ depthWriteEnabled: false,
4046
+ depthCompare: "always"
4047
+ }
4048
+ });
4049
+ }
4050
+ destroy() {
4051
+ this.model.destroy();
4052
+ }
4053
+ render(options) {
4054
+ const { renderPass, bindings } = options;
4055
+ this.model.shaderInputs.setProps({
4056
+ [this.shaderPass.name]: this.shaderPass.uniforms || {}
4057
+ });
4058
+ this.model.shaderInputs.setProps({
4059
+ [this.shaderPass.name]: this.subPass.uniforms || {}
4060
+ });
4061
+ this.model.setBindings(bindings || {});
4062
+ this.model.draw(renderPass);
4063
+ }
4064
+ };
4065
+
4066
+ // dist/compute/computation.js
4067
+ var import_core14 = require("@luma.gl/core");
4068
+ var import_shadertools6 = require("@luma.gl/shadertools");
3513
4069
  var import_types2 = require("@math.gl/types");
3514
4070
  var LOG_DRAW_PRIORITY2 = 2;
3515
4071
  var LOG_DRAW_TIMEOUT2 = 1e4;
@@ -3549,18 +4105,18 @@ var _Computation = class {
3549
4105
  const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
3550
4106
  this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
3551
4107
  this.setShaderInputs(this.shaderInputs);
3552
- this.props.shaderLayout ||= (0, import_shadertools5.getShaderLayoutFromWGSL)(this.props.source);
4108
+ this.props.shaderLayout ||= (0, import_shadertools6.getShaderLayoutFromWGSL)(this.props.source);
3553
4109
  const platformInfo = getPlatformInfo2(device);
3554
4110
  const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
3555
4111
  this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
3556
4112
  this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
3557
- const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
4113
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
3558
4114
  platformInfo,
3559
4115
  ...this.props,
3560
4116
  modules
3561
4117
  });
3562
- this.source = source;
3563
- this._getModuleUniforms = getUniforms;
4118
+ this.source = source3;
4119
+ this._getModuleUniforms = getUniforms2;
3564
4120
  this.pipeline = this._updatePipeline();
3565
4121
  if (props.bindings) {
3566
4122
  this.setBindings(props.bindings);
@@ -3607,7 +4163,7 @@ var _Computation = class {
3607
4163
  }
3608
4164
  setShaderInputs(shaderInputs) {
3609
4165
  this.shaderInputs = shaderInputs;
3610
- this._uniformStore = new import_core16.UniformStore(this.shaderInputs.modules);
4166
+ this._uniformStore = new import_core14.UniformStore(this.shaderInputs.modules);
3611
4167
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
3612
4168
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
3613
4169
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -3644,7 +4200,7 @@ var _Computation = class {
3644
4200
  if (this._pipelineNeedsUpdate) {
3645
4201
  let prevShader = null;
3646
4202
  if (this.pipeline) {
3647
- import_core17.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
4203
+ import_core14.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
3648
4204
  prevShader = this.shader;
3649
4205
  }
3650
4206
  this._pipelineNeedsUpdate = false;
@@ -3652,7 +4208,7 @@ var _Computation = class {
3652
4208
  id: `${this.id}-fragment`,
3653
4209
  stage: "compute",
3654
4210
  source: this.source,
3655
- debug: this.props.debugShaders
4211
+ debugShaders: this.props.debugShaders
3656
4212
  });
3657
4213
  this.pipeline = this.pipelineFactory.createComputePipeline({
3658
4214
  ...this.props,
@@ -3668,33 +4224,33 @@ var _Computation = class {
3668
4224
  _lastLogTime = 0;
3669
4225
  _logOpen = false;
3670
4226
  _logDrawCallStart() {
3671
- const logDrawTimeout = import_core17.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
3672
- if (import_core17.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
4227
+ const logDrawTimeout = import_core14.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
4228
+ if (import_core14.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
3673
4229
  return;
3674
4230
  }
3675
4231
  this._lastLogTime = Date.now();
3676
4232
  this._logOpen = true;
3677
- import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
4233
+ import_core14.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core14.log.level <= 2 })();
3678
4234
  }
3679
4235
  _logDrawCallEnd() {
3680
4236
  if (this._logOpen) {
3681
4237
  const uniformTable = this.shaderInputs.getDebugTable();
3682
- import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
3683
- import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
4238
+ import_core14.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
4239
+ import_core14.log.groupEnd(LOG_DRAW_PRIORITY2)();
3684
4240
  this._logOpen = false;
3685
4241
  }
3686
4242
  }
3687
4243
  _drawCount = 0;
3688
4244
  // TODO - fix typing of luma data types
3689
4245
  _getBufferOrConstantValues(attribute, dataType) {
3690
- const TypedArrayConstructor = (0, import_core18.getTypedArrayFromDataType)(dataType);
3691
- const typedArray = attribute instanceof import_core16.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
4246
+ const TypedArrayConstructor = (0, import_core14.getTypedArrayFromDataType)(dataType);
4247
+ const typedArray = attribute instanceof import_core14.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
3692
4248
  return typedArray.toString();
3693
4249
  }
3694
4250
  };
3695
4251
  var Computation = _Computation;
3696
4252
  __publicField(Computation, "defaultProps", {
3697
- ...import_core16.ComputePipeline.defaultProps,
4253
+ ...import_core14.ComputePipeline.defaultProps,
3698
4254
  id: "unnamed",
3699
4255
  handle: void 0,
3700
4256
  userData: {},
@@ -3705,7 +4261,7 @@ __publicField(Computation, "defaultProps", {
3705
4261
  shaderInputs: void 0,
3706
4262
  pipelineFactory: void 0,
3707
4263
  shaderFactory: void 0,
3708
- shaderAssembler: import_shadertools5.ShaderAssembler.getDefaultShaderAssembler(),
4264
+ shaderAssembler: import_shadertools6.ShaderAssembler.getDefaultShaderAssembler(),
3709
4265
  debugShaders: void 0
3710
4266
  });
3711
4267
  function getPlatformInfo2(device) {
@@ -3718,4 +4274,543 @@ function getPlatformInfo2(device) {
3718
4274
  features: device.features
3719
4275
  };
3720
4276
  }
4277
+
4278
+ // dist/modules/picking/picking-uniforms.js
4279
+ var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
4280
+ var INVALID_INDEX = -1;
4281
+ var uniformTypes = {
4282
+ isActive: "i32",
4283
+ indexMode: "i32",
4284
+ batchIndex: "i32",
4285
+ isHighlightActive: "i32",
4286
+ highlightedBatchIndex: "i32",
4287
+ highlightedObjectIndex: "i32",
4288
+ highlightColor: "vec4<f32>"
4289
+ };
4290
+ var GLSL_UNIFORMS = (
4291
+ /* glsl */
4292
+ `precision highp float;
4293
+ precision highp int;
4294
+
4295
+ uniform pickingUniforms {
4296
+ int isActive;
4297
+ int indexMode;
4298
+ int batchIndex;
4299
+
4300
+ int isHighlightActive;
4301
+ int highlightedBatchIndex;
4302
+ int highlightedObjectIndex;
4303
+ vec4 highlightColor;
4304
+ } picking;
4305
+ `
4306
+ );
4307
+ var WGSL_UNIFORMS = (
4308
+ /* wgsl */
4309
+ `struct pickingUniforms {
4310
+ isActive: int32;
4311
+ indexMode: int32;
4312
+ batchIndex: int32;
4313
+
4314
+ isHighlightActive: int32;
4315
+ highlightedBatchIndex: int32;
4316
+ highlightedObjectIndex: int32;
4317
+ highlightColor: vec4<f32>;
4318
+ } picking;
4319
+ `
4320
+ );
4321
+ function getUniforms(props = {}, prevUniforms) {
4322
+ const uniforms = { ...prevUniforms };
4323
+ if (props.isActive !== void 0) {
4324
+ uniforms.isActive = Boolean(props.isActive);
4325
+ }
4326
+ switch (props.indexMode) {
4327
+ case "instance":
4328
+ uniforms.indexMode = 0;
4329
+ break;
4330
+ case "custom":
4331
+ uniforms.indexMode = 1;
4332
+ break;
4333
+ case void 0:
4334
+ break;
4335
+ }
4336
+ switch (props.highlightedObjectIndex) {
4337
+ case void 0:
4338
+ break;
4339
+ case null:
4340
+ uniforms.isHighlightActive = false;
4341
+ uniforms.highlightedObjectIndex = INVALID_INDEX;
4342
+ break;
4343
+ default:
4344
+ uniforms.isHighlightActive = true;
4345
+ uniforms.highlightedObjectIndex = props.highlightedObjectIndex;
4346
+ }
4347
+ if (typeof props.highlightedBatchIndex === "number") {
4348
+ uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
4349
+ }
4350
+ if (props.highlightColor) {
4351
+ uniforms.highlightColor = props.highlightColor;
4352
+ }
4353
+ return uniforms;
4354
+ }
4355
+ var pickingUniforms = {
4356
+ props: {},
4357
+ uniforms: {},
4358
+ name: "picking",
4359
+ uniformTypes,
4360
+ defaultUniforms: {
4361
+ isActive: false,
4362
+ indexMode: 0,
4363
+ batchIndex: 0,
4364
+ isHighlightActive: true,
4365
+ highlightedBatchIndex: INVALID_INDEX,
4366
+ highlightedObjectIndex: INVALID_INDEX,
4367
+ highlightColor: DEFAULT_HIGHLIGHT_COLOR
4368
+ },
4369
+ getUniforms
4370
+ };
4371
+
4372
+ // dist/modules/picking/picking-manager.js
4373
+ var _PickingManager = class {
4374
+ device;
4375
+ props;
4376
+ /** Info from latest pick operation */
4377
+ pickInfo = { batchIndex: null, objectIndex: null };
4378
+ /** Framebuffer used for picking */
4379
+ framebuffer = null;
4380
+ constructor(device, props) {
4381
+ this.device = device;
4382
+ this.props = { ..._PickingManager.defaultProps, ...props };
4383
+ }
4384
+ destroy() {
4385
+ var _a;
4386
+ (_a = this.framebuffer) == null ? void 0 : _a.destroy();
4387
+ }
4388
+ // TODO - Ask for a cached framebuffer? a Framebuffer factory?
4389
+ getFramebuffer() {
4390
+ if (!this.framebuffer) {
4391
+ this.framebuffer = this.device.createFramebuffer({
4392
+ colorAttachments: ["rgba8unorm", "rg32sint"],
4393
+ depthStencilAttachment: "depth24plus"
4394
+ });
4395
+ }
4396
+ return this.framebuffer;
4397
+ }
4398
+ /** Clear highlighted / picked object */
4399
+ clearPickState() {
4400
+ this.props.shaderInputs.setProps({ picking: { highlightedObjectIndex: null } });
4401
+ }
4402
+ /** Prepare for rendering picking colors */
4403
+ beginRenderPass() {
4404
+ var _a;
4405
+ const framebuffer = this.getFramebuffer();
4406
+ framebuffer.resize(this.device.getDefaultCanvasContext().getPixelSize());
4407
+ (_a = this.props.shaderInputs) == null ? void 0 : _a.setProps({ picking: { isActive: true } });
4408
+ const pickingPass = this.device.beginRenderPass({
4409
+ framebuffer,
4410
+ clearColors: [new Float32Array([0, 0, 0, 0]), new Int32Array([-1, -1, 0, 0])],
4411
+ clearDepth: 1
4412
+ });
4413
+ return pickingPass;
4414
+ }
4415
+ getPickInfo(mousePosition) {
4416
+ var _a;
4417
+ const framebuffer = this.getFramebuffer();
4418
+ const [pickX, pickY] = this.getPickPosition(mousePosition);
4419
+ const pixelData = this.device.readPixelsToArrayWebGL(framebuffer, {
4420
+ sourceX: pickX,
4421
+ sourceY: pickY,
4422
+ sourceWidth: 1,
4423
+ sourceHeight: 1,
4424
+ sourceAttachment: 1
4425
+ });
4426
+ if (!pixelData) {
4427
+ return null;
4428
+ }
4429
+ const pickInfo = {
4430
+ objectIndex: pixelData[0] === INVALID_INDEX ? null : pixelData[0],
4431
+ batchIndex: pixelData[1] === INVALID_INDEX ? null : pixelData[1]
4432
+ };
4433
+ if (pickInfo.objectIndex !== this.pickInfo.objectIndex || pickInfo.batchIndex !== this.pickInfo.batchIndex) {
4434
+ this.pickInfo = pickInfo;
4435
+ this.props.onObjectPicked(pickInfo);
4436
+ }
4437
+ (_a = this.props.shaderInputs) == null ? void 0 : _a.setProps({
4438
+ picking: {
4439
+ isActive: false,
4440
+ highlightedBatchIndex: pickInfo.batchIndex,
4441
+ highlightedObjectIndex: pickInfo.objectIndex
4442
+ }
4443
+ });
4444
+ return this.pickInfo;
4445
+ }
4446
+ /**
4447
+ * Get pick position in device pixel range
4448
+ * use the center pixel location in device pixel range
4449
+ */
4450
+ getPickPosition(mousePosition) {
4451
+ const devicePixels = this.device.getDefaultCanvasContext().cssToDevicePixels(mousePosition);
4452
+ const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
4453
+ const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
4454
+ return [pickX, pickY];
4455
+ }
4456
+ };
4457
+ var PickingManager = _PickingManager;
4458
+ __publicField(PickingManager, "defaultProps", {
4459
+ shaderInputs: void 0,
4460
+ onObjectPicked: () => {
4461
+ }
4462
+ });
4463
+
4464
+ // dist/modules/picking/index-picking.js
4465
+ var source = (
4466
+ /* wgsl */
4467
+ `${WGSL_UNIFORMS}
4468
+
4469
+ const INDEX_PICKING_MODE_INSTANCE = 0;
4470
+ const INDEX_PICKING_MODE_CUSTOM = 1;
4471
+ const INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4472
+
4473
+ struct indexPickingFragmentInputs = {
4474
+ objectIndex: int32;
4475
+ };
4476
+
4477
+ let indexPickingFragmentInputs: indexPickingFragmentInputs;
4478
+
4479
+ /**
4480
+ * Vertex shaders should call this function to set the object index.
4481
+ * If using instance or vertex mode, argument will be ignored, 0 can be supplied.
4482
+ */
4483
+ fn picking_setObjectIndex(objectIndex: int32) {
4484
+ switch (picking.indexMode) {
4485
+ case INDEX_PICKING_MODE_INSTANCE, default: {
4486
+ picking_objectIndex = instance_index;
4487
+ };
4488
+ case INDEX_PICKING_MODE_CUSTOM: {
4489
+ picking_objectIndex = objectIndex;
4490
+ };
4491
+ }
4492
+ }
4493
+
4494
+ `
4495
+ );
4496
+ var vs = (
4497
+ /* glsl */
4498
+ `${GLSL_UNIFORMS}
4499
+
4500
+ const int INDEX_PICKING_MODE_INSTANCE = 0;
4501
+ const int INDEX_PICKING_MODE_CUSTOM = 1;
4502
+
4503
+ const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4504
+
4505
+ flat out int picking_objectIndex;
4506
+
4507
+ /**
4508
+ * Vertex shaders should call this function to set the object index.
4509
+ * If using instance or vertex mode, argument will be ignored, 0 can be supplied.
4510
+ */
4511
+ void picking_setObjectIndex(int objectIndex) {
4512
+ switch (picking.indexMode) {
4513
+ case INDEX_PICKING_MODE_INSTANCE:
4514
+ picking_objectIndex = gl_InstanceID;
4515
+ break;
4516
+ case INDEX_PICKING_MODE_CUSTOM:
4517
+ picking_objectIndex = objectIndex;
4518
+ break;
4519
+ }
4520
+ }
4521
+ `
4522
+ );
4523
+ var fs = (
4524
+ /* glsl */
4525
+ `${GLSL_UNIFORMS}
4526
+
4527
+ const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4528
+
4529
+ flat in int picking_objectIndex;
4530
+
4531
+ /**
4532
+ * Check if this vertex is highlighted (part of the selected batch and object)
4533
+ */
4534
+ bool picking_isFragmentHighlighted() {
4535
+ return
4536
+ bool(picking.isHighlightActive) &&
4537
+ picking.highlightedBatchIndex == picking.batchIndex &&
4538
+ picking.highlightedObjectIndex == picking_objectIndex
4539
+ ;
4540
+ }
4541
+
4542
+ /**
4543
+ * Returns highlight color if this item is selected.
4544
+ */
4545
+ vec4 picking_filterHighlightColor(vec4 color) {
4546
+ // If we are still picking, we don't highlight
4547
+ if (bool(picking.isActive)) {
4548
+ return color;
4549
+ }
4550
+
4551
+ // If we are not highlighted, return color as is
4552
+ if (!picking_isFragmentHighlighted()) {
4553
+ return color;
4554
+ }
4555
+
4556
+ // Blend in highlight color based on its alpha value
4557
+ float highLightAlpha = picking.highlightColor.a;
4558
+ float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
4559
+ float highLightRatio = highLightAlpha / blendedAlpha;
4560
+
4561
+ vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
4562
+ return vec4(blendedRGB, blendedAlpha);
4563
+ }
4564
+
4565
+ /*
4566
+ * Returns picking color if picking enabled else unmodified argument.
4567
+ */
4568
+ ivec4 picking_getPickingColor() {
4569
+ // Assumes that colorAttachment0 is rg32int
4570
+ // TODO? - we could render indices into a second color attachment and not mess with fragColor
4571
+ return ivec4(picking_objectIndex, picking.batchIndex, 0u, 0u);
4572
+ }
4573
+
4574
+ vec4 picking_filterPickingColor(vec4 color) {
4575
+ if (bool(picking.isActive)) {
4576
+ if (picking_objectIndex == INDEX_PICKING_INVALID_INDEX) {
4577
+ discard;
4578
+ }
4579
+ }
4580
+ return color;
4581
+ }
4582
+
4583
+ /*
4584
+ * Returns picking color if picking is enabled if not
4585
+ * highlight color if this item is selected, otherwise unmodified argument.
4586
+ */
4587
+ vec4 picking_filterColor(vec4 color) {
4588
+ vec4 outColor = color;
4589
+ outColor = picking_filterHighlightColor(outColor);
4590
+ outColor = picking_filterPickingColor(outColor);
4591
+ return outColor;
4592
+ }
4593
+ `
4594
+ );
4595
+ var picking = {
4596
+ ...pickingUniforms,
4597
+ name: "picking",
4598
+ source,
4599
+ vs,
4600
+ fs
4601
+ };
4602
+
4603
+ // dist/modules/picking/color-picking.js
4604
+ var source2 = (
4605
+ /* wgsl */
4606
+ `${WGSL_UNIFORMS}
4607
+ `
4608
+ );
4609
+ var vs2 = (
4610
+ /* glsl */
4611
+ `${GLSL_UNIFORMS}
4612
+ out vec4 picking_vRGBcolor_Avalid;
4613
+
4614
+ // Normalize unsigned byte color to 0-1 range
4615
+ vec3 picking_normalizeColor(vec3 color) {
4616
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
4617
+ }
4618
+
4619
+ // Normalize unsigned byte color to 0-1 range
4620
+ vec4 picking_normalizeColor(vec4 color) {
4621
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
4622
+ }
4623
+
4624
+ bool picking_isColorZero(vec3 color) {
4625
+ return dot(color, vec3(1.0)) < 0.00001;
4626
+ }
4627
+
4628
+ bool picking_isColorValid(vec3 color) {
4629
+ return dot(color, vec3(1.0)) > 0.00001;
4630
+ }
4631
+
4632
+ // Check if this vertex is highlighted
4633
+ bool isVertexHighlighted(vec3 vertexColor) {
4634
+ vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
4635
+ return
4636
+ bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor));
4637
+ }
4638
+
4639
+ // Set the current picking color
4640
+ void picking_setPickingColor(vec3 pickingColor) {
4641
+ pickingColor = picking_normalizeColor(pickingColor);
4642
+
4643
+ if (bool(picking.isActive)) {
4644
+ // Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
4645
+ picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
4646
+
4647
+ if (!bool(picking.isAttribute)) {
4648
+ // Stores the picking color so that the fragment shader can render it during picking
4649
+ picking_vRGBcolor_Avalid.rgb = pickingColor;
4650
+ }
4651
+ } else {
4652
+ // Do the comparison with selected item color in vertex shader as it should mean fewer compares
4653
+ picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor));
4654
+ }
4655
+ }
4656
+
4657
+ void picking_setObjectIndex(uint objectIndex) {
4658
+ if (bool(picking.isActive)) {
4659
+ uint index = objectIndex;
4660
+ if (picking.indexMode == PICKING_INDEX_MODE_INSTANCE) {
4661
+ index = uint(gl_InstanceID);
4662
+ }
4663
+ picking_vRGBcolor_Avalid.r = float(index % 255) / 255.0;
4664
+ picking_vRGBcolor_Avalid.g = float((index / 255) % 255) / 255.0;
4665
+ picking_vRGBcolor_Avalid.b = float((index / 255 / 255) %255) / 255.0;
4666
+ }
4667
+ }
4668
+
4669
+ void picking_setPickingAttribute(float value) {
4670
+ if (bool(picking.isAttribute)) {
4671
+ picking_vRGBcolor_Avalid.r = value;
4672
+ }
4673
+ }
4674
+
4675
+ void picking_setPickingAttribute(vec2 value) {
4676
+ if (bool(picking.isAttribute)) {
4677
+ picking_vRGBcolor_Avalid.rg = value;
4678
+ }
4679
+ }
4680
+
4681
+ void picking_setPickingAttribute(vec3 value) {
4682
+ if (bool(picking.isAttribute)) {
4683
+ picking_vRGBcolor_Avalid.rgb = value;
4684
+ }
4685
+ }
4686
+ `
4687
+ );
4688
+ var fs2 = (
4689
+ /* glsl */
4690
+ `${GLSL_UNIFORMS}
4691
+
4692
+ in vec4 picking_vRGBcolor_Avalid;
4693
+
4694
+ /*
4695
+ * Returns highlight color if this item is selected.
4696
+ */
4697
+ vec4 picking_filterHighlightColor(vec4 color) {
4698
+ // If we are still picking, we don't highlight
4699
+ if (picking.isActive > 0.5) {
4700
+ return color;
4701
+ }
4702
+
4703
+ bool selected = bool(picking_vRGBcolor_Avalid.a);
4704
+
4705
+ if (selected) {
4706
+ // Blend in highlight color based on its alpha value
4707
+ float highLightAlpha = picking.highlightColor.a;
4708
+ float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
4709
+ float highLightRatio = highLightAlpha / blendedAlpha;
4710
+
4711
+ vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
4712
+ return vec4(blendedRGB, blendedAlpha);
4713
+ } else {
4714
+ return color;
4715
+ }
4716
+ }
4717
+
4718
+ /*
4719
+ * Returns picking color if picking enabled else unmodified argument.
4720
+ */
4721
+ vec4 picking_filterPickingColor(vec4 color) {
4722
+ if (bool(picking.isActive)) {
4723
+ if (picking_vRGBcolor_Avalid.a == 0.0) {
4724
+ discard;
4725
+ }
4726
+ return picking_vRGBcolor_Avalid;
4727
+ }
4728
+ return color;
4729
+ }
4730
+
4731
+ /*
4732
+ * Returns picking color if picking is enabled if not
4733
+ * highlight color if this item is selected, otherwise unmodified argument.
4734
+ */
4735
+ vec4 picking_filterColor(vec4 color) {
4736
+ vec4 highlightColor = picking_filterHighlightColor(color);
4737
+ return picking_filterPickingColor(highlightColor);
4738
+ }
4739
+ `
4740
+ );
4741
+ var picking2 = {
4742
+ ...pickingUniforms,
4743
+ name: "picking",
4744
+ source: source2,
4745
+ vs: vs2,
4746
+ fs: fs2
4747
+ };
4748
+
4749
+ // dist/modules/picking/legacy-picking-manager.js
4750
+ var LegacyPickingManager = class {
4751
+ device;
4752
+ framebuffer = null;
4753
+ shaderInputs;
4754
+ constructor(device, shaderInputs) {
4755
+ this.device = device;
4756
+ this.shaderInputs = shaderInputs;
4757
+ }
4758
+ destroy() {
4759
+ var _a;
4760
+ (_a = this.framebuffer) == null ? void 0 : _a.destroy();
4761
+ }
4762
+ getFramebuffer() {
4763
+ if (!this.framebuffer) {
4764
+ this.framebuffer = this.device.createFramebuffer({
4765
+ colorAttachments: ["rgba8unorm"],
4766
+ depthStencilAttachment: "depth24plus"
4767
+ });
4768
+ }
4769
+ return this.framebuffer;
4770
+ }
4771
+ /** Clear highlighted / picked object */
4772
+ clearPickState() {
4773
+ this.shaderInputs.setProps({ picking: { highlightedObjectColor: null } });
4774
+ }
4775
+ /** Prepare for rendering picking colors */
4776
+ beginRenderPass() {
4777
+ const framebuffer = this.getFramebuffer();
4778
+ framebuffer.resize(this.device.getCanvasContext().getPixelSize());
4779
+ this.shaderInputs.setProps({ picking: { isActive: true } });
4780
+ const pickingPass = this.device.beginRenderPass({
4781
+ framebuffer,
4782
+ clearColor: [0, 0, 0, 0],
4783
+ clearDepth: 1
4784
+ });
4785
+ return pickingPass;
4786
+ }
4787
+ updatePickState(mousePosition) {
4788
+ const framebuffer = this.getFramebuffer();
4789
+ const [pickX, pickY] = this.getPickPosition(mousePosition);
4790
+ const color255 = this.device.readPixelsToArrayWebGL(framebuffer, {
4791
+ sourceX: pickX,
4792
+ sourceY: pickY,
4793
+ sourceWidth: 1,
4794
+ sourceHeight: 1
4795
+ });
4796
+ let highlightedObjectColor = [...color255].map((x) => x / 255);
4797
+ const isHighlightActive = highlightedObjectColor[0] + highlightedObjectColor[1] + highlightedObjectColor[2] > 0;
4798
+ if (!isHighlightActive) {
4799
+ highlightedObjectColor = null;
4800
+ }
4801
+ this.shaderInputs.setProps({
4802
+ picking: { isActive: false, highlightedObjectColor }
4803
+ });
4804
+ }
4805
+ /**
4806
+ * Get pick position in device pixel range
4807
+ * use the center pixel location in device pixel range
4808
+ */
4809
+ getPickPosition(mousePosition) {
4810
+ const devicePixels = this.device.getCanvasContext().cssToDevicePixels(mousePosition);
4811
+ const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
4812
+ const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
4813
+ return [pickX, pickY];
4814
+ }
4815
+ };
3721
4816
  //# sourceMappingURL=index.cjs.map