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

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 (196) 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 +10 -15
  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 +2697 -5857
  56. package/dist/dist.min.js +420 -103
  57. package/dist/{lib → factories}/pipeline-factory.d.ts +11 -1
  58. package/dist/factories/pipeline-factory.d.ts.map +1 -0
  59. package/dist/factories/pipeline-factory.js +181 -0
  60. package/dist/factories/pipeline-factory.js.map +1 -0
  61. package/dist/{lib → factories}/shader-factory.d.ts +5 -1
  62. package/dist/factories/shader-factory.d.ts.map +1 -0
  63. package/dist/{lib → factories}/shader-factory.js +39 -4
  64. package/dist/factories/shader-factory.js.map +1 -0
  65. package/dist/geometries/cone-geometry.js +1 -0
  66. package/dist/geometries/cone-geometry.js.map +1 -0
  67. package/dist/geometries/cube-geometry.js +1 -0
  68. package/dist/geometries/cube-geometry.js.map +1 -0
  69. package/dist/geometries/cylinder-geometry.js +1 -0
  70. package/dist/geometries/cylinder-geometry.js.map +1 -0
  71. package/dist/geometries/ico-sphere-geometry.js +1 -0
  72. package/dist/geometries/ico-sphere-geometry.js.map +1 -0
  73. package/dist/geometries/plane-geometry.js +1 -0
  74. package/dist/geometries/plane-geometry.js.map +1 -0
  75. package/dist/geometries/sphere-geometry.js +1 -0
  76. package/dist/geometries/sphere-geometry.js.map +1 -0
  77. package/dist/geometries/truncated-cone-geometry.js +1 -0
  78. package/dist/geometries/truncated-cone-geometry.js.map +1 -0
  79. package/dist/geometry/geometry-table.js +1 -0
  80. package/dist/geometry/geometry-table.js.map +1 -0
  81. package/dist/geometry/geometry-utils.js +1 -0
  82. package/dist/geometry/geometry-utils.js.map +1 -0
  83. package/dist/geometry/geometry.js +1 -0
  84. package/dist/geometry/geometry.js.map +1 -0
  85. package/dist/geometry/gpu-geometry.js +1 -0
  86. package/dist/geometry/gpu-geometry.js.map +1 -0
  87. package/dist/geometry/gpu-table.js +1 -0
  88. package/dist/geometry/gpu-table.js.map +1 -0
  89. package/dist/index.cjs +1416 -209
  90. package/dist/index.cjs.map +4 -4
  91. package/dist/index.d.ts +23 -12
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +19 -9
  94. package/dist/index.js.map +1 -0
  95. package/dist/model/model.d.ts +11 -10
  96. package/dist/model/model.d.ts.map +1 -1
  97. package/dist/model/model.js +93 -70
  98. package/dist/model/model.js.map +1 -0
  99. package/dist/model/split-uniforms-and-bindings.d.ts +1 -1
  100. package/dist/model/split-uniforms-and-bindings.d.ts.map +1 -1
  101. package/dist/model/split-uniforms-and-bindings.js +2 -1
  102. package/dist/model/split-uniforms-and-bindings.js.map +1 -0
  103. package/dist/models/billboard-texture-model.d.ts +23 -0
  104. package/dist/models/billboard-texture-model.d.ts.map +1 -0
  105. package/dist/models/billboard-texture-model.js +78 -0
  106. package/dist/models/billboard-texture-model.js.map +1 -0
  107. package/dist/models/billboard-texture-module.d.ts +10 -0
  108. package/dist/models/billboard-texture-module.d.ts.map +1 -0
  109. package/dist/models/billboard-texture-module.js +37 -0
  110. package/dist/models/billboard-texture-module.js.map +1 -0
  111. package/dist/{lib → models}/clip-space.d.ts +3 -1
  112. package/dist/models/clip-space.d.ts.map +1 -0
  113. package/dist/models/clip-space.js +77 -0
  114. package/dist/models/clip-space.js.map +1 -0
  115. package/dist/modules/picking/color-picking.d.ts +28 -0
  116. package/dist/modules/picking/color-picking.d.ts.map +1 -0
  117. package/dist/modules/picking/color-picking.js +177 -0
  118. package/dist/modules/picking/color-picking.js.map +1 -0
  119. package/dist/modules/picking/index-picking.d.ts +32 -0
  120. package/dist/modules/picking/index-picking.d.ts.map +1 -0
  121. package/dist/modules/picking/index-picking.js +148 -0
  122. package/dist/modules/picking/index-picking.js.map +1 -0
  123. package/dist/modules/picking/legacy-picking-manager.d.ts +27 -0
  124. package/dist/modules/picking/legacy-picking-manager.d.ts.map +1 -0
  125. package/dist/modules/picking/legacy-picking-manager.js +76 -0
  126. package/dist/modules/picking/legacy-picking-manager.js.map +1 -0
  127. package/dist/modules/picking/picking-manager.d.ts +45 -0
  128. package/dist/modules/picking/picking-manager.d.ts.map +1 -0
  129. package/dist/modules/picking/picking-manager.js +101 -0
  130. package/dist/modules/picking/picking-manager.js.map +1 -0
  131. package/dist/modules/picking/picking-uniforms.d.ts +79 -0
  132. package/dist/modules/picking/picking-uniforms.d.ts.map +1 -0
  133. package/dist/modules/picking/picking-uniforms.js +109 -0
  134. package/dist/modules/picking/picking-uniforms.js.map +1 -0
  135. package/dist/passes/get-fragment-shader.d.ts +12 -0
  136. package/dist/passes/get-fragment-shader.d.ts.map +1 -0
  137. package/dist/passes/get-fragment-shader.js +117 -0
  138. package/dist/passes/get-fragment-shader.js.map +1 -0
  139. package/dist/passes/shader-pass-renderer.d.ts +63 -0
  140. package/dist/passes/shader-pass-renderer.d.ts.map +1 -0
  141. package/dist/passes/shader-pass-renderer.js +197 -0
  142. package/dist/passes/shader-pass-renderer.js.map +1 -0
  143. package/dist/scenegraph/group-node.js +1 -0
  144. package/dist/scenegraph/group-node.js.map +1 -0
  145. package/dist/scenegraph/model-node.js +1 -0
  146. package/dist/scenegraph/model-node.js.map +1 -0
  147. package/dist/scenegraph/scenegraph-node.js +1 -0
  148. package/dist/scenegraph/scenegraph-node.js.map +1 -0
  149. package/dist/shader-inputs.d.ts +8 -21
  150. package/dist/shader-inputs.d.ts.map +1 -1
  151. package/dist/shader-inputs.js +15 -11
  152. package/dist/shader-inputs.js.map +1 -0
  153. package/dist/utils/deep-equal.js +1 -0
  154. package/dist/utils/deep-equal.js.map +1 -0
  155. package/dist/utils/uid.js +1 -0
  156. package/dist/utils/uid.js.map +1 -0
  157. package/package.json +6 -6
  158. package/src/animation-loop/animation-loop.ts +27 -6
  159. package/src/animation-loop/make-animation-loop.ts +8 -3
  160. package/src/animation-loop/request-animation-frame.ts +4 -3
  161. package/src/application-utils/load-file.ts +2 -4
  162. package/src/async-texture/async-texture.ts +39 -7
  163. package/src/{transform → compute}/buffer-transform.ts +30 -14
  164. package/src/{computation.ts → compute/computation.ts} +14 -8
  165. package/src/compute/swap.ts +116 -0
  166. package/src/{transform → compute}/texture-transform.ts +9 -18
  167. package/src/debug/debug-framebuffer.ts +1 -1
  168. package/src/debug/debug-shader-layout.ts +1 -1
  169. package/src/factories/pipeline-factory.ts +222 -0
  170. package/src/{lib → factories}/shader-factory.ts +41 -5
  171. package/src/index.ts +35 -16
  172. package/src/model/model.ts +133 -78
  173. package/src/model/split-uniforms-and-bindings.ts +4 -4
  174. package/src/models/billboard-texture-model.ts +98 -0
  175. package/src/models/billboard-texture-module.ts +49 -0
  176. package/src/models/clip-space.ts +88 -0
  177. package/src/modules/picking/README.md +88 -0
  178. package/src/modules/picking/color-picking.ts +190 -0
  179. package/src/modules/picking/index-picking.ts +156 -0
  180. package/src/modules/picking/legacy-picking-manager.ts +99 -0
  181. package/src/modules/picking/picking-manager.ts +137 -0
  182. package/src/modules/picking/picking-uniforms.ts +179 -0
  183. package/src/passes/get-fragment-shader.ts +129 -0
  184. package/src/passes/shader-pass-renderer.ts +252 -0
  185. package/src/shader-inputs.ts +27 -48
  186. package/dist/computation.d.ts.map +0 -1
  187. package/dist/lib/clip-space.d.ts.map +0 -1
  188. package/dist/lib/clip-space.js +0 -46
  189. package/dist/lib/pipeline-factory.d.ts.map +0 -1
  190. package/dist/lib/pipeline-factory.js +0 -98
  191. package/dist/lib/shader-factory.d.ts.map +0 -1
  192. package/dist/transform/buffer-transform.d.ts +0 -35
  193. package/dist/transform/buffer-transform.d.ts.map +0 -1
  194. package/dist/transform/texture-transform.d.ts.map +0 -1
  195. package/src/lib/clip-space.ts +0 -53
  196. package/src/lib/pipeline-factory.ts +0 -126
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 */
@@ -774,59 +797,136 @@ var _PipelineFactory = class {
774
797
  return device._lumaData.defaultPipelineFactory;
775
798
  }
776
799
  device;
800
+ cachingEnabled;
777
801
  destroyPolicy;
802
+ debug;
778
803
  _hashCounter = 0;
779
804
  _hashes = {};
780
805
  _renderPipelineCache = {};
781
806
  _computePipelineCache = {};
807
+ get [Symbol.toStringTag]() {
808
+ return "PipelineFactory";
809
+ }
810
+ toString() {
811
+ return `PipelineFactory(${this.device.id})`;
812
+ }
782
813
  constructor(device) {
783
814
  this.device = device;
784
- this.destroyPolicy = device.props._factoryDestroyPolicy;
815
+ this.cachingEnabled = device.props._cachePipelines;
816
+ this.destroyPolicy = device.props._cacheDestroyPolicy;
817
+ this.debug = device.props.debugFactories;
785
818
  }
