@luma.gl/engine 9.0.0-alpha.34 → 9.0.0-alpha.36

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 (47) hide show
  1. package/dist/animation/timeline.d.ts +4 -4
  2. package/dist/animation/timeline.d.ts.map +1 -1
  3. package/dist/animation/timeline.js +13 -13
  4. package/dist/animation/timeline.js.map +1 -1
  5. package/dist/animation-loop/animation-loop.d.ts +2 -2
  6. package/dist/animation-loop/animation-loop.d.ts.map +1 -1
  7. package/dist/animation-loop/animation-loop.js +5 -6
  8. package/dist/animation-loop/animation-loop.js.map +1 -1
  9. package/dist/animation-loop/animation-props.d.ts +1 -2
  10. package/dist/animation-loop/animation-props.d.ts.map +1 -1
  11. package/dist/animation-loop/animation-props.js.map +1 -1
  12. package/dist/dist.dev.js +980 -9108
  13. package/dist/index.cjs +269 -130
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/lib/clip-space.d.ts +1 -1
  19. package/dist/lib/clip-space.d.ts.map +1 -1
  20. package/dist/lib/clip-space.js +1 -2
  21. package/dist/lib/clip-space.js.map +1 -1
  22. package/dist/model/model.d.ts +43 -22
  23. package/dist/model/model.d.ts.map +1 -1
  24. package/dist/model/model.js +72 -19
  25. package/dist/model/model.js.map +1 -1
  26. package/dist/scenegraph/scenegraph-node.d.ts +5 -5
  27. package/dist/scenegraph/scenegraph-node.d.ts.map +1 -1
  28. package/dist/scenegraph/scenegraph-node.js.map +1 -1
  29. package/dist/shadertools/shader-module-uniforms.d.ts +36 -0
  30. package/dist/shadertools/shader-module-uniforms.d.ts.map +1 -0
  31. package/dist/shadertools/shader-module-uniforms.js +87 -0
  32. package/dist/shadertools/shader-module-uniforms.js.map +1 -0
  33. package/dist/transform/transform.d.ts +2 -2
  34. package/dist/transform/transform.d.ts.map +1 -1
  35. package/dist/transform/transform.js +0 -18
  36. package/dist/transform/transform.js.map +1 -1
  37. package/dist.min.js +115 -165
  38. package/package.json +5 -6
  39. package/src/animation/timeline.ts +13 -13
  40. package/src/animation-loop/animation-loop.ts +6 -8
  41. package/src/animation-loop/animation-props.ts +1 -2
  42. package/src/index.ts +3 -0
  43. package/src/lib/clip-space.ts +2 -3
  44. package/src/model/model.ts +154 -60
  45. package/src/scenegraph/scenegraph-node.ts +5 -5
  46. package/src/shadertools/shader-module-uniforms.ts +178 -0
  47. package/src/transform/transform.ts +8 -6
package/dist/index.cjs CHANGED
@@ -21,8 +21,8 @@ var __spreadValues = (a, b) => {
21
21
  };
22
22
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
23
  var __export = (target, all) => {
24
- for (var name in all)
25
- __defProp(target, name, { get: all[name], enumerable: true });
24
+ for (var name2 in all)
25
+ __defProp(target, name2, { get: all[name2], enumerable: true });
26
26
  };