786
- /** Return a RenderPipeline matching props. Reuses a similar pipeline if already created. */
819
+ /** Return a RenderPipeline matching supplied props. Reuses an equivalent pipeline if already created. */
787
820
  createRenderPipeline(props) {
821
+ var _a;
822
+ if (!this.cachingEnabled) {
823
+ return this.device.createRenderPipeline(props);
824
+ }
788
825
  const allProps = { ...import_core4.RenderPipeline.defaultProps, ...props };
826
+ const cache = this._renderPipelineCache;
789
827
  const hash = this._hashRenderPipeline(allProps);
790
- if (!this._renderPipelineCache[hash]) {
791
- const pipeline = this.device.createRenderPipeline({
828
+ let pipeline = (_a = cache[hash]) == null ? void 0 : _a.pipeline;
829
+ if (!pipeline) {
830
+ pipeline = this.device.createRenderPipeline({
792
831
  ...allProps,
793
- id: allProps.id ? `${allProps.id}-cached` : void 0
832
+ id: allProps.id ? `${allProps.id}-cached` : uid("unnamed-cached")
794
833
  });
795
834
  pipeline.hash = hash;
796
- this._renderPipelineCache[hash] = { pipeline, useCount: 0 };
835
+ cache[hash] = { pipeline, useCount: 1 };
836
+ if (this.debug) {
837
+ import_core4.log.warn(`${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
838
+ }
839
+ } else {
840
+ cache[hash].useCount++;
841
+ if (this.debug) {
842
+ import_core4.log.warn(`${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
843
+ }
797
844
  }
798
- this._renderPipelineCache[hash].useCount++;
799
- return this._renderPipelineCache[hash].pipeline;
845
+ return pipeline;
800
846
  }
847
+ /** Return a ComputePipeline matching supplied props. Reuses an equivalent pipeline if already created. */
801
848
  createComputePipeline(props) {
849
+ var _a;
850
+ if (!this.cachingEnabled) {
851
+ return this.device.createComputePipeline(props);
852
+ }
802
853
  const allProps = { ...import_core4.ComputePipeline.defaultProps, ...props };
854
+ const cache = this._computePipelineCache;
803
855
  const hash = this._hashComputePipeline(allProps);
804
- if (!this._computePipelineCache[hash]) {
805
- const pipeline = this.device.createComputePipeline({
856
+ let pipeline = (_a = cache[hash]) == null ? void 0 : _a.pipeline;
857
+ if (!pipeline) {
858
+ pipeline = this.device.createComputePipeline({
806
859
  ...allProps,
807
860
  id: allProps.id ? `${allProps.id}-cached` : void 0
808
861
  });
809
862
  pipeline.hash = hash;
810
- this._computePipelineCache[hash] = { pipeline, useCount: 0 };
863
+ cache[hash] = { pipeline, useCount: 1 };
864
+ if (this.debug) {
865
+ import_core4.log.warn(`${this}: ${pipeline} created, count=${cache[hash].useCount}`)();
866
+ }
867
+ } else {
868
+ cache[hash].useCount++;
869
+ if (this.debug) {
870
+ import_core4.log.warn(`${this}: ${cache[hash].pipeline} reused, count=${cache[hash].useCount}, (id=${props.id})`)();
871
+ }
811
872
  }
812
- this._computePipelineCache[hash].useCount++;
813
- return this._computePipelineCache[hash].pipeline;
873
+ return pipeline;
814
874
  }
815
875
  release(pipeline) {
876
+ if (!this.cachingEnabled) {
877
+ pipeline.destroy();
878
+ return;
879
+ }
880
+ const cache = this._getCache(pipeline);
816
881
  const hash = pipeline.hash;
817
- const cache = pipeline instanceof import_core4.ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
818
882
  cache[hash].useCount--;
819
883
  if (cache[hash].useCount === 0) {
820
- if (this.destroyPolicy === "unused") {
821
- cache[hash].pipeline.destroy();
822
- delete cache[hash];
884
+ this._destroyPipeline(pipeline);
885
+ if (this.debug) {
886
+ import_core4.log.warn(`${this}: ${pipeline} released and destroyed`)();
823
887
  }
888
+ } else if (cache[hash].useCount < 0) {
889
+ import_core4.log.error(`${this}: ${pipeline} released, useCount < 0, resetting`)();
890
+ cache[hash].useCount = 0;
891
+ } else if (this.debug) {
892
+ import_core4.log.warn(`${this}: ${pipeline} released, count=${cache[hash].useCount}`)();
824
893
  }
825
894
  }
826
895
  // PRIVATE
896
+ /** Destroy a cached pipeline, removing it from the cache (depending on destroy policy) */
897
+ _destroyPipeline(pipeline) {
898
+ const cache = this._getCache(pipeline);
899
+ switch (this.destroyPolicy) {
900
+ case "never":
901
+ return false;
902
+ case "unused":
903
+ delete cache[pipeline.hash];
904
+ pipeline.destroy();
905
+ return true;
906
+ }
907
+ }
908
+ /** Get the appropriate cache for the type of pipeline */
909
+ _getCache(pipeline) {
910
+ let cache;
911
+ if (pipeline instanceof import_core4.ComputePipeline) {
912
+ cache = this._computePipelineCache;
913
+ }
914
+ if (pipeline instanceof import_core4.RenderPipeline) {
915
+ cache = this._renderPipelineCache;
916
+ }
917
+ if (!cache) {
918
+ throw new Error(`${this}`);
919
+ }
920
+ if (!cache[pipeline.hash]) {
921
+ throw new Error(`${this}: ${pipeline} matched incorrect entry`);
922
+ }
923
+ return cache;
924
+ }
925
+ /** Calculate a hash based on all the inputs for a compute pipeline */
827
926
  _hashComputePipeline(props) {
927
+ const { type } = this.device;
828
928
  const shaderHash = this._getHash(props.shader.source);
829
- return `${shaderHash}`;
929
+ return `${type}/C/${shaderHash}`;
830
930
  }
831
931
  /** Calculate a hash based on all the inputs for a render pipeline */
832
932
  _hashRenderPipeline(props) {
@@ -834,12 +934,14 @@ var _PipelineFactory = class {
834
934
  const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
835
935
  const varyingHash = "-";
836
936
  const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
837
- switch (this.device.type) {
937
+ const { type } = this.device;
938
+ switch (type) {
838
939
  case "webgl":
839
- return `${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
940
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
941
+ case "webgpu":
840
942
  default:
841
943
  const parameterHash = this._getHash(JSON.stringify(props.parameters));
842
- return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
944
+ return `${type}/R/${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
843
945
  }
844
946
  }
845
947
  _getHash(key) {
@@ -852,7 +954,7 @@ var _PipelineFactory = class {
852
954
  var PipelineFactory = _PipelineFactory;
853
955
  __publicField(PipelineFactory, "defaultProps", { ...import_core4.RenderPipeline.defaultProps });
854
956
 
855
- // dist/lib/shader-factory.js
957
+ // dist/factories/shader-factory.js
856
958
  var import_core5 = require("@luma.gl/core");
857
959
  var _ShaderFactory = class {
858
960
  /** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
@@ -861,15 +963,28 @@ var _ShaderFactory = class {
861
963
  return device._lumaData.defaultShaderFactory;
862
964
  }
863
965
  device;
966
+ cachingEnabled;
864
967
  destroyPolicy;
968
+ debug;
865
969
  _cache = {};
970
+ get [Symbol.toStringTag]() {
971
+ return "ShaderFactory";
972
+ }
973
+ toString() {
974
+ return `${this[Symbol.toStringTag]}(${this.device.id})`;
975
+ }
866
976
  /** @internal */
867
977
  constructor(device) {
868
978
  this.device = device;
869
- this.destroyPolicy = device.props._factoryDestroyPolicy;
979
+ this.cachingEnabled = device.props._cacheShaders;
980
+ this.destroyPolicy = device.props._cacheDestroyPolicy;
981
+ this.debug = true;
870
982
  }
871
983
  /** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
872
984
  createShader(props) {
985
+ if (!this.cachingEnabled) {
986
+ return this.device.createShader(props);
987
+ }
873
988
  const key = this._hashShader(props);
874
989
  let cacheEntry = this._cache[key];
875
990
  if (!cacheEntry) {
@@ -877,13 +992,24 @@ var _ShaderFactory = class {
877
992
  ...props,
878
993
  id: props.id ? `${props.id}-cached` : void 0
879
994
  });
880
- this._cache[key] = cacheEntry = { shader, useCount: 0 };
995
+ this._cache[key] = cacheEntry = { shader, useCount: 1 };
996
+ if (this.debug) {
997
+ import_core5.log.warn(`${this}: Created new shader ${shader.id}`)();
998
+ }
999
+ } else {
1000
+ cacheEntry.useCount++;
1001
+ if (this.debug) {
1002
+ import_core5.log.warn(`${this}: Reusing shader ${cacheEntry.shader.id} count=${cacheEntry.useCount}`)();
1003
+ }
881
1004
  }
882
- cacheEntry.useCount++;
883
1005
  return cacheEntry.shader;
884
1006
  }
885
1007
  /** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
886
1008
  release(shader) {
1009
+ if (!this.cachingEnabled) {
1010
+ shader.destroy();
1011
+ return;
1012
+ }
887
1013
  const key = this._hashShader(shader);
888
1014
  const cacheEntry = this._cache[key];
889
1015
  if (cacheEntry) {
@@ -892,7 +1018,14 @@ var _ShaderFactory = class {
892
1018
  if (this.destroyPolicy === "unused") {
893
1019
  delete this._cache[key];
894
1020
  cacheEntry.shader.destroy();
1021
+ if (this.debug) {
1022
+ import_core5.log.warn(`${this}: Releasing shader ${shader.id}, destroyed`)();
1023
+ }
895
1024
  }
1025
+ } else if (cacheEntry.useCount < 0) {
1026
+ throw new Error(`ShaderFactory: Shader ${shader.id} released too many times`);
1027
+ } else if (this.debug) {
1028
+ import_core5.log.warn(`${this}: Releasing shader ${shader.id} count=${cacheEntry.useCount}`)();
896
1029
  }
897
1030
  }
898
1031
  }
@@ -920,7 +1053,7 @@ function getDebugTableForShaderLayout(layout, name) {
920
1053
  }
921
1054
  for (const varyingDeclaration of layout.varyings || []) {
922
1055
  const glslDeclaration = `${varyingDeclaration.location} ${varyingDeclaration.name}`;
923
- table[`out ${glslDeclaration}`] = { [header]: JSON.stringify(varyingDeclaration.accessor) };
1056
+ table[`out ${glslDeclaration}`] = { [header]: JSON.stringify(varyingDeclaration) };
924
1057
  }
925
1058
  return table;
926
1059
  }
@@ -937,7 +1070,7 @@ function debugFramebuffer(fbo, { id, minimap, opaque, top = "0", left = "0", rgb
937
1070
  canvas.style.position = "absolute";
938
1071
  canvas.style.top = top;
939
1072
  canvas.style.left = left;
940
- canvas.style.border = "blue 1px solid";
1073
+ canvas.style.border = "blue 5px solid";
941
1074
  canvas.style.transform = "scaleY(-1)";
942
1075
  document.body.appendChild(canvas);
943
1076
  ctx = canvas.getContext("2d");
@@ -1003,10 +1136,14 @@ function deepEqual(a, b, depth) {
1003
1136
  return false;
1004
1137
  }
1005
1138
 
1139
+ // dist/shader-inputs.js
1140
+ var import_core6 = require("@luma.gl/core");
1141
+ var import_shadertools = require("@luma.gl/shadertools");
1142
+
1006
1143
  // dist/model/split-uniforms-and-bindings.js
1007
1144
  var import_types = require("@math.gl/types");
1008
1145
  function isUniformValue(value) {
1009
- return (0, import_types.isNumericArray)(value) !== null || typeof value === "number" || typeof value === "boolean";
1146
+ return (0, import_types.isNumericArray)(value) || typeof value === "number" || typeof value === "boolean";
1010
1147
  }
1011
1148
  function splitUniformsAndBindings(uniforms) {
1012
1149
  const result = { bindings: {}, uniforms: {} };
@@ -1022,8 +1159,6 @@ function splitUniformsAndBindings(uniforms) {
1022
1159
  }
1023
1160
 
1024
1161
  // dist/shader-inputs.js
1025
- var import_core6 = require("@luma.gl/core");
1026
- var import_shadertools = require("@luma.gl/shadertools");
1027
1162
  var ShaderInputs = class {
1028
1163
  /**
1029
1164
  * The map of modules
@@ -1052,9 +1187,10 @@ var ShaderInputs = class {
1052
1187
  this.moduleUniforms = {};
1053
1188
  this.moduleBindings = {};
1054
1189
  for (const [name, module2] of Object.entries(modules)) {
1055
- const moduleName = name;
1056
- this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
1057
- this.moduleBindings[moduleName] = {};
1190
+ this._addModule(module2);
1191
+ if (module2.name && name !== module2.name) {
1192
+ import_core6.log.warn(`Module name: ${name} vs ${module2.name}`)();
1193
+ }
1058
1194
  }
1059
1195
  }
1060
1196
  /** Destroy */
@@ -1075,17 +1211,12 @@ var ShaderInputs = class {
1075
1211
  }
1076
1212
  const oldUniforms = this.moduleUniforms[moduleName];
1077
1213
  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 };
1214
+ const uniformsAndBindings = ((_a = module2.getUniforms) == null ? void 0 : _a.call(module2, moduleProps, oldUniforms)) || moduleProps;
1080
1215
  const { uniforms, bindings } = splitUniformsAndBindings(uniformsAndBindings);
1081
1216
  this.moduleUniforms[moduleName] = { ...oldUniforms, ...uniforms };
1082
1217
  this.moduleBindings[moduleName] = { ...oldBindings, ...bindings };
1083
1218
  }
1084
1219
  }
1085
- /** Merges all bindings for the shader (from the various modules) */
1086
- // getUniformBlocks(): Record<string, Texture | Sampler> {
1087
- // return this.moduleUniforms;
1088
- // }
1089
1220
  /**
1090
1221
  * Return the map of modules
1091
1222
  * @todo should should this include the resolved dependencies?
@@ -1098,13 +1229,15 @@ var ShaderInputs = class {
1098
1229
  return this.moduleUniforms;
1099
1230
  }
1100
1231
  /** Merges all bindings for the shader (from the various modules) */
1101
- getBindings() {
1232
+ getBindingValues() {
1102
1233
  const bindings = {};
1103
1234
  for (const moduleBindings of Object.values(this.moduleBindings)) {
1104
1235
  Object.assign(bindings, moduleBindings);
1105
1236
  }
1106
1237
  return bindings;
1107
1238
  }
1239
+ // INTERNAL
1240
+ /** Return a debug table that can be used for console.table() or log.table() */
1108
1241
  getDebugTable() {
1109
1242
  var _a;
1110
1243
  const table = {};
@@ -1118,6 +1251,11 @@ var ShaderInputs = class {
1118
1251
  }
1119
1252
  return table;
1120
1253
  }
1254
+ _addModule(module2) {
1255
+ const moduleName = module2.name;
1256
+ this.moduleUniforms[moduleName] = module2.defaultUniforms || {};
1257
+ this.moduleBindings[moduleName] = {};
1258
+ }
1121
1259
  };
1122
1260
 
1123
1261
  // dist/application-utils/load-file.js
@@ -1130,7 +1268,7 @@ async function loadImageBitmap(url, opts) {
1130
1268
  image.crossOrigin = (opts == null ? void 0 : opts.crossOrigin) || "anonymous";
1131
1269
  image.src = url.startsWith("http") ? url : pathPrefix + url;
1132
1270
  await image.decode();
1133
- return await createImageBitmap(image);
1271
+ return opts ? await createImageBitmap(image, opts) : await createImageBitmap(image);
1134
1272
  }
1135
1273
  async function loadImage(url, opts) {
1136
1274
  return await new Promise((resolve, reject) => {
@@ -1149,6 +1287,7 @@ async function loadImage(url, opts) {
1149
1287
  // dist/async-texture/async-texture.js
1150
1288
  var AsyncTexture = class {
1151
1289
  device;
1290
+ id;
1152
1291
  // TODO - should we type these as possibly `null`? It will make usage harder?
1153
1292
  // @ts-expect-error
1154
1293
  texture;
@@ -1163,8 +1302,15 @@ var AsyncTexture = class {
1163
1302
  };
1164
1303
  rejectReady = () => {
1165
1304
  };
1305
+ get [Symbol.toStringTag]() {
1306
+ return "AsyncTexture";
1307
+ }
1308
+ toString() {
1309
+ return `AsyncTexture:"${this.id}"(${this.isReady ? "ready" : "loading"})`;
1310
+ }
1166
1311
  constructor(device, props) {
1167
1312
  this.device = device;
1313
+ this.id = props.id || uid("async-texture");
1168
1314
  if (typeof (props == null ? void 0 : props.data) === "string" && props.dimension === "2d") {
1169
1315
  props = { ...props, data: loadImageBitmap(props.data) };
1170
1316
  }
@@ -1198,6 +1344,26 @@ var AsyncTexture = class {
1198
1344
  }
1199
1345
  this.destroyed = true;
1200
1346
  }
1347
+ /**
1348
+ * Textures are immutable and cannot be resized after creation,
1349
+ * but we can create a similar texture with the same parameters but a new size.
1350
+ * @note Does not copy contents of the texture
1351
+ * @todo Abort pending promise and create a texture with the new size?
1352
+ */
1353
+ resize(size) {
1354
+ if (!this.isReady) {
1355
+ throw new Error("Cannot resize texture before it is ready");
1356
+ }
1357
+ if (size.width === this.texture.width && size.height === this.texture.height) {
1358
+ return false;
1359
+ }
1360
+ if (this.texture) {
1361
+ const texture = this.texture;
1362
+ this.texture = texture.clone(size);
1363
+ texture.destroy();
1364
+ }
1365
+ return true;
1366
+ }
1201
1367
  };
1202
1368
  async function awaitAllPromises(x) {
1203
1369
  x = await x;
@@ -1280,6 +1446,12 @@ var _Model = class {
1280
1446
  _destroyed = false;
1281
1447
  /** "Time" of last draw. Monotonically increasing timestamp */
1282
1448
  _lastDrawTimestamp = -1;
1449
+ get [Symbol.toStringTag]() {
1450
+ return "Model";
1451
+ }
1452
+ toString() {
1453
+ return `Model(${this.id})`;
1454
+ }
1283
1455
  constructor(device, props) {
1284
1456
  var _a, _b, _c;
1285
1457
  this.props = { ..._Model.defaultProps, ...props };
@@ -1297,22 +1469,22 @@ var _Model = class {
1297
1469
  const isWebGPU = this.device.type === "webgpu";
1298
1470
  if (isWebGPU && this.props.source) {
1299
1471
  this.props.shaderLayout ||= (0, import_shadertools2.getShaderLayoutFromWGSL)(this.props.source);
1300
- const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
1472
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
1301
1473
  platformInfo,
1302
1474
  ...this.props,
1303
1475
  modules
1304
1476
  });
1305
- this.source = source;
1306
- this._getModuleUniforms = getUniforms;
1477
+ this.source = source3;
1478
+ this._getModuleUniforms = getUniforms2;
1307
1479
  } else {
1308
- const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleGLSLShaderPair({
1480
+ const { vs: vs3, fs: fs3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleGLSLShaderPair({
1309
1481
  platformInfo,
1310
1482
  ...this.props,
1311
1483
  modules
1312
1484
  });
1313
- this.vs = vs;
1314
- this.fs = fs;
1315
- this._getModuleUniforms = getUniforms;
1485
+ this.vs = vs3;
1486
+ this.fs = fs3;
1487
+ this._getModuleUniforms = getUniforms2;
1316
1488
  }
1317
1489
  this.vertexCount = this.props.vertexCount;
1318
1490
  this.instanceCount = this.props.instanceCount;
@@ -1326,7 +1498,8 @@ var _Model = class {
1326
1498
  this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
1327
1499
  this.pipeline = this._updatePipeline();
1328
1500
  this.vertexArray = device.createVertexArray({
1329
- renderPipeline: this.pipeline
1501
+ shaderLayout: this.pipeline.shaderLayout,
1502
+ bufferLayout: this.pipeline.bufferLayout
1330
1503
  });
1331
1504
  if (this._gpuGeometry) {
1332
1505
  this._setGeometryAttributes(this._gpuGeometry);
@@ -1353,10 +1526,10 @@ var _Model = class {
1353
1526
  this.setBindings(props.bindings);
1354
1527
  }
1355
1528
  if (props.uniforms) {
1356
- this.setUniforms(props.uniforms);
1529
+ this.setUniformsWebGL(props.uniforms);
1357
1530
  }
1358
1531
  if (props.moduleSettings) {
1359
- this.updateModuleSettings(props.moduleSettings);
1532
+ this.updateModuleSettingsWebGL(props.moduleSettings);
1360
1533
  }
1361
1534
  if (props.transformFeedback) {
1362
1535
  this.transformFeedback = props.transformFeedback;
@@ -1365,16 +1538,16 @@ var _Model = class {
1365
1538
  }
1366
1539
  destroy() {
1367
1540
  var _a;
1368
- if (this._destroyed)
1369
- return;
1370
- this.pipelineFactory.release(this.pipeline);
1371
- this.shaderFactory.release(this.pipeline.vs);
1372
- if (this.pipeline.fs) {
1373
- this.shaderFactory.release(this.pipeline.fs);
1541
+ if (!this._destroyed) {
1542
+ this.pipelineFactory.release(this.pipeline);
1543
+ this.shaderFactory.release(this.pipeline.vs);
1544
+ if (this.pipeline.fs) {
1545
+ this.shaderFactory.release(this.pipeline.fs);
1546
+ }
1547
+ this._uniformStore.destroy();
1548
+ (_a = this._gpuGeometry) == null ? void 0 : _a.destroy();
1549
+ this._destroyed = true;
1374
1550
  }
1375
- this._uniformStore.destroy();
1376
- (_a = this._gpuGeometry) == null ? void 0 : _a.destroy();
1377
- this._destroyed = true;
1378
1551
  }
1379
1552
  // Draw call
1380
1553
  /** Query redraw status. Clears the status. */
@@ -1395,9 +1568,20 @@ var _Model = class {
1395
1568
  this.pipeline = this._updatePipeline();
1396
1569
  }
1397
1570
  draw(renderPass) {
1398
- this.predraw();
1571
+ const loadingBinding = this._areBindingsLoading();
1572
+ if (loadingBinding) {
1573
+ import_core7.log.info(LOG_DRAW_PRIORITY, `>>> DRAWING ABORTED ${this.id}: ${loadingBinding} not loaded`)();
1574
+ return false;
1575
+ }
1576
+ try {
1577
+ renderPass.pushDebugGroup(`${this}.predraw(${renderPass})`);
1578
+ this.predraw();
1579
+ } finally {
1580
+ renderPass.popDebugGroup();
1581
+ }
1399
1582
  let drawSuccess;
1400
1583
  try {
1584
+ renderPass.pushDebugGroup(`${this}.draw(${renderPass})`);
1401
1585
  this._logDrawCallStart();
1402
1586
  this.pipeline = this._updatePipeline();
1403
1587
  const syncBindings = this._getBindings();
@@ -1424,6 +1608,7 @@ var _Model = class {
1424
1608
  topology: this.topology
1425
1609
  });
1426
1610
  } finally {
1611
+ renderPass.popDebugGroup();
1427
1612
  this._logDrawCallEnd();
1428
1613
  }
1429
1614
  this._logFramebuffer(renderPass);
@@ -1447,7 +1632,8 @@ var _Model = class {
1447
1632
  const gpuGeometry = geometry && makeGPUGeometry(this.device, geometry);
1448
1633
  if (gpuGeometry) {
1449
1634
  this.setTopology(gpuGeometry.topology || "triangle-list");
1450
- this.bufferLayout = mergeBufferLayouts(gpuGeometry.bufferLayout, this.bufferLayout);
1635
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1636
+ this.bufferLayout = bufferLayoutHelper.mergeBufferLayouts(gpuGeometry.bufferLayout, this.bufferLayout);
1451
1637
  if (this.vertexArray) {
1452
1638
  this._setGeometryAttributes(gpuGeometry);
1453
1639
  }
@@ -1469,11 +1655,13 @@ var _Model = class {
1469
1655
  * @note Triggers a pipeline rebuild / pipeline cache fetch
1470
1656
  */
1471
1657
  setBufferLayout(bufferLayout) {
1472
- this.bufferLayout = this._gpuGeometry ? mergeBufferLayouts(bufferLayout, this._gpuGeometry.bufferLayout) : bufferLayout;
1658
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1659
+ this.bufferLayout = this._gpuGeometry ? bufferLayoutHelper.mergeBufferLayouts(bufferLayout, this._gpuGeometry.bufferLayout) : bufferLayout;
1473
1660
  this._setPipelineNeedsUpdate("bufferLayout");
1474
1661
  this.pipeline = this._updatePipeline();
1475
1662
  this.vertexArray = this.device.createVertexArray({
1476
- renderPipeline: this.pipeline
1663
+ shaderLayout: this.pipeline.shaderLayout,
1664
+ bufferLayout: this.pipeline.bufferLayout
1477
1665
  });
1478
1666
  if (this._gpuGeometry) {
1479
1667
  this._setGeometryAttributes(this._gpuGeometry);
@@ -1513,17 +1701,19 @@ var _Model = class {
1513
1701
  /** Set the shader inputs */
1514
1702
  setShaderInputs(shaderInputs) {
1515
1703
  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;
1704
+ this._uniformStore = new import_core7.UniformStore(this.shaderInputs.modules);
1705
+ for (const [moduleName, module2] of Object.entries(this.shaderInputs.modules)) {
1706
+ if (shaderModuleHasUniforms(module2)) {
1707
+ const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
1708
+ this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
1709
+ }
1520
1710
  }
1521
1711
  this.setNeedsRedraw("shaderInputs");
1522
1712
  }
1523
1713
  /** Update uniform buffers from the model's shader inputs */
1524
1714
  updateShaderInputs() {
1525
1715
  this._uniformStore.setUniforms(this.shaderInputs.getUniformValues());
1526
- this.setBindings(this.shaderInputs.getBindings());
1716
+ this.setBindings(this.shaderInputs.getBindingValues());
1527
1717
  this.setNeedsRedraw("shaderInputs");
1528
1718
  }
1529
1719
  /**
@@ -1553,16 +1743,20 @@ var _Model = class {
1553
1743
  * @note Overrides any attributes previously set with the same name
1554
1744
  */
1555
1745
  setAttributes(buffers, options) {
1746
+ const disableWarnings = (options == null ? void 0 : options.disableWarnings) ?? this.props.disableWarnings;
1556
1747
  if (buffers.indices) {
1557
- import_core9.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
1748
+ import_core7.log.warn(`Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`)();
1558
1749
  }
1750
+ const bufferLayoutHelper = new import_core7._BufferLayoutHelper(this.bufferLayout);
1559
1751
  for (const [bufferName, buffer] of Object.entries(buffers)) {
1560
- const bufferLayout = this.bufferLayout.find((layout) => getAttributeNames(layout).includes(bufferName));
1752
+ const bufferLayout = bufferLayoutHelper.getBufferLayout(bufferName);
1561
1753
  if (!bufferLayout) {
1562
- import_core9.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
1754
+ if (!disableWarnings) {
1755
+ import_core7.log.warn(`Model(${this.id}): Missing layout for buffer "${bufferName}".`)();
1756
+ }
1563
1757
  continue;
1564
1758
  }
1565
- const attributeNames = getAttributeNames(bufferLayout);
1759
+ const attributeNames = bufferLayoutHelper.getAttributeNamesForBuffer(bufferLayout);
1566
1760
  let set = false;
1567
1761
  for (const attributeName of attributeNames) {
1568
1762
  const attributeInfo = this._attributeInfos[attributeName];
@@ -1571,8 +1765,8 @@ var _Model = class {
1571
1765
  set = true;
1572
1766
  }
1573
1767
  }
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}"`)();
1768
+ if (!set && !disableWarnings) {
1769
+ import_core7.log.warn(`Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`)();
1576
1770
  }
1577
1771
  }
1578
1772
  this.setNeedsRedraw("attributes");
@@ -1591,7 +1785,7 @@ var _Model = class {
1591
1785
  if (attributeInfo) {
1592
1786
  this.vertexArray.setConstantWebGL(attributeInfo.location, value);
1593
1787
  } 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}"`)();
1788
+ import_core7.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${attributeName}"`)();
1595
1789
  }
1596
1790
  }
1597
1791
  this.setNeedsRedraw("constants");
@@ -1602,7 +1796,7 @@ var _Model = class {
1602
1796
  * @deprecated WebGL only, use uniform buffers for portability
1603
1797
  * @param uniforms
1604
1798
  */
1605
- setUniforms(uniforms) {
1799
+ setUniformsWebGL(uniforms) {
1606
1800
  if (!isObjectEmpty(uniforms)) {
1607
1801
  this.pipeline.setUniformsWebGL(uniforms);
1608
1802
  Object.assign(this.uniforms, uniforms);
@@ -1612,25 +1806,35 @@ var _Model = class {
1612
1806
  /**
1613
1807
  * @deprecated Updates shader module settings (which results in uniforms being set)
1614
1808
  */
1615
- updateModuleSettings(props) {
1809
+ updateModuleSettingsWebGL(props) {
1616
1810
  const { bindings, uniforms } = splitUniformsAndBindings(this._getModuleUniforms(props));
1617
1811
  Object.assign(this.bindings, bindings);
1618
1812
  Object.assign(this.uniforms, uniforms);
1619
1813
  this.setNeedsRedraw("moduleSettings");
1620
1814
  }
1621
1815
  // Internal methods
1622
- /** Get texture / texture view from any async textures */
1816
+ /** Check that bindings are loaded. Returns id of first binding that is still loading. */
1817
+ _areBindingsLoading() {
1818
+ for (const binding of Object.values(this.bindings)) {
1819
+ if (binding instanceof AsyncTexture && !binding.isReady) {
1820
+ return binding.id;
1821
+ }
1822
+ }
1823
+ return false;
1824
+ }
1825
+ /** Extracts texture view from loaded async textures. Returns null if any textures have not yet been loaded. */
1623
1826
  _getBindings() {
1624
- return Object.entries(this.bindings).reduce((acc, [name, binding]) => {
1827
+ const validBindings = {};
1828
+ for (const [name, binding] of Object.entries(this.bindings)) {
1625
1829
  if (binding instanceof AsyncTexture) {
1626
1830
  if (binding.isReady) {
1627
- acc[name] = binding.texture;
1831
+ validBindings[name] = binding.texture;
1628
1832
  }
1629
1833
  } else {
1630
- acc[name] = binding;
1834
+ validBindings[name] = binding;
1631
1835
  }
1632
- return acc;
1633
- }, {});
1836
+ }
1837
+ return validBindings;
1634
1838
  }
1635
1839
  /** Get the timestamp of the latest updated bound GPU memory resource (buffer/texture). */
1636
1840
  _getBindingsUpdateTimestamp() {
@@ -1680,26 +1884,26 @@ var _Model = class {
1680
1884
  let prevShaderVs = null;
1681
1885
  let prevShaderFs = null;
1682
1886
  if (this.pipeline) {
1683
- import_core9.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1887
+ import_core7.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1684
1888
  prevShaderVs = this.pipeline.vs;
1685
1889
  prevShaderFs = this.pipeline.fs;
1686
1890
  }
1687
1891
  this._pipelineNeedsUpdate = false;
1688
- const vs = this.shaderFactory.createShader({
1892
+ const vs3 = this.shaderFactory.createShader({
1689
1893
  id: `${this.id}-vertex`,
1690
1894
  stage: "vertex",
1691
1895
  source: this.source || this.vs,
1692
- debug: this.props.debugShaders
1896
+ debugShaders: this.props.debugShaders
1693
1897
  });
1694
- let fs = null;
1898
+ let fs3 = null;
1695
1899
  if (this.source) {
1696
- fs = vs;
1900
+ fs3 = vs3;
1697
1901
  } else if (this.fs) {
1698
- fs = this.shaderFactory.createShader({
1902
+ fs3 = this.shaderFactory.createShader({
1699
1903
  id: `${this.id}-fragment`,
1700
1904
  stage: "fragment",
1701
1905
  source: this.source || this.fs,
1702
- debug: this.props.debugShaders
1906
+ debugShaders: this.props.debugShaders
1703
1907
  });
1704
1908
  }
1705
1909
  this.pipeline = this.pipelineFactory.createRenderPipeline({
@@ -1710,10 +1914,10 @@ var _Model = class {
1710
1914
  // TODO - why set bindings here when we reset them every frame?
1711
1915
  // Should we expose a BindGroup abstraction?
1712
1916
  bindings: this._getBindings(),
1713
- vs,
1714
- fs
1917
+ vs: vs3,
1918
+ fs: fs3
1715
1919
  });
1716
- this._attributeInfos = (0, import_core10.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
1920
+ this._attributeInfos = (0, import_core7.getAttributeInfosFromLayouts)(this.pipeline.shaderLayout, this.bufferLayout);
1717
1921
  if (prevShaderVs)
1718
1922
  this.shaderFactory.release(prevShaderVs);
1719
1923
  if (prevShaderFs)
@@ -1725,35 +1929,35 @@ var _Model = class {
1725
1929
  _lastLogTime = 0;
1726
1930
  _logOpen = false;
1727
1931
  _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) {
1932
+ const logDrawTimeout = import_core7.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT;
1933
+ if (import_core7.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
1730
1934
  return;
1731
1935
  }
1732
1936
  this._lastLogTime = Date.now();
1733
1937
  this._logOpen = true;
1734
- import_core9.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core9.log.level <= 2 })();
1938
+ import_core7.log.group(LOG_DRAW_PRIORITY, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core7.log.level <= 2 })();
1735
1939
  }
1736
1940
  _logDrawCallEnd() {
1737
1941
  if (this._logOpen) {
1738
1942
  const shaderLayoutTable = getDebugTableForShaderLayout(this.pipeline.shaderLayout, this.id);
1739
- import_core9.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
1943
+ import_core7.log.table(LOG_DRAW_PRIORITY, shaderLayoutTable)();
1740
1944
  const uniformTable = this.shaderInputs.getDebugTable();
1741
1945
  for (const [name, value] of Object.entries(this.uniforms)) {
1742
1946
  uniformTable[name] = { value };
1743
1947
  }
1744
- import_core9.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1948
+ import_core7.log.table(LOG_DRAW_PRIORITY, uniformTable)();
1745
1949
  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)();
1950
+ import_core7.log.table(LOG_DRAW_PRIORITY, this._attributeInfos)();
1951
+ import_core7.log.table(LOG_DRAW_PRIORITY, attributeTable)();
1952
+ import_core7.log.groupEnd(LOG_DRAW_PRIORITY)();
1749
1953
  this._logOpen = false;
1750
1954
  }
1751
1955
  }
1752
1956
  _drawCount = 0;
1753
1957
  _logFramebuffer(renderPass) {
1754
- const debugFramebuffers = import_core9.log.get("framebuffer");
1958
+ const debugFramebuffers = this.device.props.debugFramebuffers;
1755
1959
  this._drawCount++;
1756
- if (!debugFramebuffers || this._drawCount++ > 3 && this._drawCount % 60) {
1960
+ if (!debugFramebuffers) {
1757
1961
  return;
1758
1962
  }
1759
1963
  const framebuffer = renderPass.props.framebuffer;
@@ -1784,14 +1988,14 @@ var _Model = class {
1784
1988
  }
1785
1989
  // TODO - fix typing of luma data types
1786
1990
  _getBufferOrConstantValues(attribute, dataType) {
1787
- const TypedArrayConstructor = (0, import_core10.getTypedArrayFromDataType)(dataType);
1991
+ const TypedArrayConstructor = (0, import_core7.getTypedArrayFromDataType)(dataType);
1788
1992
  const typedArray = attribute instanceof import_core7.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
1789
1993
  return typedArray.toString();
1790
1994
  }
1791
1995
  };
1792
1996
  var Model = _Model;
1793
1997
  __publicField(Model, "defaultProps", {
1794
- ...import_core8.RenderPipeline.defaultProps,
1998
+ ...import_core7.RenderPipeline.defaultProps,
1795
1999
  source: void 0,
1796
2000
  vs: null,
1797
2001
  fs: null,
@@ -1817,17 +2021,8 @@ __publicField(Model, "defaultProps", {
1817
2021
  debugShaders: void 0,
1818
2022
  disableWarnings: void 0
1819
2023
  });
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;
2024
+ function shaderModuleHasUniforms(module2) {
2025
+ return Boolean(module2.uniformTypes && !isObjectEmpty(module2.uniformTypes));
1831
2026
  }
1832
2027
  function getPlatformInfo(device) {
1833
2028
  return {
@@ -1839,33 +2034,26 @@ function getPlatformInfo(device) {
1839
2034
  features: device.features
1840
2035
  };
1841
2036
  }
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
2037
  function isObjectEmpty(obj) {
1847
- let isEmpty = true;
1848
2038
  for (const key in obj) {
1849
- isEmpty = false;
1850
- break;
2039
+ return false;
1851
2040
  }
1852
- return isEmpty;
2041
+ return true;
1853
2042
  }
1854
2043
 
1855
- // dist/transform/buffer-transform.js
1856
- var import_core11 = require("@luma.gl/core");
2044
+ // dist/compute/buffer-transform.js
2045
+ var import_core8 = require("@luma.gl/core");
1857
2046
  var import_shadertools3 = require("@luma.gl/shadertools");
1858
- var BufferTransform = class {
2047
+ var _BufferTransform = class {
1859
2048
  device;
1860
2049
  model;
1861
2050
  transformFeedback;
1862
- /** @deprecated Use device feature test. */
1863
2051
  static isSupported(device) {
1864
2052
  var _a;
1865
2053
  return ((_a = device == null ? void 0 : device.info) == null ? void 0 : _a.type) === "webgl";
1866
2054
  }
1867
- constructor(device, props = Model.defaultProps) {
1868
- if (!BufferTransform.isSupported(device)) {
2055
+ constructor(device, props = _BufferTransform.defaultProps) {
2056
+ if (!_BufferTransform.isSupported(device)) {
1869
2057
  throw new Error("BufferTransform not yet implemented on WebGPU");
1870
2058
  }
1871
2059
  this.device = device;
@@ -1873,6 +2061,7 @@ var BufferTransform = class {
1873
2061
  id: props.id || "buffer-transform-model",
1874
2062
  fs: props.fs || (0, import_shadertools3.getPassthroughFS)(),
1875
2063
  topology: props.topology || "point-list",
2064
+ varyings: props.outputs || props.varyings,
1876
2065
  ...props
1877
2066
  });
1878
2067
  this.transformFeedback = this.device.createTransformFeedback({
@@ -1895,32 +2084,42 @@ var BufferTransform = class {
1895
2084
  }
1896
2085
  /** Run one transform loop. */
1897
2086
  run(options) {
2087
+ if (options == null ? void 0 : options.inputBuffers) {
2088
+ this.model.setAttributes(options.inputBuffers);
2089
+ }
2090
+ if (options == null ? void 0 : options.outputBuffers) {
2091
+ this.transformFeedback.setBuffers(options.outputBuffers);
2092
+ }
1898
2093
  const renderPass = this.device.beginRenderPass(options);
1899
2094
  this.model.draw(renderPass);
1900
2095
  renderPass.end();
1901
2096
  }
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. */
2097
+ // DEPRECATED METHODS
2098
+ /** @deprecated App knows what buffers it is passing in - Returns the {@link Buffer} or {@link BufferRange} for given varying name. */
1907
2099
  getBuffer(varyingName) {
1908
2100
  return this.transformFeedback.getBuffer(varyingName);
1909
2101
  }
2102
+ /** @deprecated App knows what buffers it is passing in - Reads the {@link Buffer} or {@link BufferRange} for given varying name. */
1910
2103
  readAsync(varyingName) {
1911
2104
  const result = this.getBuffer(varyingName);
1912
2105
  if (!result) {
1913
2106
  throw new Error("BufferTransform#getBuffer");
1914
2107
  }
1915
- if (result instanceof import_core11.Buffer) {
2108
+ if (result instanceof import_core8.Buffer) {
1916
2109
  return result.readAsync();
1917
2110
  }
1918
2111
  const { buffer, byteOffset = 0, byteLength = buffer.byteLength } = result;
1919
2112
  return buffer.readAsync(byteOffset, byteLength);
1920
2113
  }
1921
2114
  };
2115
+ var BufferTransform = _BufferTransform;
2116
+ __publicField(BufferTransform, "defaultProps", {
2117
+ ...Model.defaultProps,
2118
+ outputs: void 0,
2119
+ feedbackBuffers: void 0
2120
+ });
1922
2121
 
1923
- // dist/transform/texture-transform.js
2122
+ // dist/compute/texture-transform.js
1924
2123
  var import_shadertools4 = require("@luma.gl/shadertools");
1925
2124
  var FS_OUTPUT_VARIABLE = "transform_output";
1926
2125
  var TextureTransform = class {
@@ -1943,7 +2142,7 @@ var TextureTransform = class {
1943
2142
  mipmapFilter: "nearest"
1944
2143
  });
1945
2144
  this.model = new Model(this.device, {
1946
- id: props.id || "texture-transform-model",
2145
+ id: props.id || uid("texture-transform-model"),
1947
2146
  fs: props.fs || (0, import_shadertools4.getPassthroughFS)({
1948
2147
  input: props.targetTextureVarying,
1949
2148
  inputChannels: props.targetTextureChannels,
@@ -1958,6 +2157,11 @@ var TextureTransform = class {
1958
2157
  }
1959
2158
  // Delete owned resources.
1960
2159
  destroy() {
2160
+ var _a;
2161
+ this.model.destroy();
2162
+ for (const binding of this.bindings) {
2163
+ (_a = binding.framebuffer) == null ? void 0 : _a.destroy();
2164
+ }
1961
2165
  }
1962
2166
  /** @deprecated Use {@link destroy}. */
1963
2167
  delete() {
@@ -1969,13 +2173,6 @@ var TextureTransform = class {
1969
2173
  this.model.draw(renderPass);
1970
2174
  renderPass.end();
1971
2175
  }
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
2176
  getTargetTexture() {
1980
2177
  const { targetTexture } = this.bindings[this.currentIndex];
1981
2178
  return targetTexture;
@@ -2111,56 +2308,161 @@ var Geometry = class {
2111
2308
  }
2112
2309
  };
2113
2310
 
2114
- // dist/lib/clip-space.js
2311
+ // dist/models/clip-space.js
2312
+ var CLIPSPACE_VERTEX_SHADER_WGSL = (
2313
+ /* wgsl */
2314
+ `struct VertexInputs {
2315
+ @location(0) clipSpacePosition: vec2<f32>,
2316
+ @location(1) texCoord: vec2<f32>,
2317
+ @location(2) coordinate: vec2<f32>
2318
+ }
2319
+
2320
+ struct FragmentInputs {
2321
+ @builtin(position) Position : vec4<f32>,
2322
+ @location(0) position : vec2<f32>,
2323
+ @location(1) coordinate : vec2<f32>,
2324
+ @location(2) uv : vec2<f32>
2325
+ };
2326
+
2327
+ @vertex
2328
+ fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
2329
+ var outputs: FragmentInputs;
2330
+ outputs.Position = vec4(inputs.clipSpacePosition, 0., 1.);
2331
+ outputs.position = inputs.clipSpacePosition;
2332
+ outputs.coordinate = inputs.coordinate;
2333
+ outputs.uv = inputs.texCoord;
2334
+ return outputs;
2335
+ }
2336
+ `
2337
+ );
2115
2338
  var CLIPSPACE_VERTEX_SHADER = (
2116
2339
  /* glsl */
2117
2340
  `#version 300 es
2118
- in vec2 aClipSpacePosition;
2119
- in vec2 aTexCoord;
2120
- in vec2 aCoordinate;
2341
+ in vec2 clipSpacePosition;
2342
+ in vec2 texCoord;
2343
+ in vec2 coordinate;
2121
2344
 
2122
2345
  out vec2 position;
2123
2346
  out vec2 coordinate;
2124
2347
  out vec2 uv;
2125
2348
 
2126
2349
  void main(void) {
2127
- gl_Position = vec4(aClipSpacePosition, 0., 1.);
2128
- position = aClipSpacePosition;
2129
- coordinate = aCoordinate;
2130
- uv = aTexCoord;
2350
+ gl_Position = vec4(clipSpacePosition, 0., 1.);
2351
+ position = clipSpacePosition;
2352
+ coordinate = coordinate;
2353
+ uv = texCoord;
2131
2354
  }
2132
2355
  `
2133
2356
  );
2134
2357
  var POSITIONS = [-1, -1, 1, -1, -1, 1, 1, 1];
2135
2358
  var ClipSpace = class extends Model {
2136
- constructor(device, opts) {
2359
+ constructor(device, props) {
2137
2360
  const TEX_COORDS = POSITIONS.map((coord) => coord === -1 ? 0 : coord);
2361
+ if (props.source) {
2362
+ props = { ...props, source: `${CLIPSPACE_VERTEX_SHADER_WGSL}
2363
+ ${props.source}` };
2364
+ }
2138
2365
  super(device, {
2139
- ...opts,
2366
+ id: props.id || uid("clip-space"),
2367
+ ...props,
2140
2368
  vs: CLIPSPACE_VERTEX_SHADER,
2141
2369
  vertexCount: 4,
2142
2370
  geometry: new Geometry({
2143
2371
  topology: "triangle-strip",
2144
2372
  vertexCount: 4,
2145
2373
  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) }
2374
+ clipSpacePosition: { size: 2, value: new Float32Array(POSITIONS) },
2375
+ texCoord: { size: 2, value: new Float32Array(TEX_COORDS) },
2376
+ coordinate: { size: 2, value: new Float32Array(TEX_COORDS) }
2149
2377
  }
2150
2378
  })
2151
2379
  });
2152
2380
  }
2153
2381
  };
2154
2382
 
2383
+ // dist/models/billboard-texture-model.js
2384
+ var BACKGROUND_FS_WGSL = (
2385
+ /* wgsl */
2386
+ `@group(0) @binding(0) var backgroundTexture: texture_2d<f32>;
2387
+ @group(0) @binding(1) var backgroundTextureSampler: sampler;
2388
+
2389
+ fn billboardTexture_getTextureUV(coordinates: vec2<f32>) -> vec2<f32> {
2390
+ let iTexSize: vec2<u32> = textureDimensions(backgroundTexture, 0) * 2;
2391
+ let texSize: vec2<f32> = vec2<f32>(f32(iTexSize.x), f32(iTexSize.y));
2392
+ var position: vec2<f32> = coordinates.xy / texSize;
2393
+ return position;
2394
+ }
2395
+
2396
+ @fragment
2397
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
2398
+ let position: vec2<f32> = billboardTexture_getTextureUV(inputs.coordinate);
2399
+ return textureSample(backgroundTexture, backgroundTextureSampler, position);
2400
+ }
2401
+ `
2402
+ );
2403
+ var BACKGROUND_FS = (
2404
+ /* glsl */
2405
+ `#version 300 es
2406
+ precision highp float;
2407
+
2408
+ uniform sampler2D backgroundTexture;
2409
+ out vec4 fragColor;
2410
+
2411
+ vec2 billboardTexture_getTextureUV() {
2412
+ ivec2 iTexSize = textureDimensions(backgroundTexture, 0) * 2;
2413
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
2414
+ vec2 position = gl_FragCoord.xy / texSize;
2415
+ return position;
2416
+ }
2417
+
2418
+ void main(void) {
2419
+ vec2 position = billboardTexture_getTextureUV();
2420
+ fragColor = texture(backgroundTexture, position);
2421
+ }
2422
+ `
2423
+ );
2424
+ var BackgroundTextureModel = class extends ClipSpace {
2425
+ constructor(device, props) {
2426
+ super(device, {
2427
+ id: props.id || "background-texture-model",
2428
+ source: BACKGROUND_FS_WGSL,
2429
+ fs: BACKGROUND_FS,
2430
+ parameters: {
2431
+ depthWriteEnabled: false,
2432
+ depthCompare: "always",
2433
+ ...props.blend ? {
2434
+ blend: true,
2435
+ blendColorOperation: "add",
2436
+ blendAlphaOperation: "add",
2437
+ blendColorSrcFactor: "one",
2438
+ blendColorDstFactor: "one-minus-src-color",
2439
+ blendAlphaSrcFactor: "one",
2440
+ blendAlphaDstFactor: "one-minus-src-alpha"
2441
+ } : {}
2442
+ }
2443
+ });
2444
+ this.setTexture(props.backgroundTexture);
2445
+ }
2446
+ setTexture(backgroundTexture) {
2447
+ this.setBindings({
2448
+ backgroundTexture
2449
+ });
2450
+ }
2451
+ predraw() {
2452
+ this.shaderInputs.setProps({});
2453
+ super.predraw();
2454
+ }
2455
+ };
2456
+
2155
2457
  // dist/scenegraph/scenegraph-node.js
2156
- var import_core12 = require("@math.gl/core");
2458
+ var import_core9 = require("@math.gl/core");
2157
2459
  var ScenegraphNode = class {
2158
2460
  id;
2159
- matrix = new import_core12.Matrix4();
2461
+ matrix = new import_core9.Matrix4();
2160
2462
  display = true;
2161
- position = new import_core12.Vector3();
2162
- rotation = new import_core12.Vector3();
2163
- scale = new import_core12.Vector3(1, 1, 1);
2463
+ position = new import_core9.Vector3();
2464
+ rotation = new import_core9.Vector3();
2465
+ scale = new import_core9.Vector3(1, 1, 1);
2164
2466
  userData = {};
2165
2467
  props = {};
2166
2468
  constructor(props = {}) {
@@ -2245,7 +2547,7 @@ var ScenegraphNode = class {
2245
2547
  }
2246
2548
  getCoordinateUniforms(viewMatrix, modelMatrix) {
2247
2549
  modelMatrix = modelMatrix || this.matrix;
2248
- const worldMatrix = new import_core12.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2550
+ const worldMatrix = new import_core9.Matrix4(viewMatrix).multiplyRight(modelMatrix);
2249
2551
  const worldInverse = worldMatrix.invert();
2250
2552
  const worldInverseTranspose = worldInverse.transpose();
2251
2553
  return {
@@ -2297,14 +2599,14 @@ var ScenegraphNode = class {
2297
2599
  };
2298
2600
 
2299
2601
  // dist/scenegraph/group-node.js
2300
- var import_core13 = require("@math.gl/core");
2301
- var import_core14 = require("@luma.gl/core");
2602
+ var import_core10 = require("@math.gl/core");
2603
+ var import_core11 = require("@luma.gl/core");
2302
2604
  var GroupNode = class extends ScenegraphNode {
2303
2605
  children;
2304
2606
  constructor(props = {}) {
2305
2607
  props = Array.isArray(props) ? { children: props } : props;
2306
2608
  const { children = [] } = props;
2307
- import_core14.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2609
+ import_core11.log.assert(children.every((child) => child instanceof ScenegraphNode), "every child must an instance of ScenegraphNode");
2308
2610
  super(props);
2309
2611
  this.children = children;
2310
2612
  }
@@ -2319,12 +2621,12 @@ var GroupNode = class extends ScenegraphNode {
2319
2621
  return;
2320
2622
  }
2321
2623
  const [min, max] = bounds;
2322
- const center = new import_core13.Vector3(min).add(max).divide([2, 2, 2]);
2624
+ const center = new import_core10.Vector3(min).add(max).divide([2, 2, 2]);
2323
2625
  worldMatrix.transformAsPoint(center, center);
2324
- const halfSize = new import_core13.Vector3(max).subtract(min).divide([2, 2, 2]);
2626
+ const halfSize = new import_core10.Vector3(max).subtract(min).divide([2, 2, 2]);
2325
2627
  worldMatrix.transformAsVector(halfSize, halfSize);
2326
2628
  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);
2629
+ const position = new import_core10.Vector3(v & 1 ? -1 : 1, v & 2 ? -1 : 1, v & 4 ? -1 : 1).multiply(halfSize).add(center);
2328
2630
  for (let i = 0; i < 3; i++) {
2329
2631
  result[0][i] = Math.min(result[0][i], position[i]);
2330
2632
  result[1][i] = Math.max(result[1][i], position[i]);
@@ -2364,8 +2666,8 @@ var GroupNode = class extends ScenegraphNode {
2364
2666
  this.children = [];
2365
2667
  return this;
2366
2668
  }
2367
- traverse(visitor, { worldMatrix = new import_core13.Matrix4() } = {}) {
2368
- const modelMatrix = new import_core13.Matrix4(worldMatrix).multiplyRight(this.matrix);
2669
+ traverse(visitor, { worldMatrix = new import_core10.Matrix4() } = {}) {
2670
+ const modelMatrix = new import_core10.Matrix4(worldMatrix).multiplyRight(this.matrix);
2369
2671
  for (const child of this.children) {
2370
2672
  if (child instanceof GroupNode) {
2371
2673
  child.traverse(visitor, { worldMatrix: modelMatrix });
@@ -3147,7 +3449,7 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
3147
3449
  };
3148
3450
 
3149
3451
  // dist/geometries/ico-sphere-geometry.js
3150
- var import_core15 = require("@math.gl/core");
3452
+ var import_core12 = require("@math.gl/core");
3151
3453
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
3152
3454
  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
3455
  var IcoSphereGeometry = class extends Geometry {
@@ -3245,7 +3547,7 @@ function tesselateIcosaHedron(props) {
3245
3547
  const u3 = 1 - phi3 / PI2;
3246
3548
  const vec1 = [x3 - x2, y3 - y2, z3 - z2];
3247
3549
  const vec2 = [x1 - x2, y1 - y2, z1 - z2];
3248
- const normal = new import_core15.Vector3(vec1).cross(vec2).normalize();
3550
+ const normal = new import_core12.Vector3(vec1).cross(vec2).normalize();
3249
3551
  let newIndex;
3250
3552
  if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
3251
3553
  positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
@@ -3505,11 +3807,377 @@ function fract(n) {
3505
3807
  return n - Math.floor(n);
3506
3808
  }
3507
3809
 
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");
3810
+ // dist/passes/shader-pass-renderer.js
3512
3811
  var import_shadertools5 = require("@luma.gl/shadertools");
3812
+
3813
+ // dist/compute/swap.js
3814
+ var import_core13 = require("@luma.gl/core");
3815
+ var Swap = class {
3816
+ /** The current resource - usually the source for renders or computations */
3817
+ current;
3818
+ /** The next resource - usually the target/destination for transforms / computations */
3819
+ next;
3820
+ constructor(props) {
3821
+ this.current = props.current;
3822
+ this.next = props.next;
3823
+ }
3824
+ /** Destroys the two managed resources */
3825
+ destroy() {
3826
+ var _a, _b;
3827
+ (_a = this.current) == null ? void 0 : _a.destroy();
3828
+ (_b = this.next) == null ? void 0 : _b.destroy();
3829
+ }
3830
+ /** Make the next resource into the current resource, and reuse the current resource as the next resource */
3831
+ swap() {
3832
+ const current = this.current;
3833
+ this.current = this.next;
3834
+ this.next = current;
3835
+ }
3836
+ };
3837
+ var SwapFramebuffers = class extends Swap {
3838
+ constructor(device, props) {
3839
+ var _a, _b;
3840
+ props = { ...props };
3841
+ let colorAttachments = (_a = props.colorAttachments) == null ? void 0 : _a.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
3842
+ format: colorAttachment,
3843
+ usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
3844
+ }));
3845
+ const current = device.createFramebuffer({ ...props, colorAttachments });
3846
+ colorAttachments = (_b = props.colorAttachments) == null ? void 0 : _b.map((colorAttachment) => typeof colorAttachment !== "string" ? colorAttachment : device.createTexture({
3847
+ format: colorAttachment,
3848
+ usage: import_core13.Texture.COPY_DST | import_core13.Texture.RENDER_ATTACHMENT
3849
+ }));
3850
+ const next = device.createFramebuffer({ ...props, colorAttachments });
3851
+ super({ current, next });
3852
+ }
3853
+ /**
3854
+ * Resizes the Framebuffers.
3855
+ * @returns true if the size changed, otherwise exiting framebuffers were preserved
3856
+ * @note any contents are not preserved!
3857
+ */
3858
+ resize(size) {
3859
+ if (size.width === this.current.width && size.height === this.current.height) {
3860
+ return false;
3861
+ }
3862
+ const { current, next } = this;
3863
+ this.current = current.clone(size);
3864
+ current.destroy();
3865
+ this.next = next.clone(size);
3866
+ next.destroy();
3867
+ return true;
3868
+ }
3869
+ };
3870
+ var SwapBuffers = class extends Swap {
3871
+ constructor(device, props) {
3872
+ super({ current: device.createBuffer(props), next: device.createBuffer(props) });
3873
+ }
3874
+ /**
3875
+ * Resizes the Buffers.
3876
+ * @returns true if the size changed, otherwise exiting buffers were preserved.
3877
+ * @note any contents are not preserved!
3878
+ */
3879
+ resize(props) {
3880
+ if (props.byteLength === this.current.byteLength) {
3881
+ return false;
3882
+ }
3883
+ const { current, next } = this;
3884
+ this.current = current.clone(props);
3885
+ current.destroy();
3886
+ this.next = next.clone(props);
3887
+ next.destroy();
3888
+ return true;
3889
+ }
3890
+ };
3891
+
3892
+ // dist/passes/get-fragment-shader.js
3893
+ function getFragmentShaderForRenderPass(options) {
3894
+ const { shaderPass, action, shadingLanguage } = options;
3895
+ switch (action) {
3896
+ case "filter":
3897
+ const filterFunc = `${shaderPass.name}_filterColor_ext`;
3898
+ return shadingLanguage === "wgsl" ? getFilterShaderWGSL(filterFunc) : getFilterShaderGLSL(filterFunc);
3899
+ case "sample":
3900
+ const samplerFunc = `${shaderPass.name}_sampleColor`;
3901
+ return shadingLanguage === "wgsl" ? getSamplerShaderWGSL(samplerFunc) : getSamplerShaderGLSL(samplerFunc);
3902
+ default:
3903
+ throw new Error(`${shaderPass.name} no fragment shader generated for shader pass`);
3904
+ }
3905
+ }
3906
+ function getFilterShaderWGSL(func) {
3907
+ return (
3908
+ /* wgsl */
3909
+ `// Binding 0:1 is reserved for shader passes
3910
+ @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
3911
+ @group(0) @binding(1) var texture: texture_2d<f32>;
3912
+ @group(0) @binding(2) var sampler: sampler;
3913
+
3914
+ struct FragmentInputs = {
3915
+ @location(0) fragUV: vec2f,
3916
+ @location(1) fragPosition: vec4f,
3917
+ @location(2) fragCoordinate: vec4f
3918
+ };
3919
+
3920
+ @fragment
3921
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
3922
+ let texSize = textureDimensions(texture, 0);
3923
+ var fragColor = textureSample(texture, sampler, fragUV);
3924
+ fragColor = ${func}(gl_FragColor, texSize, texCoord);
3925
+ return fragColor;
3926
+ }
3927
+ `
3928
+ );
3929
+ }
3930
+ function getSamplerShaderWGSL(func) {
3931
+ return (
3932
+ /* wgsl */
3933
+ `// Binding 0:1 is reserved for shader passes
3934
+ @group(0) @binding(0) var<uniform> brightnessContrast : brightnessContrastUniforms;
3935
+ @group(0) @binding(1) var texture: texture_2d<f32>;
3936
+ @group(0) @binding(2) var sampler: sampler;
3937
+
3938
+ struct FragmentInputs = {
3939
+ @location(0) fragUV: vec2f,
3940
+ @location(1) fragPosition: vec4f,
3941
+ @location(2) fragCoordinate: vec4f
3942
+ };
3943
+
3944
+ @fragment
3945
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
3946
+ let texSize = textureDimensions(texture, 0);
3947
+ var fragColor = textureSample(texture, sampler, fragUV);
3948
+ fragColor = ${func}(gl_FragColor, texSize, texCoord);
3949
+ return fragColor;
3950
+ }
3951
+ `
3952
+ );
3953
+ }
3954
+ function getFilterShaderGLSL(func) {
3955
+ return (
3956
+ /* glsl */
3957
+ `#version 300 es
3958
+
3959
+ uniform sampler2D sourceTexture;
3960
+
3961
+ in vec2 position;
3962
+ in vec2 coordinate;
3963
+ in vec2 uv;
3964
+
3965
+ out vec4 fragColor;
3966
+
3967
+ void main() {
3968
+ vec2 texCoord = coordinate;
3969
+ ivec2 iTexSize = textureSize(sourceTexture, 0);
3970
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
3971
+
3972
+ fragColor = texture(sourceTexture, texCoord);
3973
+ fragColor = ${func}(fragColor, texSize, texCoord);
3974
+ }
3975
+ `
3976
+ );
3977
+ }
3978
+ function getSamplerShaderGLSL(func) {
3979
+ return (
3980
+ /* glsl */
3981
+ `#version 300 es
3982
+
3983
+ uniform sampler2D sourceTexture;
3984
+
3985
+ in vec2 position;
3986
+ in vec2 coordinate;
3987
+ in vec2 uv;
3988
+
3989
+ out vec4 fragColor;
3990
+
3991
+ void main() {
3992
+ vec2 texCoord = coordinate;
3993
+ ivec2 iTexSize = textureSize(sourceTexture, 0);
3994
+ vec2 texSize = vec2(float(iTexSize.x), float(iTexSize.y));
3995
+
3996
+ fragColor = ${func}(sourceTexture, texSize, texCoord);
3997
+ }
3998
+ `
3999
+ );
4000
+ }
4001
+
4002
+ // dist/passes/shader-pass-renderer.js
4003
+ var ShaderPassRenderer = class {
4004
+ device;
4005
+ shaderInputs;
4006
+ passRenderers;
4007
+ swapFramebuffers;
4008
+ /** For rendering to the screen */
4009
+ clipSpace;
4010
+ textureModel;
4011
+ constructor(device, props) {
4012
+ this.device = device;
4013
+ props.shaderPasses.map((shaderPass) => (0, import_shadertools5.initializeShaderModule)(shaderPass));
4014
+ const modules = props.shaderPasses.reduce((object, shaderPass) => ({ ...object, [shaderPass.name]: shaderPass }), {});
4015
+ this.shaderInputs = props.shaderInputs || new ShaderInputs(modules);
4016
+ const size = device.getCanvasContext().getPixelSize();
4017
+ this.swapFramebuffers = new SwapFramebuffers(device, {
4018
+ colorAttachments: ["rgba8unorm"],
4019
+ width: size[0],
4020
+ height: size[1]
4021
+ });
4022
+ this.textureModel = new BackgroundTextureModel(device, {
4023
+ backgroundTexture: this.swapFramebuffers.current.colorAttachments[0].texture
4024
+ });
4025
+ this.clipSpace = new ClipSpace(device, {
4026
+ source: (
4027
+ /* wgsl */
4028
+ ` @group(0) @binding(0) var sourceTexture: texture_2d<f32>;
4029
+ @group(0) @binding(1) var sourceTextureSampler: sampler;
4030
+
4031
+ @fragment
4032
+ fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4<f32> {
4033
+ let texCoord: vec2<f32> = inputs.coordinate;
4034
+ return textureSample(sourceTexture, sourceTextureSampler, texCoord);
4035
+ }
4036
+ `
4037
+ ),
4038
+ fs: (
4039
+ /* glsl */
4040
+ `#version 300 es
4041
+
4042
+ uniform sampler2D sourceTexture;
4043
+ in vec2 uv;
4044
+ in vec2 coordinate;
4045
+ out vec4 fragColor;
4046
+
4047
+ void main() {
4048
+ vec2 texCoord = coordinate;
4049
+ fragColor = texture(sourceTexture, coordinate);
4050
+ }
4051
+ `
4052
+ )
4053
+ });
4054
+ this.passRenderers = props.shaderPasses.map((shaderPass) => new PassRenderer(device, shaderPass));
4055
+ }
4056
+ /** Destroys resources created by this ShaderPassRenderer */
4057
+ destroy() {
4058
+ for (const subPassRenderer of this.passRenderers) {
4059
+ subPassRenderer.destroy();
4060
+ }
4061
+ this.swapFramebuffers.destroy();
4062
+ this.clipSpace.destroy();
4063
+ }
4064
+ resize(width, height) {
4065
+ this.swapFramebuffers.resize({ width, height });
4066
+ }
4067
+ renderToScreen(options) {
4068
+ const outputTexture = this.renderToTexture(options);
4069
+ if (!outputTexture) {
4070
+ return false;
4071
+ }
4072
+ const renderPass = this.device.beginRenderPass({ clearColor: [0, 0, 0, 1], clearDepth: 1 });
4073
+ this.clipSpace.setBindings({ sourceTexture: outputTexture });
4074
+ this.clipSpace.draw(renderPass);
4075
+ renderPass.end();
4076
+ return true;
4077
+ }
4078
+ /** Runs the shaderPasses in sequence on the sourceTexture and returns a texture with the results.
4079
+ * @returns null if the the sourceTexture has not yet been loaded
4080
+ */
4081
+ renderToTexture(options) {
4082
+ const { sourceTexture } = options;
4083
+ if (!sourceTexture.isReady) {
4084
+ return null;
4085
+ }
4086
+ this.textureModel.destroy();
4087
+ this.textureModel = new BackgroundTextureModel(this.device, {
4088
+ backgroundTexture: sourceTexture
4089
+ });
4090
+ const clearTexturePass = this.device.beginRenderPass({
4091
+ framebuffer: this.swapFramebuffers.current,
4092
+ clearColor: [0, 0, 0, 1]
4093
+ });
4094
+ this.textureModel.draw(clearTexturePass);
4095
+ clearTexturePass.end();
4096
+ let first = true;
4097
+ for (const passRenderer of this.passRenderers) {
4098
+ for (const subPassRenderer of passRenderer.subPassRenderers) {
4099
+ if (!first) {
4100
+ this.swapFramebuffers.swap();
4101
+ }
4102
+ first = false;
4103
+ const swapBufferTexture = this.swapFramebuffers.current.colorAttachments[0].texture;
4104
+ const bindings = {
4105
+ sourceTexture: swapBufferTexture
4106
+ // texSize: [sourceTextures.width, sourceTextures.height]
4107
+ };
4108
+ const renderPass = this.device.beginRenderPass({
4109
+ framebuffer: this.swapFramebuffers.next,
4110
+ clearColor: [0, 0, 0, 1],
4111
+ clearDepth: 1
4112
+ });
4113
+ subPassRenderer.render({ renderPass, bindings });
4114
+ renderPass.end();
4115
+ }
4116
+ }
4117
+ this.swapFramebuffers.swap();
4118
+ const outputTexture = this.swapFramebuffers.current.colorAttachments[0].texture;
4119
+ return outputTexture;
4120
+ }
4121
+ };
4122
+ var PassRenderer = class {
4123
+ shaderPass;
4124
+ subPassRenderers;
4125
+ constructor(device, shaderPass, props = {}) {
4126
+ this.shaderPass = shaderPass;
4127
+ const subPasses = shaderPass.passes || [];
4128
+ this.subPassRenderers = subPasses.map((subPass) => {
4129
+ return new SubPassRenderer(device, shaderPass, subPass);
4130
+ });
4131
+ }
4132
+ destroy() {
4133
+ for (const subPassRenderer of this.subPassRenderers) {
4134
+ subPassRenderer.destroy();
4135
+ }
4136
+ }
4137
+ };
4138
+ var SubPassRenderer = class {
4139
+ model;
4140
+ shaderPass;
4141
+ subPass;
4142
+ constructor(device, shaderPass, subPass) {
4143
+ this.shaderPass = shaderPass;
4144
+ this.subPass = subPass;
4145
+ const action = subPass.action || subPass.filter && "filter" || subPass.sampler && "sample" || "filter";
4146
+ const fs3 = getFragmentShaderForRenderPass({
4147
+ shaderPass,
4148
+ action,
4149
+ shadingLanguage: device.info.shadingLanguage
4150
+ });
4151
+ this.model = new ClipSpace(device, {
4152
+ id: `${shaderPass.name}-subpass`,
4153
+ source: fs3,
4154
+ fs: fs3,
4155
+ modules: [shaderPass],
4156
+ parameters: {
4157
+ depthWriteEnabled: false,
4158
+ depthCompare: "always"
4159
+ }
4160
+ });
4161
+ }
4162
+ destroy() {
4163
+ this.model.destroy();
4164
+ }
4165
+ render(options) {
4166
+ const { renderPass, bindings } = options;
4167
+ this.model.shaderInputs.setProps({
4168
+ [this.shaderPass.name]: this.shaderPass.uniforms || {}
4169
+ });
4170
+ this.model.shaderInputs.setProps({
4171
+ [this.shaderPass.name]: this.subPass.uniforms || {}
4172
+ });
4173
+ this.model.setBindings(bindings || {});
4174
+ this.model.draw(renderPass);
4175
+ }
4176
+ };
4177
+
4178
+ // dist/compute/computation.js
4179
+ var import_core14 = require("@luma.gl/core");
4180
+ var import_shadertools6 = require("@luma.gl/shadertools");
3513
4181
  var import_types2 = require("@math.gl/types");
3514
4182
  var LOG_DRAW_PRIORITY2 = 2;
3515
4183
  var LOG_DRAW_TIMEOUT2 = 1e4;
@@ -3549,18 +4217,18 @@ var _Computation = class {
3549
4217
  const moduleMap = Object.fromEntries(((_a = this.props.modules) == null ? void 0 : _a.map((module2) => [module2.name, module2])) || []);
3550
4218
  this.shaderInputs = props.shaderInputs || new ShaderInputs(moduleMap);
3551
4219
  this.setShaderInputs(this.shaderInputs);
3552
- this.props.shaderLayout ||= (0, import_shadertools5.getShaderLayoutFromWGSL)(this.props.source);
4220
+ this.props.shaderLayout ||= (0, import_shadertools6.getShaderLayoutFromWGSL)(this.props.source);
3553
4221
  const platformInfo = getPlatformInfo2(device);
3554
4222
  const modules = (((_b = this.props.modules) == null ? void 0 : _b.length) > 0 ? this.props.modules : (_c = this.shaderInputs) == null ? void 0 : _c.getModules()) || [];
3555
4223
  this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
3556
4224
  this.shaderFactory = props.shaderFactory || ShaderFactory.getDefaultShaderFactory(this.device);
3557
- const { source, getUniforms } = this.props.shaderAssembler.assembleWGSLShader({
4225
+ const { source: source3, getUniforms: getUniforms2 } = this.props.shaderAssembler.assembleWGSLShader({
3558
4226
  platformInfo,
3559
4227
  ...this.props,
3560
4228
  modules
3561
4229
  });
3562
- this.source = source;
3563
- this._getModuleUniforms = getUniforms;
4230
+ this.source = source3;
4231
+ this._getModuleUniforms = getUniforms2;
3564
4232
  this.pipeline = this._updatePipeline();
3565
4233
  if (props.bindings) {
3566
4234
  this.setBindings(props.bindings);
@@ -3607,7 +4275,7 @@ var _Computation = class {
3607
4275
  }
3608
4276
  setShaderInputs(shaderInputs) {
3609
4277
  this.shaderInputs = shaderInputs;
3610
- this._uniformStore = new import_core16.UniformStore(this.shaderInputs.modules);
4278
+ this._uniformStore = new import_core14.UniformStore(this.shaderInputs.modules);
3611
4279
  for (const moduleName of Object.keys(this.shaderInputs.modules)) {
3612
4280
  const uniformBuffer = this._uniformStore.getManagedUniformBuffer(this.device, moduleName);
3613
4281
  this.bindings[`${moduleName}Uniforms`] = uniformBuffer;
@@ -3644,7 +4312,7 @@ var _Computation = class {
3644
4312
  if (this._pipelineNeedsUpdate) {
3645
4313
  let prevShader = null;
3646
4314
  if (this.pipeline) {
3647
- import_core17.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
4315
+ import_core14.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
3648
4316
  prevShader = this.shader;
3649
4317
  }
3650
4318
  this._pipelineNeedsUpdate = false;
@@ -3652,7 +4320,7 @@ var _Computation = class {
3652
4320
  id: `${this.id}-fragment`,
3653
4321
  stage: "compute",
3654
4322
  source: this.source,
3655
- debug: this.props.debugShaders
4323
+ debugShaders: this.props.debugShaders
3656
4324
  });
3657
4325
  this.pipeline = this.pipelineFactory.createComputePipeline({
3658
4326
  ...this.props,
@@ -3668,33 +4336,33 @@ var _Computation = class {
3668
4336
  _lastLogTime = 0;
3669
4337
  _logOpen = false;
3670
4338
  _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) {
4339
+ const logDrawTimeout = import_core14.log.level > 3 ? 0 : LOG_DRAW_TIMEOUT2;
4340
+ if (import_core14.log.level < 2 || Date.now() - this._lastLogTime < logDrawTimeout) {
3673
4341
  return;
3674
4342
  }
3675
4343
  this._lastLogTime = Date.now();
3676
4344
  this._logOpen = true;
3677
- import_core17.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core17.log.level <= 2 })();
4345
+ import_core14.log.group(LOG_DRAW_PRIORITY2, `>>> DRAWING MODEL ${this.id}`, { collapsed: import_core14.log.level <= 2 })();
3678
4346
  }
3679
4347
  _logDrawCallEnd() {
3680
4348
  if (this._logOpen) {
3681
4349
  const uniformTable = this.shaderInputs.getDebugTable();
3682
- import_core17.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
3683
- import_core17.log.groupEnd(LOG_DRAW_PRIORITY2)();
4350
+ import_core14.log.table(LOG_DRAW_PRIORITY2, uniformTable)();
4351
+ import_core14.log.groupEnd(LOG_DRAW_PRIORITY2)();
3684
4352
  this._logOpen = false;
3685
4353
  }
3686
4354
  }
3687
4355
  _drawCount = 0;
3688
4356
  // TODO - fix typing of luma data types
3689
4357
  _getBufferOrConstantValues(attribute, dataType) {
3690
- const TypedArrayConstructor = (0, import_core18.getTypedArrayFromDataType)(dataType);
3691
- const typedArray = attribute instanceof import_core16.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
4358
+ const TypedArrayConstructor = (0, import_core14.getTypedArrayFromDataType)(dataType);
4359
+ const typedArray = attribute instanceof import_core14.Buffer ? new TypedArrayConstructor(attribute.debugData) : attribute;
3692
4360
  return typedArray.toString();
3693
4361
  }
3694
4362
  };
3695
4363
  var Computation = _Computation;
3696
4364
  __publicField(Computation, "defaultProps", {
3697
- ...import_core16.ComputePipeline.defaultProps,
4365
+ ...import_core14.ComputePipeline.defaultProps,
3698
4366
  id: "unnamed",
3699
4367
  handle: void 0,
3700
4368
  userData: {},
@@ -3705,7 +4373,7 @@ __publicField(Computation, "defaultProps", {
3705
4373
  shaderInputs: void 0,
3706
4374
  pipelineFactory: void 0,
3707
4375
  shaderFactory: void 0,
3708
- shaderAssembler: import_shadertools5.ShaderAssembler.getDefaultShaderAssembler(),
4376
+ shaderAssembler: import_shadertools6.ShaderAssembler.getDefaultShaderAssembler(),
3709
4377
  debugShaders: void 0
3710
4378
  });
3711
4379
  function getPlatformInfo2(device) {
@@ -3718,4 +4386,543 @@ function getPlatformInfo2(device) {
3718
4386
  features: device.features
3719
4387
  };
3720
4388
  }
4389
+
4390
+ // dist/modules/picking/picking-uniforms.js
4391
+ var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1];
4392
+ var INVALID_INDEX = -1;
4393
+ var uniformTypes = {
4394
+ isActive: "i32",
4395
+ indexMode: "i32",
4396
+ batchIndex: "i32",
4397
+ isHighlightActive: "i32",
4398
+ highlightedBatchIndex: "i32",
4399
+ highlightedObjectIndex: "i32",
4400
+ highlightColor: "vec4<f32>"
4401
+ };
4402
+ var GLSL_UNIFORMS = (
4403
+ /* glsl */
4404
+ `precision highp float;
4405
+ precision highp int;
4406
+
4407
+ uniform pickingUniforms {
4408
+ int isActive;
4409
+ int indexMode;
4410
+ int batchIndex;
4411
+
4412
+ int isHighlightActive;
4413
+ int highlightedBatchIndex;
4414
+ int highlightedObjectIndex;
4415
+ vec4 highlightColor;
4416
+ } picking;
4417
+ `
4418
+ );
4419
+ var WGSL_UNIFORMS = (
4420
+ /* wgsl */
4421
+ `struct pickingUniforms {
4422
+ isActive: int32;
4423
+ indexMode: int32;
4424
+ batchIndex: int32;
4425
+
4426
+ isHighlightActive: int32;
4427
+ highlightedBatchIndex: int32;
4428
+ highlightedObjectIndex: int32;
4429
+ highlightColor: vec4<f32>;
4430
+ } picking;
4431
+ `
4432
+ );
4433
+ function getUniforms(props = {}, prevUniforms) {
4434
+ const uniforms = { ...prevUniforms };
4435
+ if (props.isActive !== void 0) {
4436
+ uniforms.isActive = Boolean(props.isActive);
4437
+ }
4438
+ switch (props.indexMode) {
4439
+ case "instance":
4440
+ uniforms.indexMode = 0;
4441
+ break;
4442
+ case "custom":
4443
+ uniforms.indexMode = 1;
4444
+ break;
4445
+ case void 0:
4446
+ break;
4447
+ }
4448
+ switch (props.highlightedObjectIndex) {
4449
+ case void 0:
4450
+ break;
4451
+ case null:
4452
+ uniforms.isHighlightActive = false;
4453
+ uniforms.highlightedObjectIndex = INVALID_INDEX;
4454
+ break;
4455
+ default:
4456
+ uniforms.isHighlightActive = true;
4457
+ uniforms.highlightedObjectIndex = props.highlightedObjectIndex;
4458
+ }
4459
+ if (typeof props.highlightedBatchIndex === "number") {
4460
+ uniforms.highlightedBatchIndex = props.highlightedBatchIndex;
4461
+ }
4462
+ if (props.highlightColor) {
4463
+ uniforms.highlightColor = props.highlightColor;
4464
+ }
4465
+ return uniforms;
4466
+ }
4467
+ var pickingUniforms = {
4468
+ props: {},
4469
+ uniforms: {},
4470
+ name: "picking",
4471
+ uniformTypes,
4472
+ defaultUniforms: {
4473
+ isActive: false,
4474
+ indexMode: 0,
4475
+ batchIndex: 0,
4476
+ isHighlightActive: true,
4477
+ highlightedBatchIndex: INVALID_INDEX,
4478
+ highlightedObjectIndex: INVALID_INDEX,
4479
+ highlightColor: DEFAULT_HIGHLIGHT_COLOR
4480
+ },
4481
+ getUniforms
4482
+ };
4483
+
4484
+ // dist/modules/picking/picking-manager.js
4485
+ var _PickingManager = class {
4486
+ device;
4487
+ props;
4488
+ /** Info from latest pick operation */
4489
+ pickInfo = { batchIndex: null, objectIndex: null };
4490
+ /** Framebuffer used for picking */
4491
+ framebuffer = null;
4492
+ constructor(device, props) {
4493
+ this.device = device;
4494
+ this.props = { ..._PickingManager.defaultProps, ...props };
4495
+ }
4496
+ destroy() {
4497
+ var _a;
4498
+ (_a = this.framebuffer) == null ? void 0 : _a.destroy();
4499
+ }
4500
+ // TODO - Ask for a cached framebuffer? a Framebuffer factory?
4501
+ getFramebuffer() {
4502
+ if (!this.framebuffer) {
4503
+ this.framebuffer = this.device.createFramebuffer({
4504
+ colorAttachments: ["rgba8unorm", "rg32sint"],
4505
+ depthStencilAttachment: "depth24plus"
4506
+ });
4507
+ }
4508
+ return this.framebuffer;
4509
+ }
4510
+ /** Clear highlighted / picked object */
4511
+ clearPickState() {
4512
+ this.props.shaderInputs.setProps({ picking: { highlightedObjectIndex: null } });
4513
+ }
4514
+ /** Prepare for rendering picking colors */
4515
+ beginRenderPass() {
4516
+ var _a;
4517
+ const framebuffer = this.getFramebuffer();
4518
+ framebuffer.resize(this.device.getDefaultCanvasContext().getPixelSize());
4519
+ (_a = this.props.shaderInputs) == null ? void 0 : _a.setProps({ picking: { isActive: true } });
4520
+ const pickingPass = this.device.beginRenderPass({
4521
+ framebuffer,
4522
+ clearColors: [new Float32Array([0, 0, 0, 0]), new Int32Array([-1, -1, 0, 0])],
4523
+ clearDepth: 1
4524
+ });
4525
+ return pickingPass;
4526
+ }
4527
+ getPickInfo(mousePosition) {
4528
+ var _a;
4529
+ const framebuffer = this.getFramebuffer();
4530
+ const [pickX, pickY] = this.getPickPosition(mousePosition);
4531
+ const pixelData = this.device.readPixelsToArrayWebGL(framebuffer, {
4532
+ sourceX: pickX,
4533
+ sourceY: pickY,
4534
+ sourceWidth: 1,
4535
+ sourceHeight: 1,
4536
+ sourceAttachment: 1
4537
+ });
4538
+ if (!pixelData) {
4539
+ return null;
4540
+ }
4541
+ const pickInfo = {
4542
+ objectIndex: pixelData[0] === INVALID_INDEX ? null : pixelData[0],
4543
+ batchIndex: pixelData[1] === INVALID_INDEX ? null : pixelData[1]
4544
+ };
4545
+ if (pickInfo.objectIndex !== this.pickInfo.objectIndex || pickInfo.batchIndex !== this.pickInfo.batchIndex) {
4546
+ this.pickInfo = pickInfo;
4547
+ this.props.onObjectPicked(pickInfo);
4548
+ }
4549
+ (_a = this.props.shaderInputs) == null ? void 0 : _a.setProps({
4550
+ picking: {
4551
+ isActive: false,
4552
+ highlightedBatchIndex: pickInfo.batchIndex,
4553
+ highlightedObjectIndex: pickInfo.objectIndex
4554
+ }
4555
+ });
4556
+ return this.pickInfo;
4557
+ }
4558
+ /**
4559
+ * Get pick position in device pixel range
4560
+ * use the center pixel location in device pixel range
4561
+ */
4562
+ getPickPosition(mousePosition) {
4563
+ const devicePixels = this.device.getDefaultCanvasContext().cssToDevicePixels(mousePosition);
4564
+ const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
4565
+ const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
4566
+ return [pickX, pickY];
4567
+ }
4568
+ };
4569
+ var PickingManager = _PickingManager;
4570
+ __publicField(PickingManager, "defaultProps", {
4571
+ shaderInputs: void 0,
4572
+ onObjectPicked: () => {
4573
+ }
4574
+ });
4575
+
4576
+ // dist/modules/picking/index-picking.js
4577
+ var source = (
4578
+ /* wgsl */
4579
+ `${WGSL_UNIFORMS}
4580
+
4581
+ const INDEX_PICKING_MODE_INSTANCE = 0;
4582
+ const INDEX_PICKING_MODE_CUSTOM = 1;
4583
+ const INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4584
+
4585
+ struct indexPickingFragmentInputs = {
4586
+ objectIndex: int32;
4587
+ };
4588
+
4589
+ let indexPickingFragmentInputs: indexPickingFragmentInputs;
4590
+
4591
+ /**
4592
+ * Vertex shaders should call this function to set the object index.
4593
+ * If using instance or vertex mode, argument will be ignored, 0 can be supplied.
4594
+ */
4595
+ fn picking_setObjectIndex(objectIndex: int32) {
4596
+ switch (picking.indexMode) {
4597
+ case INDEX_PICKING_MODE_INSTANCE, default: {
4598
+ picking_objectIndex = instance_index;
4599
+ };
4600
+ case INDEX_PICKING_MODE_CUSTOM: {
4601
+ picking_objectIndex = objectIndex;
4602
+ };
4603
+ }
4604
+ }
4605
+
4606
+ `
4607
+ );
4608
+ var vs = (
4609
+ /* glsl */
4610
+ `${GLSL_UNIFORMS}
4611
+
4612
+ const int INDEX_PICKING_MODE_INSTANCE = 0;
4613
+ const int INDEX_PICKING_MODE_CUSTOM = 1;
4614
+
4615
+ const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4616
+
4617
+ flat out int picking_objectIndex;
4618
+
4619
+ /**
4620
+ * Vertex shaders should call this function to set the object index.
4621
+ * If using instance or vertex mode, argument will be ignored, 0 can be supplied.
4622
+ */
4623
+ void picking_setObjectIndex(int objectIndex) {
4624
+ switch (picking.indexMode) {
4625
+ case INDEX_PICKING_MODE_INSTANCE:
4626
+ picking_objectIndex = gl_InstanceID;
4627
+ break;
4628
+ case INDEX_PICKING_MODE_CUSTOM:
4629
+ picking_objectIndex = objectIndex;
4630
+ break;
4631
+ }
4632
+ }
4633
+ `
4634
+ );
4635
+ var fs = (
4636
+ /* glsl */
4637
+ `${GLSL_UNIFORMS}
4638
+
4639
+ const int INDEX_PICKING_INVALID_INDEX = ${INVALID_INDEX}; // 2^32 - 1
4640
+
4641
+ flat in int picking_objectIndex;
4642
+
4643
+ /**
4644
+ * Check if this vertex is highlighted (part of the selected batch and object)
4645
+ */
4646
+ bool picking_isFragmentHighlighted() {
4647
+ return
4648
+ bool(picking.isHighlightActive) &&
4649
+ picking.highlightedBatchIndex == picking.batchIndex &&
4650
+ picking.highlightedObjectIndex == picking_objectIndex
4651
+ ;
4652
+ }
4653
+
4654
+ /**
4655
+ * Returns highlight color if this item is selected.
4656
+ */
4657
+ vec4 picking_filterHighlightColor(vec4 color) {
4658
+ // If we are still picking, we don't highlight
4659
+ if (bool(picking.isActive)) {
4660
+ return color;
4661
+ }
4662
+
4663
+ // If we are not highlighted, return color as is
4664
+ if (!picking_isFragmentHighlighted()) {
4665
+ return color;
4666
+ }
4667
+
4668
+ // Blend in highlight color based on its alpha value
4669
+ float highLightAlpha = picking.highlightColor.a;
4670
+ float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
4671
+ float highLightRatio = highLightAlpha / blendedAlpha;
4672
+
4673
+ vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
4674
+ return vec4(blendedRGB, blendedAlpha);
4675
+ }
4676
+
4677
+ /*
4678
+ * Returns picking color if picking enabled else unmodified argument.
4679
+ */
4680
+ ivec4 picking_getPickingColor() {
4681
+ // Assumes that colorAttachment0 is rg32int
4682
+ // TODO? - we could render indices into a second color attachment and not mess with fragColor
4683
+ return ivec4(picking_objectIndex, picking.batchIndex, 0u, 0u);
4684
+ }
4685
+
4686
+ vec4 picking_filterPickingColor(vec4 color) {
4687
+ if (bool(picking.isActive)) {
4688
+ if (picking_objectIndex == INDEX_PICKING_INVALID_INDEX) {
4689
+ discard;
4690
+ }
4691
+ }
4692
+ return color;
4693
+ }
4694
+
4695
+ /*
4696
+ * Returns picking color if picking is enabled if not
4697
+ * highlight color if this item is selected, otherwise unmodified argument.
4698
+ */
4699
+ vec4 picking_filterColor(vec4 color) {
4700
+ vec4 outColor = color;
4701
+ outColor = picking_filterHighlightColor(outColor);
4702
+ outColor = picking_filterPickingColor(outColor);
4703
+ return outColor;
4704
+ }
4705
+ `
4706
+ );
4707
+ var picking = {
4708
+ ...pickingUniforms,
4709
+ name: "picking",
4710
+ source,
4711
+ vs,
4712
+ fs
4713
+ };
4714
+
4715
+ // dist/modules/picking/color-picking.js
4716
+ var source2 = (
4717
+ /* wgsl */
4718
+ `${WGSL_UNIFORMS}
4719
+ `
4720
+ );
4721
+ var vs2 = (
4722
+ /* glsl */
4723
+ `${GLSL_UNIFORMS}
4724
+ out vec4 picking_vRGBcolor_Avalid;
4725
+
4726
+ // Normalize unsigned byte color to 0-1 range
4727
+ vec3 picking_normalizeColor(vec3 color) {
4728
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
4729
+ }
4730
+
4731
+ // Normalize unsigned byte color to 0-1 range
4732
+ vec4 picking_normalizeColor(vec4 color) {
4733
+ return picking.useFloatColors > 0.5 ? color : color / 255.0;
4734
+ }
4735
+
4736
+ bool picking_isColorZero(vec3 color) {
4737
+ return dot(color, vec3(1.0)) < 0.00001;
4738
+ }
4739
+
4740
+ bool picking_isColorValid(vec3 color) {
4741
+ return dot(color, vec3(1.0)) > 0.00001;
4742
+ }
4743
+
4744
+ // Check if this vertex is highlighted
4745
+ bool isVertexHighlighted(vec3 vertexColor) {
4746
+ vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor);
4747
+ return
4748
+ bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor));
4749
+ }
4750
+
4751
+ // Set the current picking color
4752
+ void picking_setPickingColor(vec3 pickingColor) {
4753
+ pickingColor = picking_normalizeColor(pickingColor);
4754
+
4755
+ if (bool(picking.isActive)) {
4756
+ // Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable
4757
+ picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor));
4758
+
4759
+ if (!bool(picking.isAttribute)) {
4760
+ // Stores the picking color so that the fragment shader can render it during picking
4761
+ picking_vRGBcolor_Avalid.rgb = pickingColor;
4762
+ }
4763
+ } else {
4764
+ // Do the comparison with selected item color in vertex shader as it should mean fewer compares
4765
+ picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor));
4766
+ }
4767
+ }
4768
+
4769
+ void picking_setObjectIndex(uint objectIndex) {
4770
+ if (bool(picking.isActive)) {
4771
+ uint index = objectIndex;
4772
+ if (picking.indexMode == PICKING_INDEX_MODE_INSTANCE) {
4773
+ index = uint(gl_InstanceID);
4774
+ }
4775
+ picking_vRGBcolor_Avalid.r = float(index % 255) / 255.0;
4776
+ picking_vRGBcolor_Avalid.g = float((index / 255) % 255) / 255.0;
4777
+ picking_vRGBcolor_Avalid.b = float((index / 255 / 255) %255) / 255.0;
4778
+ }
4779
+ }
4780
+
4781
+ void picking_setPickingAttribute(float value) {
4782
+ if (bool(picking.isAttribute)) {
4783
+ picking_vRGBcolor_Avalid.r = value;
4784
+ }
4785
+ }
4786
+
4787
+ void picking_setPickingAttribute(vec2 value) {
4788
+ if (bool(picking.isAttribute)) {
4789
+ picking_vRGBcolor_Avalid.rg = value;
4790
+ }
4791
+ }
4792
+
4793
+ void picking_setPickingAttribute(vec3 value) {
4794
+ if (bool(picking.isAttribute)) {
4795
+ picking_vRGBcolor_Avalid.rgb = value;
4796
+ }
4797
+ }
4798
+ `
4799
+ );
4800
+ var fs2 = (
4801
+ /* glsl */
4802
+ `${GLSL_UNIFORMS}
4803
+
4804
+ in vec4 picking_vRGBcolor_Avalid;
4805
+
4806
+ /*
4807
+ * Returns highlight color if this item is selected.
4808
+ */
4809
+ vec4 picking_filterHighlightColor(vec4 color) {
4810
+ // If we are still picking, we don't highlight
4811
+ if (picking.isActive > 0.5) {
4812
+ return color;
4813
+ }
4814
+
4815
+ bool selected = bool(picking_vRGBcolor_Avalid.a);
4816
+
4817
+ if (selected) {
4818
+ // Blend in highlight color based on its alpha value
4819
+ float highLightAlpha = picking.highlightColor.a;
4820
+ float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha);
4821
+ float highLightRatio = highLightAlpha / blendedAlpha;
4822
+
4823
+ vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio);
4824
+ return vec4(blendedRGB, blendedAlpha);
4825
+ } else {
4826
+ return color;
4827
+ }
4828
+ }
4829
+
4830
+ /*
4831
+ * Returns picking color if picking enabled else unmodified argument.
4832
+ */
4833
+ vec4 picking_filterPickingColor(vec4 color) {
4834
+ if (bool(picking.isActive)) {
4835
+ if (picking_vRGBcolor_Avalid.a == 0.0) {
4836
+ discard;
4837
+ }
4838
+ return picking_vRGBcolor_Avalid;
4839
+ }
4840
+ return color;
4841
+ }
4842
+
4843
+ /*
4844
+ * Returns picking color if picking is enabled if not
4845
+ * highlight color if this item is selected, otherwise unmodified argument.
4846
+ */
4847
+ vec4 picking_filterColor(vec4 color) {
4848
+ vec4 highlightColor = picking_filterHighlightColor(color);
4849
+ return picking_filterPickingColor(highlightColor);
4850
+ }
4851
+ `
4852
+ );
4853
+ var picking2 = {
4854
+ ...pickingUniforms,
4855
+ name: "picking",
4856
+ source: source2,
4857
+ vs: vs2,
4858
+ fs: fs2
4859
+ };
4860
+
4861
+ // dist/modules/picking/legacy-picking-manager.js
4862
+ var LegacyPickingManager = class {
4863
+ device;
4864
+ framebuffer = null;
4865
+ shaderInputs;
4866
+ constructor(device, shaderInputs) {
4867
+ this.device = device;
4868
+ this.shaderInputs = shaderInputs;
4869
+ }
4870
+ destroy() {
4871
+ var _a;
4872
+ (_a = this.framebuffer) == null ? void 0 : _a.destroy();
4873
+ }
4874
+ getFramebuffer() {
4875
+ if (!this.framebuffer) {
4876
+ this.framebuffer = this.device.createFramebuffer({
4877
+ colorAttachments: ["rgba8unorm"],
4878
+ depthStencilAttachment: "depth24plus"
4879
+ });
4880
+ }
4881
+ return this.framebuffer;
4882
+ }
4883
+ /** Clear highlighted / picked object */
4884
+ clearPickState() {
4885
+ this.shaderInputs.setProps({ picking: { highlightedObjectColor: null } });
4886
+ }
4887
+ /** Prepare for rendering picking colors */
4888
+ beginRenderPass() {
4889
+ const framebuffer = this.getFramebuffer();
4890
+ framebuffer.resize(this.device.getCanvasContext().getPixelSize());
4891
+ this.shaderInputs.setProps({ picking: { isActive: true } });
4892
+ const pickingPass = this.device.beginRenderPass({
4893
+ framebuffer,
4894
+ clearColor: [0, 0, 0, 0],
4895
+ clearDepth: 1
4896
+ });
4897
+ return pickingPass;
4898
+ }
4899
+ updatePickState(mousePosition) {
4900
+ const framebuffer = this.getFramebuffer();
4901
+ const [pickX, pickY] = this.getPickPosition(mousePosition);
4902
+ const color255 = this.device.readPixelsToArrayWebGL(framebuffer, {
4903
+ sourceX: pickX,
4904
+ sourceY: pickY,
4905
+ sourceWidth: 1,
4906
+ sourceHeight: 1
4907
+ });
4908
+ let highlightedObjectColor = [...color255].map((x) => x / 255);
4909
+ const isHighlightActive = highlightedObjectColor[0] + highlightedObjectColor[1] + highlightedObjectColor[2] > 0;
4910
+ if (!isHighlightActive) {
4911
+ highlightedObjectColor = null;
4912
+ }
4913
+ this.shaderInputs.setProps({
4914
+ picking: { isActive: false, highlightedObjectColor }
4915
+ });
4916
+ }
4917
+ /**
4918
+ * Get pick position in device pixel range
4919
+ * use the center pixel location in device pixel range
4920
+ */
4921
+ getPickPosition(mousePosition) {
4922
+ const devicePixels = this.device.getCanvasContext().cssToDevicePixels(mousePosition);
4923
+ const pickX = devicePixels.x + Math.floor(devicePixels.width / 2);
4924
+ const pickY = devicePixels.y + Math.floor(devicePixels.height / 2);
4925
+ return [pickX, pickY];
4926
+ }
4927
+ };
3721
4928
  //# sourceMappingURL=index.cjs.map