27
27
  var __copyProps = (to, from, except, desc) => {
28
28
  if (from && typeof from === "object" || typeof from === "function") {
@@ -72,6 +72,7 @@ __export(src_exports, {
72
72
  PipelineFactory: () => PipelineFactory,
73
73
  PlaneGeometry: () => PlaneGeometry,
74
74
  ScenegraphNode: () => ScenegraphNode,
75
+ ShaderModuleUniforms: () => ShaderModuleUniforms,
75
76
  SphereGeometry: () => SphereGeometry,
76
77
  Timeline: () => Timeline,
77
78
  Transform: () => Transform,
@@ -93,7 +94,7 @@ var Timeline = class {
93
94
  }
94
95
  addChannel(props) {
95
96
  const { delay = 0, duration = Number.POSITIVE_INFINITY, rate = 1, repeat = 1 } = props;
96
- const handle = channelHandles++;
97
+ const channelId = channelHandles++;
97
98
  const channel = {
98
99
  time: 0,
99
100
  delay,
@@ -102,29 +103,29 @@ var Timeline = class {
102
103
  repeat
103
104
  };
104
105
  this._setChannelTime(channel, this.time);
105
- this.channels.set(handle, channel);
106
- return handle;
106
+ this.channels.set(channelId, channel);
107
+ return channelId;
107
108
  }
108
- removeChannel(handle) {
109
- this.channels.delete(handle);
109
+ removeChannel(channelId) {
110
+ this.channels.delete(channelId);
110
111
  for (const [animationHandle, animation] of this.animations) {
111
- if (animation.channel === handle) {
112
+ if (animation.channel === channelId) {
112
113
  this.detachAnimation(animationHandle);
113
114
  }
114
115
  }
115
116
  }
116
- isFinished(handle) {
117
- const channel = this.channels.get(handle);
117
+ isFinished(channelId) {
118
+ const channel = this.channels.get(channelId);
118
119
  if (channel === void 0) {
119
120
  return false;
120
121
  }
121
122
  return this.time >= channel.delay + channel.duration * channel.repeat;
122
123
  }
123
- getTime(handle) {
124
- if (handle === void 0) {
124
+ getTime(channelId) {
125
+ if (channelId === void 0) {
125
126
  return this.time;
126
127
  }
127
- const channel = this.channels.get(handle);
128
+ const channel = this.channels.get(channelId);
128
129
  if (channel === void 0) {
129
130
  return -1;
130
131
  }
@@ -161,8 +162,8 @@ var Timeline = class {
161
162
  animation.setTime(this.getTime(channelHandle));
162
163
  return animationHandle;
163
164
  }
164
- detachAnimation(handle) {
165
- this.animations.delete(handle);
165
+ detachAnimation(channelId) {
166
+ this.animations.delete(channelId);
166
167
  }
167
168
  update(engineTime) {
168
169
  if (this.playing) {
@@ -377,7 +378,7 @@ var AnimationLoop = class {
377
378
  if ((_a = this.device) == null ? void 0 : _a.isLost) {
378
379
  return this;
379
380
  }
380
- this._beginTimers();
381
+ this._beginFrameTimers();
381
382
  this._setupFrame();
382
383
  this._updateAnimationProps();
383
384
  this._renderFrame(this._getAnimationProps());
@@ -387,7 +388,7 @@ var AnimationLoop = class {
387
388
  this._nextFramePromise = null;
388
389
  this._resolveNextFrame = null;
389
390
  }
390
- this._endTimers();
391
+ this._endFrameTimers();
391
392
  return this;
392
393
  }
393
394
  // Stops a render loop if already running, finalizing
@@ -493,7 +494,6 @@ var AnimationLoop = class {
493
494
  animationLoop: this,
494
495
  device: this.device,
495
496
  canvas: (_b = (_a = this.device) == null ? void 0 : _a.canvasContext) == null ? void 0 : _b.canvas,
496
- renderPass: this.device.getDefaultRenderPass(),
497
497
  timeline: this.timeline,
498
498
  // Initial values
499
499
  useDevicePixels: this.props.useDevicePixels,
@@ -524,7 +524,6 @@ var AnimationLoop = class {
524
524
  if (!this.animationProps) {
525
525
  return;
526
526
  }
527
- this.animationProps.renderPass = this.device.getDefaultRenderPass();
528
527
  const { width, height, aspect } = this._getSizeAndAspect();
529
528
  if (width !== this.animationProps.width || height !== this.animationProps.height) {
530
529
  this.setNeedsRedraw("drawing buffer resized");
@@ -607,11 +606,12 @@ var AnimationLoop = class {
607
606
  (_b = (_a = this.device) == null ? void 0 : _a.canvasContext) == null ? void 0 : _b.resize({ useDevicePixels: this.props.useDevicePixels });
608
607
  }
609
608
  }
610
- _beginTimers() {
609
+ _beginFrameTimers() {
611
610
  this.frameRate.timeEnd();
612
611
  this.frameRate.timeStart();
612
+ this.cpuTime.timeStart();
613
613
  }
614
- _endTimers() {
614
+ _endFrameTimers() {
615
615
  this.cpuTime.timeEnd();
616
616
  }
617
617
  // Event handling
@@ -655,6 +655,7 @@ function makeAnimationLoop(AnimationLoopTemplateCtor, props) {
655
655
 
656
656
  // src/model/model.ts
657
657
  var import_core6 = require("@luma.gl/core");
658
+ var import_core7 = require("@luma.gl/core");
658
659
  var import_shadertools = require("@luma.gl/shadertools");
659
660
 
660
661
  // src/geometry/gpu-geometry.ts
@@ -720,20 +721,20 @@ function getAttributeBuffersFromGeometry(device, geometry) {
720
721
  const bufferLayout = [];
721
722
  const attributes = {};
722
723
  for (const [attributeName, attribute] of Object.entries(geometry.attributes)) {
723
- let name = attributeName;
724
+ let name2 = attributeName;
724
725
  switch (attributeName) {
725
726
  case "POSITION":
726
- name = "positions";
727
+ name2 = "positions";
727
728
  break;
728
729
  case "NORMAL":
729
- name = "normals";
730
+ name2 = "normals";
730
731
  break;
731
732
  case "TEXCOORD_0":
732
- name = "texCoords";
733
+ name2 = "texCoords";
733
734
  break;
734
735
  }
735
- attributes[name] = device.createBuffer({ data: attribute.value, id: `${attributeName}-buffer` });
736
- bufferLayout.push({ name, format: `float32x${attribute.size}` });
736
+ attributes[name2] = device.createBuffer({ data: attribute.value, id: `${attributeName}-buffer` });
737
+ bufferLayout.push({ name: name2, format: `float32x${attribute.size}` });
737
738
  }
738
739
  const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
739
740
  return { attributes, bufferLayout, vertexCount };
@@ -822,7 +823,7 @@ var _Model = class {
822
823
  /** instance count */
823
824
  this.instanceCount = 0;
824
825
  /** Index buffer */
825
- this.indices = null;
826
+ this.indexBuffer = null;
826
827
  /** Buffer-valued attributes */
827
828
  this.bufferAttributes = {};
828
829
  /** Constant-valued attributes */
@@ -832,6 +833,7 @@ var _Model = class {
832
833
  /** Sets uniforms @deprecated Use uniform buffers and setBindings() for portability*/
833
834
  this.uniforms = {};
834
835
  this._pipelineNeedsUpdate = "newly created";
836
+ this._attributeInfos = {};
835
837
  this.props = __spreadValues(__spreadValues({}, _Model.defaultProps), props);
836
838
  props = this.props;
837
839
  this.id = props.id || (0, import_core6.uid)("model");
@@ -843,7 +845,10 @@ var _Model = class {
843
845
  gpu: device.info.gpu,
844
846
  features: device.features
845
847
  };
846
- const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleShaders(platformInfo, this.props);
848
+ const { vs, fs, getUniforms } = this.props.shaderAssembler.assembleShaders(
849
+ platformInfo,
850
+ this.props
851
+ );
847
852
  this.vs = vs;
848
853
  this.fs = fs;
849
854
  this._getModuleUniforms = getUniforms;
@@ -852,11 +857,18 @@ var _Model = class {
852
857
  this.topology = this.props.topology;
853
858
  this.bufferLayout = this.props.bufferLayout;
854
859
  this.parameters = this.props.parameters;
860
+ let gpuGeometry;
855
861
  if (props.geometry) {
856
- this.setGeometry(props.geometry);
862
+ gpuGeometry = this.setGeometry(props.geometry);
857
863
  }
858
864
  this.pipelineFactory = props.pipelineFactory || PipelineFactory.getDefaultPipelineFactory(this.device);
859
865
  this.pipeline = this._updatePipeline();
866
+ this.vertexArray = device.createVertexArray({
867
+ renderPipeline: this.pipeline
868
+ });
869
+ if (gpuGeometry) {
870
+ this._setGeometryAttributes(gpuGeometry);
871
+ }
860
872
  if (props.vertexCount) {
861
873
  this.setVertexCount(props.vertexCount);
862
874
  }
@@ -864,11 +876,17 @@ var _Model = class {
864
876
  this.setInstanceCount(props.instanceCount);
865
877
  }
866
878
  if (props.indices) {
867
- this.setIndexBuffer(props.indices);
879
+ throw new Error("Model.props.indices removed. Use props.indexBuffer");
880
+ }
881
+ if (props.indexBuffer) {
882
+ this.setIndexBuffer(props.indexBuffer);
868
883
  }
869
884
  if (props.attributes) {
870
885
  this.setAttributes(props.attributes);
871
886
  }
887
+ if (props.constantAttributes) {
888
+ this.setConstantAttributes(props.constantAttributes);
889
+ }
872
890
  if (props.bindings) {
873
891
  this.setBindings(props.bindings);
874
892
  }
@@ -887,33 +905,42 @@ var _Model = class {
887
905
  // Draw call
888
906
  draw(renderPass) {
889
907
  this.pipeline = this._updatePipeline();
890
- this.pipeline.setIndexBuffer(this.indices);
891
- this.pipeline.setAttributes(this.bufferAttributes);
892
- this.pipeline.setConstantAttributes(this.constantAttributes);
893
908
  this.pipeline.setBindings(this.bindings);
894
909
  this.pipeline.setUniforms(this.uniforms);
895
910
  this.pipeline.draw({
896
911
  renderPass,
912
+ vertexArray: this.vertexArray,
897
913
  vertexCount: this.vertexCount,
898
914
  instanceCount: this.instanceCount
899
915
  });
900
916
  }
901
917
  // Update fixed fields (can trigger pipeline rebuild)
902
- /**
918
+ /**
903
919
  * Updates the optional geometry
904
- * Geometry, sets several attributes, indices, and also vertex count and topology
920
+ * Geometry, set topology and bufferLayout
905
921
  * @note Can trigger a pipeline rebuild / pipeline cache fetch on WebGPU
906
922
  */
907
923
  setGeometry(geometry) {
908
924
  const gpuGeometry = geometry && makeGPUGeometry(this.device, geometry);
909
925
  this.setTopology(gpuGeometry.topology || "triangle-list");
910
926
  this.bufferLayout = mergeBufferLayouts(this.bufferLayout, gpuGeometry.bufferLayout);
927
+ if (this.vertexArray) {
928
+ this._setGeometryAttributes(gpuGeometry);
929
+ }
930
+ return gpuGeometry;
931
+ }
932
+ /**
933
+ * Updates the optional geometry attributes
934
+ * Geometry, sets several attributes, indexBuffer, and also vertex count
935
+ * @note Can trigger a pipeline rebuild / pipeline cache fetch on WebGPU
936
+ */
937
+ _setGeometryAttributes(gpuGeometry) {
911
938
  this.vertexCount = gpuGeometry.vertexCount;
912
939
  this.setAttributes(gpuGeometry.attributes);
913
940
  this.setIndexBuffer(gpuGeometry.indices);
914
941
  }
915
- /**
916
- * Updates the primitive topology ('triangle-list', 'triangle-strip' etc).
942
+ /**
943
+ * Updates the primitive topology ('triangle-list', 'triangle-strip' etc).
917
944
  * @note Triggers a pipeline rebuild / pipeline cache fetch on WebGPU
918
945
  */
919
946
  setTopology(topology) {
@@ -922,8 +949,8 @@ var _Model = class {
922
949
  this._setPipelineNeedsUpdate("topology");
923
950
  }
924
951
  }
925
- /**
926
- * Updates the buffer layout.
952
+ /**
953
+ * Updates the buffer layout.
927
954
  * @note Triggers a pipeline rebuild / pipeline cache fetch on WebGPU
928
955
  */
929
956
  setBufferLayout(bufferLayout) {
@@ -971,61 +998,99 @@ var _Model = class {
971
998
  updateModuleSettings(props) {
972
999
  this.setShaderModuleProps(props);
973
1000
  }
1001
+ /**
1002
+ * Sets bindings (textures, samplers, uniform buffers)
1003
+ */
1004
+ setBindings(bindings) {
1005
+ Object.assign(this.bindings, bindings);
1006
+ }
1007
+ /**
1008
+ * Sets individual uniforms
1009
+ * @deprecated WebGL only, use uniform buffers for portability
1010
+ * @param uniforms
1011
+ * @returns self for chaining
1012
+ */
1013
+ setUniforms(uniforms) {
1014
+ this.pipeline.setUniforms(uniforms);
1015
+ Object.assign(this.uniforms, uniforms);
1016
+ }
974
1017
  /**
975
1018
  * Sets the index buffer
976
1019
  * @todo - how to unset it if we change geometry?
977
1020
  */
978
- setIndexBuffer(indices) {
979
- this.indices = indices;
1021
+ setIndexBuffer(indexBuffer) {
1022
+ this.vertexArray.setIndexBuffer(indexBuffer);
980
1023
  }
981
1024
  /**
982
1025
  * Sets attributes (buffers)
983
1026
  * @note Overrides any attributes previously set with the same name
984
1027
  */
985
- setAttributes(bufferAttributes) {
986
- if (bufferAttributes.indices) {
987
- import_core6.log.warn(`Model:${this.id} setAttributes() - indices should be set using setIndexBuffer()`);
1028
+ setAttributes(buffers) {
1029
+ var _a;
1030
+ if (buffers.indices) {
1031
+ import_core6.log.warn(
1032
+ `Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()`
1033
+ );
1034
+ }
1035
+ for (const [bufferName, buffer] of Object.entries(buffers)) {
1036
+ const bufferLayout = this.bufferLayout.find((layout) => layout.name === bufferName);
1037
+ if (!bufferLayout) {
1038
+ continue;
1039
+ }
1040
+ const attributeNames = bufferLayout.attributes ? (_a = bufferLayout.attributes) == null ? void 0 : _a.map((layout) => layout.attribute) : [bufferLayout.name];
1041
+ let set = false;
1042
+ for (const attributeName of attributeNames) {
1043
+ const attributeInfo = this._attributeInfos[attributeName];
1044
+ if (attributeInfo) {
1045
+ this.vertexArray.setBuffer(attributeInfo.location, buffer);
1046
+ set = true;
1047
+ }
1048
+ }
1049
+ if (!set) {
1050
+ import_core6.log.warn(
1051
+ `Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"`
1052
+ )();
1053
+ }
988
1054
  }
989
- Object.assign(this.bufferAttributes, bufferAttributes);
990
1055
  }
991
1056
  /**
992
1057
  * Sets constant attributes
993
1058
  * @note Overrides any attributes previously set with the same name
1059
+ * Constant attributes are only supported in WebGL, not in WebGPU
1060
+ * Any attribute that is disabled in the current vertex array object
1061
+ * is read from the context's global constant value for that attribute location.
994
1062
  * @param constantAttributes
995
1063
  */
996
- setConstantAttributes(constantAttributes) {
997
- Object.assign(this.constantAttributes, constantAttributes);
998
- }
999
- /**
1000
- * Sets bindings (textures, samplers, uniform buffers)
1001
- */
1002
- setBindings(bindings) {
1003
- Object.assign(this.bindings, bindings);
1004
- }
1005
- /**
1006
- * Sets individual uniforms
1007
- * @deprecated WebGL only, use uniform buffers for portability
1008
- * @param uniforms
1009
- * @returns self for chaining
1010
- */
1011
- setUniforms(uniforms) {
1012
- this.pipeline.setUniforms(uniforms);
1013
- Object.assign(this.uniforms, uniforms);
1064
+ setConstantAttributes(attributes) {
1065
+ for (const [attributeName, value] of Object.entries(attributes)) {
1066
+ const attributeInfo = this._attributeInfos[attributeName];
1067
+ if (attributeInfo) {
1068
+ this.vertexArray.setConstant(attributeInfo.location, value);
1069
+ } else {
1070
+ import_core6.log.warn(`Model "${this.id}: Ignoring constant supplied for unknown attribute "${name}"`)();
1071
+ }
1072
+ }
1014
1073
  }
1015
1074
  _setPipelineNeedsUpdate(reason) {
1016
1075
  this._pipelineNeedsUpdate = this._pipelineNeedsUpdate || reason;
1017
1076
  }
1018
1077
  _updatePipeline() {
1019
1078
  if (this._pipelineNeedsUpdate) {
1020
- import_core6.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1079
+ if (this.pipeline) {
1080
+ import_core6.log.log(1, `Model ${this.id}: Recreating pipeline because "${this._pipelineNeedsUpdate}".`)();
1081
+ }
1021
1082
  this._pipelineNeedsUpdate = false;
1022
1083
  this.pipeline = this.device.createRenderPipeline(__spreadProps(__spreadValues({}, this.props), {
1023
1084
  bufferLayout: this.bufferLayout,
1024
1085
  topology: this.topology,
1025
1086
  parameters: this.parameters,
1026
- vs: this.device.createShader({ stage: "vertex", source: this.vs }),
1027
- fs: this.fs ? this.device.createShader({ stage: "fragment", source: this.fs }) : null
1087
+ vs: this.device.createShader({ id: "{$this.id}-vertex", stage: "vertex", source: this.vs }),
1088
+ fs: this.fs ? this.device.createShader({ id: "{$this.id}-fragment", stage: "fragment", source: this.fs }) : null
1028
1089
  }));
1090
+ this._attributeInfos = (0, import_core7.getAttributeInfosFromLayouts)(
1091
+ this.pipeline.shaderLayout,
1092
+ this.bufferLayout
1093
+ );
1029
1094
  }
1030
1095
  return this.pipeline;
1031
1096
  }
@@ -1041,15 +1106,16 @@ Model.defaultProps = __spreadProps(__spreadValues({}, import_core6.RenderPipelin
1041
1106
  modules: [],
1042
1107
  moduleSettings: {},
1043
1108
  geometry: null,
1109
+ indexBuffer: null,
1110
+ attributes: {},
1111
+ constantAttributes: {},
1044
1112
  pipelineFactory: void 0,
1045
1113
  shaderAssembler: import_shadertools.ShaderAssembler.getDefaultShaderAssembler()
1046
1114
  });
1047
1115
  function mergeBufferLayouts(layouts1, layouts2) {
1048
1116
  const layouts = [...layouts1];
1049
1117
  for (const attribute of layouts2) {
1050
- const index = layouts.findIndex(
1051
- (attribute2) => attribute2.name === attribute.name
1052
- );
1118
+ const index = layouts.findIndex((attribute2) => attribute2.name === attribute.name);
1053
1119
  if (index < 0) {
1054
1120
  layouts.push(attribute);
1055
1121
  } else {
@@ -1060,9 +1126,6 @@ function mergeBufferLayouts(layouts1, layouts2) {
1060
1126
  }
1061
1127
 
1062
1128
  // src/transform/transform.ts
1063
- var import_shadertools2 = require("@luma.gl/shadertools");
1064
- var import_constants = require("@luma.gl/constants");
1065
- var import_webgl = require("@luma.gl/webgl");
1066
1129
  var Transform = class {
1067
1130
  constructor(device, props = {}) {
1068
1131
  // model: Model;
@@ -1070,18 +1133,6 @@ var Transform = class {
1070
1133
  // bufferTransform: BufferTransform | null = null;
1071
1134
  // textureTransform: TextureTransform | null = null;
1072
1135
  this.elementIDBuffer = null;
1073
- this.device = import_webgl.WebGLDevice.attach(device);
1074
- this.gl = this.device.gl2;
1075
- this._buildResourceTransforms(props);
1076
- props = this._updateModelProps(props);
1077
- this.model = new Model(this.device, __spreadProps(__spreadValues({}, props), {
1078
- fs: props.fs || (0, import_shadertools2.getPassthroughFS)({ version: (0, import_shadertools2.getShaderInfo)(props.vs).version }),
1079
- id: props.id || "transform-model",
1080
- // @ts-expect-error
1081
- drawMode: props.drawMode || import_constants.GL.POINTS,
1082
- vertexCount: props.elementCount
1083
- }));
1084
- Object.seal(this);
1085
1136
  }
1086
1137
  /**
1087
1138
  * Check if Transforms are supported (they are not under WebGL1)
@@ -1134,17 +1185,105 @@ var Transform = class {
1134
1185
  }
1135
1186
  };
1136
1187
 
1137
- // src/lib/clip-space.ts
1188
+ // src/shadertools/shader-module-uniforms.ts
1138
1189
  var import_core8 = require("@luma.gl/core");
1139
- var import_webgl2 = require("@luma.gl/webgl");
1190
+ var import_core9 = require("@luma.gl/core");
1191
+ var ShaderModuleUniforms = class {
1192
+ constructor(props) {
1193
+ this.uniformBuffer = null;
1194
+ this.uniforms = {};
1195
+ this.modifiedUniforms = {};
1196
+ this.modified = true;
1197
+ this.needsRedraw = "initialized";
1198
+ this.device = props.device;
1199
+ this.shaderModule = props.shaderModule;
1200
+ this.useUniformBuffers = this.device.info.type !== "webgl";
1201
+ const uniformTypes = {};
1202
+ for (const [name2, { format }] of Object.entries(props.shaderModule.uniforms)) {
1203
+ uniformTypes[name2] = format;
1204
+ }
1205
+ this.uniformBufferLayout = new import_core9.UniformBufferLayout(uniformTypes);
1206
+ if (this.useUniformBuffers) {
1207
+ this.uniformBuffer = this.device.createBuffer({
1208
+ usage: import_core9.Buffer.UNIFORM,
1209
+ byteLength: this.uniformBufferLayout.byteLength
1210
+ });
1211
+ }
1212
+ }
1213
+ /** Set a map of uniforms */
1214
+ setUniforms(uniforms) {
1215
+ for (const [key, value] of Object.entries(uniforms)) {
1216
+ this._setUniform(key, value);
1217
+ this.setNeedsRedraw(key);
1218
+ }
1219
+ }
1220
+ setNeedsRedraw(reason) {
1221
+ this.needsRedraw = this.needsRedraw || reason;
1222
+ }
1223
+ /**
1224
+ * Updates the uniform buffer if needed.
1225
+ * Clears the dirty flag.
1226
+ */
1227
+ getUniformBuffer() {
1228
+ if (this.needsRedraw) {
1229
+ const modifiedUniforms = this.getModifiedUniforms();
1230
+ const data = this.uniformBufferLayout.getData(modifiedUniforms);
1231
+ this.uniformBuffer.write(data);
1232
+ }
1233
+ return this.uniformBuffer;
1234
+ }
1235
+ /** Returns all uniforms */
1236
+ getUniforms(groupName) {
1237
+ this.modifiedUniforms = {};
1238
+ this.needsRedraw = false;
1239
+ return this.uniforms[groupName] || {};
1240
+ }
1241
+ /** Returns modified uniforms */
1242
+ getModifiedUniforms() {
1243
+ const modifiedUniforms = this.modifiedUniforms;
1244
+ this.modifiedUniforms = {};
1245
+ this.needsRedraw = false;
1246
+ return modifiedUniforms;
1247
+ }
1248
+ /** Set a single uniform */
1249
+ _setUniform(key, value) {
1250
+ if (arrayEqual(this.uniforms[key], value)) {
1251
+ return;
1252
+ }
1253
+ this.uniforms[key] = value;
1254
+ this.modifiedUniforms[key] = true;
1255
+ this.modified = true;
1256
+ }
1257
+ };
1258
+ function arrayEqual(a, b, limit = 16) {
1259
+ if (a !== b) {
1260
+ return false;
1261
+ }
1262
+ const arrayA = (0, import_core8.isNumberArray)(a);
1263
+ if (!arrayA) {
1264
+ return false;
1265
+ }
1266
+ const arrayB = (0, import_core8.isNumberArray)(b);
1267
+ if (arrayB && arrayA.length === arrayB.length) {
1268
+ for (let i = 0; i < arrayA.length; ++i) {
1269
+ if (arrayB[i] !== arrayA[i]) {
1270
+ return false;
1271
+ }
1272
+ }
1273
+ }
1274
+ return true;
1275
+ }
1276
+
1277
+ // src/lib/clip-space.ts
1278
+ var import_core11 = require("@luma.gl/core");
1140
1279
 
1141
1280
  // src/geometry/geometry.ts
1142
- var import_core7 = require("@luma.gl/core");
1281
+ var import_core10 = require("@luma.gl/core");
1143
1282
  var Geometry = class {
1144
1283
  constructor(props) {
1145
1284
  this.userData = {};
1146
1285
  const { attributes = {}, indices = null, vertexCount = null } = props;
1147
- this.id = props.id || (0, import_core7.uid)("geometry");
1286
+ this.id = props.id || (0, import_core10.uid)("geometry");
1148
1287
  this.topology = props.topology;
1149
1288
  if (indices) {
1150
1289
  this.indices = ArrayBuffer.isView(indices) ? { value: indices, size: 1 } : indices;
@@ -1152,7 +1291,7 @@ var Geometry = class {
1152
1291
  this.attributes = {};
1153
1292
  for (const [attributeName, attributeValue] of Object.entries(attributes)) {
1154
1293
  const attribute = ArrayBuffer.isView(attributeValue) ? { value: attributeValue } : attributeValue;
1155
- (0, import_core7.assert)(
1294
+ (0, import_core10.assert)(
1156
1295
  ArrayBuffer.isView(attribute.value),
1157
1296
  `${this._print(attributeName)}: must be typed array or object with value as typed array`
1158
1297
  );
@@ -1160,7 +1299,7 @@ var Geometry = class {
1160
1299
  attribute.size = 3;
1161
1300
  }
1162
1301
  if (attributeName === "indices") {
1163
- (0, import_core7.assert)(!this.indices);
1302
+ (0, import_core10.assert)(!this.indices);
1164
1303
  this.indices = attribute;
1165
1304
  } else {
1166
1305
  this.attributes[attributeName] = attribute;
@@ -1211,13 +1350,13 @@ var Geometry = class {
1211
1350
  vertexCount = Math.min(vertexCount, value.length / size);
1212
1351
  }
1213
1352
  }
1214
- (0, import_core7.assert)(Number.isFinite(vertexCount));
1353
+ (0, import_core10.assert)(Number.isFinite(vertexCount));
1215
1354
  return vertexCount;
1216
1355
  }
1217
1356
  };
1218
1357
 
1219
1358
  // src/lib/clip-space.ts
1220
- var CLIPSPACE_VERTEX_SHADER = import_core8.glsl`\
1359
+ var CLIPSPACE_VERTEX_SHADER = import_core11.glsl`\
1221
1360
  attribute vec2 aClipSpacePosition;
1222
1361
  attribute vec2 aTexCoord;
1223
1362
  attribute vec2 aCoordinate;
@@ -1238,7 +1377,7 @@ var ClipSpace = class extends Model {
1238
1377
  constructor(device, opts) {
1239
1378
  const TEX_COORDS = POSITIONS.map((coord) => coord === -1 ? 0 : coord);
1240
1379
  super(
1241
- import_webgl2.WebGLDevice.attach(device),
1380
+ device,
1242
1381
  __spreadProps(__spreadValues({}, opts), {
1243
1382
  vs: CLIPSPACE_VERTEX_SHADER,
1244
1383
  vertexCount: 4,
@@ -1257,19 +1396,19 @@ var ClipSpace = class extends Model {
1257
1396
  };
1258
1397
 
1259
1398
  // src/scenegraph/scenegraph-node.ts
1260
- var import_core9 = require("@luma.gl/core");
1261
- var import_core10 = require("@math.gl/core");
1399
+ var import_core12 = require("@luma.gl/core");
1400
+ var import_core13 = require("@math.gl/core");
1262
1401
  var ScenegraphNode = class {
1263
1402
  constructor(props = {}) {
1264
- this.matrix = new import_core10.Matrix4();
1403
+ this.matrix = new import_core13.Matrix4();
1265
1404
  this.display = true;
1266
- this.position = new import_core10.Vector3();
1267
- this.rotation = new import_core10.Vector3();
1268
- this.scale = new import_core10.Vector3(1, 1, 1);
1405
+ this.position = new import_core13.Vector3();
1406
+ this.rotation = new import_core13.Vector3();
1407
+ this.scale = new import_core13.Vector3(1, 1, 1);
1269
1408
  this.userData = {};
1270
1409
  this.props = {};
1271
1410
  const { id } = props;
1272
- this.id = id || (0, import_core9.uid)(this.constructor.name);
1411
+ this.id = id || (0, import_core12.uid)(this.constructor.name);
1273
1412
  this._setScenegraphNodeProps(props);
1274
1413
  }
1275
1414
  getBounds() {
@@ -1289,17 +1428,17 @@ var ScenegraphNode = class {
1289
1428
  return `{type: ScenegraphNode, id: ${this.id})}`;
1290
1429
  }
1291
1430
  setPosition(position) {
1292
- (0, import_core9.assert)(position.length === 3, "setPosition requires vector argument");
1431
+ (0, import_core12.assert)(position.length === 3, "setPosition requires vector argument");
1293
1432
  this.position = position;
1294
1433
  return this;
1295
1434
  }
1296
1435
  setRotation(rotation) {
1297
- (0, import_core9.assert)(rotation.length === 3, "setRotation requires vector argument");
1436
+ (0, import_core12.assert)(rotation.length === 3, "setRotation requires vector argument");
1298
1437
  this.rotation = rotation;
1299
1438
  return this;
1300
1439
  }
1301
1440
  setScale(scale) {
1302
- (0, import_core9.assert)(scale.length === 3, "setScale requires vector argument");
1441
+ (0, import_core12.assert)(scale.length === 3, "setScale requires vector argument");
1303
1442
  this.scale = scale;
1304
1443
  return this;
1305
1444
  }
@@ -1351,9 +1490,9 @@ var ScenegraphNode = class {
1351
1490
  return this;
1352
1491
  }
1353
1492
  getCoordinateUniforms(viewMatrix, modelMatrix) {
1354
- (0, import_core9.assert)(viewMatrix);
1493
+ (0, import_core12.assert)(viewMatrix);
1355
1494
  modelMatrix = modelMatrix || this.matrix;
1356
- const worldMatrix = new import_core10.Matrix4(viewMatrix).multiplyRight(modelMatrix);
1495
+ const worldMatrix = new import_core13.Matrix4(viewMatrix).multiplyRight(modelMatrix);
1357
1496
  const worldInverse = worldMatrix.invert();
1358
1497
  const worldInverseTranspose = worldInverse.transpose();
1359
1498
  return {
@@ -1408,13 +1547,13 @@ var ScenegraphNode = class {
1408
1547
  };
1409
1548
 
1410
1549
  // src/scenegraph/group-node.ts
1411
- var import_core11 = require("@math.gl/core");
1412
- var import_core12 = require("@luma.gl/core");
1550
+ var import_core14 = require("@math.gl/core");
1551
+ var import_core15 = require("@luma.gl/core");
1413
1552
  var GroupNode = class extends ScenegraphNode {
1414
1553
  constructor(props = {}) {
1415
1554
  props = Array.isArray(props) ? { children: props } : props;
1416
1555
  const { children = [] } = props;
1417
- import_core12.log.assert(
1556
+ import_core15.log.assert(
1418
1557
  children.every((child) => child instanceof ScenegraphNode),
1419
1558
  "every child must an instance of ScenegraphNode"
1420
1559
  );
@@ -1429,12 +1568,12 @@ var GroupNode = class extends ScenegraphNode {
1429
1568
  return;
1430
1569
  }
1431
1570
  const [min, max] = bounds;
1432
- const center = new import_core11.Vector3(min).add(max).divide([2, 2, 2]);
1571
+ const center = new import_core14.Vector3(min).add(max).divide([2, 2, 2]);
1433
1572
  worldMatrix.transformAsPoint(center, center);
1434
- const halfSize = new import_core11.Vector3(max).subtract(min).divide([2, 2, 2]);
1573
+ const halfSize = new import_core14.Vector3(max).subtract(min).divide([2, 2, 2]);
1435
1574
  worldMatrix.transformAsVector(halfSize, halfSize);
1436
1575
  for (let v = 0; v < 8; v++) {
1437
- const position = new import_core11.Vector3(
1576
+ const position = new import_core14.Vector3(
1438
1577
  v & 1 ? -1 : 1,
1439
1578
  v & 2 ? -1 : 1,
1440
1579
  v & 4 ? -1 : 1
@@ -1478,8 +1617,8 @@ var GroupNode = class extends ScenegraphNode {
1478
1617
  this.children = [];
1479
1618
  return this;
1480
1619
  }
1481
- traverse(visitor, { worldMatrix = new import_core11.Matrix4() } = {}) {
1482
- const modelMatrix = new import_core11.Matrix4(worldMatrix).multiplyRight(this.matrix);
1620
+ traverse(visitor, { worldMatrix = new import_core14.Matrix4() } = {}) {
1621
+ const modelMatrix = new import_core14.Matrix4(worldMatrix).multiplyRight(this.matrix);
1483
1622
  for (const child of this.children) {
1484
1623
  if (child instanceof GroupNode) {
1485
1624
  child.traverse(visitor, { worldMatrix: modelMatrix });
@@ -1522,10 +1661,10 @@ var ModelNode = class extends ScenegraphNode {
1522
1661
  };
1523
1662
 
1524
1663
  // src/geometries/cone-geometry.ts
1525
- var import_core14 = require("@luma.gl/core");
1664
+ var import_core17 = require("@luma.gl/core");
1526
1665
 
1527
1666
  // src/geometries/truncated-cone-geometry.ts
1528
- var import_core13 = require("@luma.gl/core");
1667
+ var import_core16 = require("@luma.gl/core");
1529
1668
  var INDEX_OFFSETS = {
1530
1669
  x: [2, 0, 1],
1531
1670
  y: [0, 1, 2],
@@ -1533,7 +1672,7 @@ var INDEX_OFFSETS = {
1533
1672
  };
1534
1673
  var TruncatedConeGeometry = class extends Geometry {
1535
1674
  constructor(props = {}) {
1536
- const { id = (0, import_core13.uid)("truncated-code-geometry") } = props;
1675
+ const { id = (0, import_core16.uid)("truncated-code-geometry") } = props;
1537
1676
  const { indices, attributes } = tesselateTruncatedCone(props);
1538
1677
  super(__spreadProps(__spreadValues({}, props), {
1539
1678
  id,
@@ -1635,7 +1774,7 @@ function tesselateTruncatedCone(props = {}) {
1635
1774
  // src/geometries/cone-geometry.ts
1636
1775
  var ConeGeometry = class extends TruncatedConeGeometry {
1637
1776
  constructor(props = {}) {
1638
- const { id = (0, import_core14.uid)("cone-geometry"), radius = 1, cap = true } = props;
1777
+ const { id = (0, import_core17.uid)("cone-geometry"), radius = 1, cap = true } = props;
1639
1778
  super(__spreadProps(__spreadValues({}, props), {
1640
1779
  id,
1641
1780
  topRadius: 0,
@@ -1647,10 +1786,10 @@ var ConeGeometry = class extends TruncatedConeGeometry {
1647
1786
  };
1648
1787
 
1649
1788
  // src/geometries/cube-geometry.ts
1650
- var import_core15 = require("@luma.gl/core");
1789
+ var import_core18 = require("@luma.gl/core");
1651
1790
  var CubeGeometry = class extends Geometry {
1652
1791
  constructor(props = {}) {
1653
- const { id = (0, import_core15.uid)("cube-geometry"), indices = true } = props;
1792
+ const { id = (0, import_core18.uid)("cube-geometry"), indices = true } = props;
1654
1793
  super(indices ? __spreadProps(__spreadValues({}, props), {
1655
1794
  id,
1656
1795
  topology: "triangle-list",
@@ -2291,10 +2430,10 @@ var NON_INDEXED_ATTRIBUTES = {
2291
2430
  };
2292
2431
 
2293
2432
  // src/geometries/cylinder-geometry.ts
2294
- var import_core16 = require("@luma.gl/core");
2433
+ var import_core19 = require("@luma.gl/core");
2295
2434
  var CylinderGeometry = class extends TruncatedConeGeometry {
2296
2435
  constructor(props = {}) {
2297
- const { id = (0, import_core16.uid)("cylinder-geometry"), radius = 1 } = props;
2436
+ const { id = (0, import_core19.uid)("cylinder-geometry"), radius = 1 } = props;
2298
2437
  super(__spreadProps(__spreadValues({}, props), {
2299
2438
  id,
2300
2439
  bottomRadius: radius,
@@ -2304,13 +2443,13 @@ var CylinderGeometry = class extends TruncatedConeGeometry {
2304
2443
  };
2305
2444
 
2306
2445
  // src/geometries/ico-sphere-geometry.ts
2307
- var import_core17 = require("@luma.gl/core");
2308
- var import_core18 = require("@math.gl/core");
2446
+ var import_core20 = require("@luma.gl/core");
2447
+ var import_core21 = require("@math.gl/core");
2309
2448
  var ICO_POSITIONS = [-1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0];
2310
2449
  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];
2311
2450
  var IcoSphereGeometry = class extends Geometry {
2312
2451
  constructor(props = {}) {
2313
- const { id = (0, import_core17.uid)("ico-sphere-geometry") } = props;
2452
+ const { id = (0, import_core20.uid)("ico-sphere-geometry") } = props;
2314
2453
  const { indices, attributes } = tesselateIcosaHedron(props);
2315
2454
  super(__spreadProps(__spreadValues({}, props), {
2316
2455
  id,
@@ -2402,7 +2541,7 @@ function tesselateIcosaHedron(props) {
2402
2541
  const u3 = 1 - phi3 / PI2;
2403
2542
  const vec1 = [x3 - x2, y3 - y2, z3 - z2];
2404
2543
  const vec2 = [x1 - x2, y1 - y2, z1 - z2];
2405
- const normal = new import_core18.Vector3(vec1).cross(vec2).normalize();
2544
+ const normal = new import_core21.Vector3(vec1).cross(vec2).normalize();
2406
2545
  let newIndex;
2407
2546
  if ((u1 === 0 || u2 === 0 || u3 === 0) && (u1 === 0 || u1 > 0.5) && (u2 === 0 || u2 > 0.5) && (u3 === 0 || u3 > 0.5)) {
2408
2547
  positions.push(positions[in1 + 0], positions[in1 + 1], positions[in1 + 2]);
@@ -2451,7 +2590,7 @@ function tesselateIcosaHedron(props) {
2451
2590
  }
2452
2591
 
2453
2592
  // src/geometries/plane-geometry.ts
2454
- var import_core19 = require("@luma.gl/core");
2593
+ var import_core22 = require("@luma.gl/core");
2455
2594
 
2456
2595
  // src/geometry/geometry-utils.ts
2457
2596
  function unpackIndexedGeometry(geometry) {
@@ -2484,7 +2623,7 @@ function unpackIndexedGeometry(geometry) {
2484
2623
  // src/geometries/plane-geometry.ts
2485
2624
  var PlaneGeometry = class extends Geometry {
2486
2625
  constructor(props = {}) {
2487
- const { id = (0, import_core19.uid)("plane-geometry") } = props;
2626
+ const { id = (0, import_core22.uid)("plane-geometry") } = props;
2488
2627
  const { indices, attributes } = tesselatePlane(props);
2489
2628
  super(__spreadProps(__spreadValues({}, props), {
2490
2629
  id,
@@ -2573,10 +2712,10 @@ function tesselatePlane(props) {
2573
2712
  }
2574
2713
 
2575
2714
  // src/geometries/sphere-geometry.ts
2576
- var import_core20 = require("@luma.gl/core");
2715
+ var import_core23 = require("@luma.gl/core");
2577
2716
  var SphereGeometry = class extends Geometry {
2578
2717
  constructor(props = {}) {
2579
- const { id = (0, import_core20.uid)("sphere-geometry") } = props;
2718
+ const { id = (0, import_core23.uid)("sphere-geometry") } = props;
2580
2719
  const { indices, attributes } = tesselateSphere(props);
2581
2720
  super(__spreadProps(__spreadValues({}, props), {
2582
2721
  id,