@rings-webgpu/core 1.0.37 → 1.0.39

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.
@@ -24081,10 +24081,44 @@ class Uint8ArrayTexture extends Texture {
24081
24081
  }
24082
24082
  return this;
24083
24083
  }
24084
- updateTexture(width, height, data) {
24084
+ updateTexture(width, height, data, startRow, rowCount) {
24085
24085
  let device = webGPUContext.device;
24086
24086
  const bytesPerRow = Math.ceil(width * 4 / 256) * 256;
24087
24087
  this.mipmapCount = Math.floor(Math.log2(width) );
24088
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24089
+ const updateHeight = rowCount;
24090
+ const updateOffset = startRow * width * 4;
24091
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24092
+ const neededSize = updateData.byteLength;
24093
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24094
+ this._dataBuffer && this._dataBuffer.destroy();
24095
+ this._dataBuffer = device.createBuffer({
24096
+ size: neededSize,
24097
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24098
+ });
24099
+ }
24100
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24101
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24102
+ commandEncoder2.copyBufferToTexture(
24103
+ {
24104
+ buffer: this._dataBuffer,
24105
+ bytesPerRow,
24106
+ offset: 0
24107
+ },
24108
+ {
24109
+ texture: this.getGPUTexture(),
24110
+ origin: [0, startRow, 0]
24111
+ // Start at row startRow
24112
+ },
24113
+ {
24114
+ width,
24115
+ height: updateHeight,
24116
+ depthOrArrayLayers: 1
24117
+ }
24118
+ );
24119
+ GPUContext.endCommandEncoder(commandEncoder2);
24120
+ return;
24121
+ }
24088
24122
  this._dataBuffer && this._dataBuffer.destroy();
24089
24123
  this._dataBuffer = null;
24090
24124
  const textureDataBuffer = this._dataBuffer = device.createBuffer({
@@ -24140,9 +24174,28 @@ class Uint32ArrayTexture extends Texture {
24140
24174
  this.gpuSampler = device.createSampler({});
24141
24175
  return this;
24142
24176
  }
24143
- updateTexture(width, height, data) {
24177
+ updateTexture(width, height, data, startRow, rowCount) {
24144
24178
  let device = webGPUContext.device;
24145
24179
  const bytesPerRow = width * 4 * 4;
24180
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24181
+ const updateHeight = rowCount;
24182
+ const updateOffset = startRow * width * 4;
24183
+ const updateData = data.subarray(updateOffset, updateOffset + updateHeight * width * 4);
24184
+ device.queue.writeTexture(
24185
+ {
24186
+ texture: this.getGPUTexture(),
24187
+ origin: [0, startRow, 0]
24188
+ // Start at row startRow
24189
+ },
24190
+ updateData.buffer,
24191
+ {
24192
+ bytesPerRow,
24193
+ offset: updateData.byteOffset
24194
+ },
24195
+ { width, height: updateHeight, depthOrArrayLayers: 1 }
24196
+ );
24197
+ return;
24198
+ }
24146
24199
  device.queue.writeTexture(
24147
24200
  { texture: this.getGPUTexture() },
24148
24201
  data.buffer,
@@ -24189,30 +24242,37 @@ class R32UintTexture extends Texture {
24189
24242
  }
24190
24243
  }
24191
24244
 
24192
- const _floatView = new Float32Array(1);
24193
- const _int32View = new Int32Array(_floatView.buffer);
24194
- let toHalfFloat = function(val) {
24195
- _floatView[0] = val;
24196
- const x = _int32View[0];
24197
- let bits = x >> 16 & 32768;
24198
- let m = x >> 12 & 2047;
24199
- const e = x >> 23 & 255;
24200
- if (e < 103) return bits;
24201
- if (e > 142) {
24202
- bits |= 31744;
24203
- bits |= (e == 255 ? 1 : 0) && x & 8388607;
24204
- return bits;
24205
- }
24206
- if (e < 114) {
24207
- m |= 2048;
24208
- bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24209
- return bits;
24245
+ const _floatView$1 = new Float32Array(1);
24246
+ const _int32View$1 = new Int32Array(_floatView$1.buffer);
24247
+ function batchConvertToHalfFloat(src, dst, offset, length) {
24248
+ for (let i = 0; i < length; i++) {
24249
+ const val = src[offset + i];
24250
+ _floatView$1[0] = val;
24251
+ const x = _int32View$1[0];
24252
+ let bits = x >> 16 & 32768;
24253
+ let m = x >> 12 & 2047;
24254
+ const e = x >> 23 & 255;
24255
+ if (e < 103) {
24256
+ dst[offset + i] = bits;
24257
+ continue;
24258
+ }
24259
+ if (e > 142) {
24260
+ bits |= 31744;
24261
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24262
+ dst[offset + i] = bits;
24263
+ continue;
24264
+ }
24265
+ if (e < 114) {
24266
+ m |= 2048;
24267
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24268
+ dst[offset + i] = bits;
24269
+ continue;
24270
+ }
24271
+ bits |= e - 112 << 10 | m >> 1;
24272
+ bits += m & 1;
24273
+ dst[offset + i] = bits;
24210
24274
  }
24211
- bits |= e - 112 << 10 | m >> 1;
24212
- bits += m & 1;
24213
- return bits;
24214
- };
24215
-
24275
+ }
24216
24276
  class Float16ArrayTexture extends Texture {
24217
24277
  uint16Array;
24218
24278
  floatArray;
@@ -24241,8 +24301,10 @@ class Float16ArrayTexture extends Texture {
24241
24301
  * @param height 纹理高度
24242
24302
  * @param numbers 像素数据数组
24243
24303
  * @param mipmap 是否生成Mipmap
24304
+ * @param startRow 起始行(部分更新)
24305
+ * @param rowCount 更新的行数(部分更新)
24244
24306
  */
24245
- updateTexture(width, height, numbers, mipmap = true) {
24307
+ updateTexture(width, height, numbers, mipmap = true, startRow, rowCount) {
24246
24308
  if (width != this.width || height != this.height) {
24247
24309
  this._dataBuffer && this._dataBuffer.destroy();
24248
24310
  this._dataBuffer = null;
@@ -24255,22 +24317,70 @@ class Float16ArrayTexture extends Texture {
24255
24317
  this.format = GPUTextureFormat.rgba16float;
24256
24318
  this.mipmapCount = Math.floor(mipmap ? Math.log2(width) : 1);
24257
24319
  this.createTextureDescriptor(width, height, this.mipmapCount, this.format);
24320
+ if (startRow !== void 0 && rowCount !== void 0 && rowCount < height) {
24321
+ const updateHeight = rowCount;
24322
+ const updateOffset = startRow * width * 4;
24323
+ const updateLength = updateHeight * width * 4;
24324
+ if (!this.uint16Array || this.uint16Array.length < updateOffset + updateLength) {
24325
+ if (!this.uint16Array || this.uint16Array.length < numbers.length) {
24326
+ this.uint16Array = new Uint16Array(numbers.length);
24327
+ }
24328
+ }
24329
+ const uint16Array2 = this.uint16Array;
24330
+ batchConvertToHalfFloat(numbers, uint16Array2, updateOffset, updateLength);
24331
+ const updateData = uint16Array2.subarray(updateOffset, updateOffset + updateLength);
24332
+ const neededSize2 = updateData.byteLength;
24333
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize2) {
24334
+ this._dataBuffer && this._dataBuffer.destroy();
24335
+ this._dataBuffer = device.createBuffer({
24336
+ size: neededSize2,
24337
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24338
+ });
24339
+ }
24340
+ device.queue.writeBuffer(this._dataBuffer, 0, updateData.buffer, updateData.byteOffset, updateData.byteLength);
24341
+ const commandEncoder2 = GPUContext.beginCommandEncoder();
24342
+ commandEncoder2.copyBufferToTexture(
24343
+ {
24344
+ buffer: this._dataBuffer,
24345
+ bytesPerRow,
24346
+ offset: 0
24347
+ },
24348
+ {
24349
+ texture: this.getGPUTexture(),
24350
+ origin: [0, startRow, 0]
24351
+ // Start at row startRow
24352
+ },
24353
+ {
24354
+ width,
24355
+ height: updateHeight,
24356
+ depthOrArrayLayers: 1
24357
+ }
24358
+ );
24359
+ if (!this.useMipmap) {
24360
+ this.samplerBindingLayout.type = `filtering`;
24361
+ this.textureBindingLayout.sampleType = `float`;
24362
+ }
24363
+ GPUContext.endCommandEncoder(commandEncoder2);
24364
+ return;
24365
+ }
24258
24366
  if (!this.uint16Array || this.uint16Array.length != numbers.length) {
24259
24367
  this.uint16Array = new Uint16Array(numbers.length);
24260
24368
  }
24261
- let uint16Array = this.uint16Array;
24262
- for (let i = 0, c = uint16Array.length; i < c; i++) {
24263
- uint16Array[i] = toHalfFloat(numbers[i]);
24369
+ const uint16Array = this.uint16Array;
24370
+ batchConvertToHalfFloat(numbers, uint16Array, 0, numbers.length);
24371
+ const neededSize = uint16Array.byteLength;
24372
+ if (!this._dataBuffer || this._dataBuffer.size < neededSize) {
24373
+ this._dataBuffer && this._dataBuffer.destroy();
24374
+ this._dataBuffer = device.createBuffer({
24375
+ size: neededSize,
24376
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24377
+ });
24264
24378
  }
24265
- const textureDataBuffer = this._dataBuffer = device.createBuffer({
24266
- size: uint16Array.byteLength,
24267
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24268
- });
24269
- device.queue.writeBuffer(textureDataBuffer, 0, uint16Array);
24379
+ device.queue.writeBuffer(this._dataBuffer, 0, uint16Array.buffer, uint16Array.byteOffset, uint16Array.byteLength);
24270
24380
  const commandEncoder = GPUContext.beginCommandEncoder();
24271
24381
  commandEncoder.copyBufferToTexture(
24272
24382
  {
24273
- buffer: textureDataBuffer,
24383
+ buffer: this._dataBuffer,
24274
24384
  bytesPerRow
24275
24385
  },
24276
24386
  {
@@ -24293,6 +24403,30 @@ class Float16ArrayTexture extends Texture {
24293
24403
  }
24294
24404
  }
24295
24405
 
24406
+ const _floatView = new Float32Array(1);
24407
+ const _int32View = new Int32Array(_floatView.buffer);
24408
+ let toHalfFloat = function(val) {
24409
+ _floatView[0] = val;
24410
+ const x = _int32View[0];
24411
+ let bits = x >> 16 & 32768;
24412
+ let m = x >> 12 & 2047;
24413
+ const e = x >> 23 & 255;
24414
+ if (e < 103) return bits;
24415
+ if (e > 142) {
24416
+ bits |= 31744;
24417
+ bits |= (e == 255 ? 1 : 0) && x & 8388607;
24418
+ return bits;
24419
+ }
24420
+ if (e < 114) {
24421
+ m |= 2048;
24422
+ bits |= (m >> 114 - e) + (m >> 113 - e & 1);
24423
+ return bits;
24424
+ }
24425
+ bits |= e - 112 << 10 | m >> 1;
24426
+ bits += m & 1;
24427
+ return bits;
24428
+ };
24429
+
24296
24430
  var __getOwnPropDesc$m = Object.getOwnPropertyDescriptor;
24297
24431
  var __decorateClass$m = (decorators, target, key, kind) => {
24298
24432
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$m(target, key) : target;
@@ -42151,7 +42285,7 @@ class PostProcessingComponent extends ComponentBase {
42151
42285
  }
42152
42286
  }
42153
42287
 
42154
- const version = "1.0.36";
42288
+ const version = "1.0.38";
42155
42289
 
42156
42290
  class Engine3D {
42157
42291
  /**
@@ -54360,13 +54494,48 @@ let GSplatStreamRenderer = class extends RenderNode {
54360
54494
  // Splat count and texture dimensions
54361
54495
  totalCount = 0;
54362
54496
  size = new Vector2();
54363
- worldBoundBox = new BoundingBox();
54497
+ localBoundBox = new BoundingBox();
54498
+ // public worldBoundBox: BoundingBox = new BoundingBox();
54499
+ get worldBoundBox() {
54500
+ const boundBox = new BoundingBox();
54501
+ boundBox.makeEmpty();
54502
+ const worldMatrix = this.object3D.transform.worldMatrix;
54503
+ const m = worldMatrix.rawData;
54504
+ const localMin = this.localBoundBox.min;
54505
+ const localMax = this.localBoundBox.max;
54506
+ const corners = [
54507
+ [localMin.x, localMin.y, localMin.z],
54508
+ // 0: min, min, min
54509
+ [localMax.x, localMin.y, localMin.z],
54510
+ // 1: max, min, min
54511
+ [localMin.x, localMax.y, localMin.z],
54512
+ // 2: min, max, min
54513
+ [localMax.x, localMax.y, localMin.z],
54514
+ // 3: max, max, min
54515
+ [localMin.x, localMin.y, localMax.z],
54516
+ // 4: min, min, max
54517
+ [localMax.x, localMin.y, localMax.z],
54518
+ // 5: max, min, max
54519
+ [localMin.x, localMax.y, localMax.z],
54520
+ // 6: min, max, max
54521
+ [localMax.x, localMax.y, localMax.z]
54522
+ // 7: max, max, max
54523
+ ];
54524
+ for (const [x, y, z] of corners) {
54525
+ const wx = m[0] * x + m[4] * y + m[8] * z + m[12];
54526
+ const wy = m[1] * x + m[5] * y + m[9] * z + m[13];
54527
+ const wz = m[2] * x + m[6] * y + m[10] * z + m[14];
54528
+ boundBox.expandByPoint(new Vector3(wx, wy, wz));
54529
+ }
54530
+ return boundBox;
54531
+ }
54364
54532
  // GPU textures for splat data
54365
54533
  splatColor;
54366
54534
  transformA;
54367
54535
  transformB;
54368
54536
  texParams;
54369
54537
  // [numSplats, texWidth, validCount, visBoost]
54538
+ _texParamDirty = true;
54370
54539
  splatOrder;
54371
54540
  // Material and geometry
54372
54541
  gsplatMaterial;
@@ -54381,8 +54550,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54381
54550
  // R32U: size.x * size.y
54382
54551
  _positions;
54383
54552
  // xyz per splat (local space)
54384
- _worldPositions;
54385
- // xyz per splat (world space, cached)
54553
+ // private _worldPositions: Float32Array; // xyz per splat (world space, cached)
54386
54554
  // Tracking which splats have been set
54387
54555
  _splatSetFlags;
54388
54556
  // Track which indices have data
@@ -54442,8 +54610,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54442
54610
  }
54443
54611
  this._positions = new Float32Array(totalCount * 3);
54444
54612
  this._positions.fill(0);
54445
- this._worldPositions = new Float32Array(totalCount * 3);
54446
- this._worldPositions.fill(0);
54613
+ this.localBoundBox.makeEmpty();
54447
54614
  this._splatSetFlags = new Array(totalCount).fill(false);
54448
54615
  this._validCount = 0;
54449
54616
  this.texParams = new Float32Array([this._validCount, this.size.x, 0, 1]);
@@ -54492,6 +54659,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54492
54659
  this._positions[index * 3 + 0] = data.position[0];
54493
54660
  this._positions[index * 3 + 1] = data.position[1];
54494
54661
  this._positions[index * 3 + 2] = data.position[2];
54662
+ this.localBoundBox.expandByPoint(new Vector3(data.position[0], data.position[1], data.position[2]));
54495
54663
  const SH_C0 = 0.28209479177387814;
54496
54664
  let r = 0.5, g = 0.5, b = 0.5;
54497
54665
  if (data.sh && data.sh.coeffs && data.sh.coeffs.length >= 3) {
@@ -54509,8 +54677,6 @@ let GSplatStreamRenderer = class extends RenderNode {
54509
54677
  if (!wasSet) {
54510
54678
  this._splatSetFlags[index] = true;
54511
54679
  this._validCount++;
54512
- this.texParams[2] = this._validCount;
54513
- this._centersSent = false;
54514
54680
  }
54515
54681
  this._pendingUpdates.add(index);
54516
54682
  }
@@ -54598,14 +54764,32 @@ let GSplatStreamRenderer = class extends RenderNode {
54598
54764
  /**
54599
54765
  * Flush pending updates to GPU
54600
54766
  * Updates GPU textures with all pending changes
54767
+ * Uses partial updates when possible for better performance
54601
54768
  */
54602
54769
  flushUpdates() {
54603
54770
  if (this._pendingUpdates.size === 0) return;
54604
54771
  const w = this.size.x | 0;
54605
54772
  const h = this.size.y | 0;
54606
- this.splatColor.updateTexture(w, h, this._colorData);
54607
- this.transformA.updateTexture(w, h, this._transformAData);
54608
- this.transformB.updateTexture(w, h, this._transformBData, false);
54773
+ const pendingIndices = Array.from(this._pendingUpdates);
54774
+ if (pendingIndices.length === 0) return;
54775
+ let minRow = h;
54776
+ let maxRow = 0;
54777
+ for (const index of pendingIndices) {
54778
+ const row = Math.floor(index / w);
54779
+ if (row < minRow) minRow = row;
54780
+ if (row > maxRow) maxRow = row;
54781
+ }
54782
+ const rowCount = maxRow - minRow + 1;
54783
+ const updateRatio = rowCount / h;
54784
+ if (updateRatio < 0.5 && rowCount < h) {
54785
+ this.splatColor.updateTexture(w, h, this._colorData, minRow, rowCount);
54786
+ this.transformA.updateTexture(w, h, this._transformAData, minRow, rowCount);
54787
+ this.transformB.updateTexture(w, h, this._transformBData, false, minRow, rowCount);
54788
+ } else {
54789
+ this.splatColor.updateTexture(w, h, this._colorData);
54790
+ this.transformA.updateTexture(w, h, this._transformAData);
54791
+ this.transformB.updateTexture(w, h, this._transformBData, false);
54792
+ }
54609
54793
  this.updatePendingWorldPositions();
54610
54794
  this._pendingUpdates.clear();
54611
54795
  }
@@ -54631,55 +54815,22 @@ let GSplatStreamRenderer = class extends RenderNode {
54631
54815
  * Update splat sorting before rendering
54632
54816
  * Uses the same logic as GSplatRenderer for reliable sorting
54633
54817
  */
54634
- onBeforeUpdate(view) {
54635
- if (this._validCount > 0 && view?.camera) {
54636
- if (view.camera.viewMatrix) {
54637
- this.scheduleOrder(view.camera.viewMatrix);
54638
- }
54639
- }
54640
- }
54818
+ // public onBeforeUpdate(view?: View3D) {
54819
+ // if (this._validCount > 0 && view?.camera) {
54820
+ // if (view.camera.viewMatrix) {
54821
+ // this.scheduleOrder(view.camera.viewMatrix);
54822
+ // }
54823
+ // }
54824
+ // }
54641
54825
  /**
54642
54826
  * Update world space positions when transform changes
54643
54827
  */
54644
54828
  updateWorldPositions() {
54645
54829
  if (!this._positions || this._validCount === 0) return;
54646
- const worldMatrix = this.object3D.transform.worldMatrix;
54647
- const localPos = this._positions;
54648
- const count = this._validCount;
54649
- const m = worldMatrix.rawData;
54650
- this.worldBoundBox.makeEmpty();
54651
- for (let i = 0; i < count; i++) {
54652
- if (!this._splatSetFlags[i]) continue;
54653
- const idx = i * 3;
54654
- const x = localPos[idx + 0];
54655
- const y = localPos[idx + 1];
54656
- const z = localPos[idx + 2];
54657
- this._worldPositions[idx + 0] = m[0] * x + m[4] * y + m[8] * z + m[12];
54658
- this._worldPositions[idx + 1] = m[1] * x + m[5] * y + m[9] * z + m[13];
54659
- this._worldPositions[idx + 2] = m[2] * x + m[6] * y + m[10] * z + m[14];
54660
- this.worldBoundBox.expandByPoint(new Vector3(this._worldPositions[idx + 0], this._worldPositions[idx + 1], this._worldPositions[idx + 2]));
54661
- }
54662
54830
  this._centersSent = false;
54663
54831
  }
54664
54832
  updatePendingWorldPositions() {
54665
54833
  if (!this._positions || this._validCount === 0) return;
54666
- const worldMatrix = this.object3D.transform.worldMatrix;
54667
- const localPos = this._positions;
54668
- this._validCount;
54669
- const m = worldMatrix.rawData;
54670
- const pendingUpdates = Array.from(this._pendingUpdates.values());
54671
- for (let i = 0; i < pendingUpdates.length; i++) {
54672
- const ii = pendingUpdates[i];
54673
- if (!this._splatSetFlags[ii]) continue;
54674
- const idx = ii * 3;
54675
- const x = localPos[idx + 0];
54676
- const y = localPos[idx + 1];
54677
- const z = localPos[idx + 2];
54678
- this._worldPositions[idx + 0] = m[0] * x + m[4] * y + m[8] * z + m[12];
54679
- this._worldPositions[idx + 1] = m[1] * x + m[5] * y + m[9] * z + m[13];
54680
- this._worldPositions[idx + 2] = m[2] * x + m[6] * y + m[10] * z + m[14];
54681
- this.worldBoundBox.expandByPoint(new Vector3(this._worldPositions[idx + 0], this._worldPositions[idx + 1], this._worldPositions[idx + 2]));
54682
- }
54683
54834
  this._centersSent = false;
54684
54835
  }
54685
54836
  /**
@@ -54689,7 +54840,7 @@ let GSplatStreamRenderer = class extends RenderNode {
54689
54840
  scheduleOrder(viewMatrix) {
54690
54841
  if (this._validCount === 0) return;
54691
54842
  const transformChanged = this.object3D.transform.localChange;
54692
- if (transformChanged || !this._worldPositions || this._worldPositions.length === 0) {
54843
+ if (transformChanged) {
54693
54844
  this.updateWorldPositions();
54694
54845
  }
54695
54846
  const r = viewMatrix.rawData;
@@ -54744,21 +54895,25 @@ let GSplatStreamRenderer = class extends RenderNode {
54744
54895
  }
54745
54896
  this.splatOrder.updateTexture(this.size.x, this.size.y, this._orderData);
54746
54897
  const valid = Math.max(0, Math.min(this._validCount, ev.data.count | 0));
54747
- this.texParams[2] = valid;
54748
- this.texParams[0] = valid;
54898
+ this.setCount(valid);
54749
54899
  this._updateTexParams();
54750
54900
  const newInstanceCount = Math.ceil(valid / this._batchSize);
54751
54901
  this.instanceCount = newInstanceCount;
54752
54902
  };
54753
54903
  const centers = new Float32Array(this._validCount * 3);
54754
- const worldPos = this._worldPositions || this._positions;
54755
54904
  let centerIdx = 0;
54905
+ const worldMatrix = this.object3D.transform.worldMatrix;
54906
+ const localPos = this._positions;
54907
+ const m = worldMatrix.rawData;
54756
54908
  for (let i = 0; i < this._validCount; i++) {
54757
54909
  if (this._splatSetFlags[i]) {
54758
54910
  const srcIdx = i * 3;
54759
- centers[centerIdx * 3 + 0] = worldPos[srcIdx + 0];
54760
- centers[centerIdx * 3 + 1] = worldPos[srcIdx + 1];
54761
- centers[centerIdx * 3 + 2] = worldPos[srcIdx + 2];
54911
+ const x = localPos[srcIdx + 0];
54912
+ const y = localPos[srcIdx + 1];
54913
+ const z = localPos[srcIdx + 2];
54914
+ centers[centerIdx * 3 + 0] = m[0] * x + m[4] * y + m[8] * z + m[12];
54915
+ centers[centerIdx * 3 + 1] = m[1] * x + m[5] * y + m[9] * z + m[13];
54916
+ centers[centerIdx * 3 + 2] = m[2] * x + m[6] * y + m[10] * z + m[14];
54762
54917
  centerIdx++;
54763
54918
  }
54764
54919
  }
@@ -54774,14 +54929,19 @@ let GSplatStreamRenderer = class extends RenderNode {
54774
54929
  }
54775
54930
  if (!this._centersSent && this._sortWorker) {
54776
54931
  const centers = new Float32Array(this._validCount * 3);
54777
- const worldPos = this._worldPositions || this._positions;
54778
54932
  let centerIdx = 0;
54933
+ const worldMatrix = this.object3D.transform.worldMatrix;
54934
+ const localPos = this._positions;
54935
+ const m = worldMatrix.rawData;
54779
54936
  for (let i = 0; i < this._validCount; i++) {
54780
54937
  if (this._splatSetFlags[i]) {
54781
54938
  const srcIdx = i * 3;
54782
- centers[centerIdx * 3 + 0] = worldPos[srcIdx + 0];
54783
- centers[centerIdx * 3 + 1] = worldPos[srcIdx + 1];
54784
- centers[centerIdx * 3 + 2] = worldPos[srcIdx + 2];
54939
+ const x = localPos[srcIdx + 0];
54940
+ const y = localPos[srcIdx + 1];
54941
+ const z = localPos[srcIdx + 2];
54942
+ centers[centerIdx * 3 + 0] = m[0] * x + m[4] * y + m[8] * z + m[12];
54943
+ centers[centerIdx * 3 + 1] = m[1] * x + m[5] * y + m[9] * z + m[13];
54944
+ centers[centerIdx * 3 + 2] = m[2] * x + m[6] * y + m[10] * z + m[14];
54785
54945
  centerIdx++;
54786
54946
  }
54787
54947
  }
@@ -54941,12 +55101,17 @@ let GSplatStreamRenderer = class extends RenderNode {
54941
55101
  */
54942
55102
  setVisBoost(v) {
54943
55103
  this.texParams[3] = Math.max(0, v);
55104
+ this._texParamDirty = true;
54944
55105
  }
54945
55106
  setCount(c) {
54946
55107
  this.texParams[0] = Math.max(0, c);
55108
+ this._texParamDirty = true;
54947
55109
  }
54948
55110
  _updateTexParams() {
54949
- this.gsplatMaterial.setTexParams(this.texParams);
55111
+ if (this._texParamDirty) {
55112
+ this.gsplatMaterial.setTexParams(this.texParams);
55113
+ this._texParamDirty = false;
55114
+ }
54950
55115
  }
54951
55116
  /**
54952
55117
  * Set sort throttle interval (milliseconds)
@@ -55006,6 +55171,11 @@ let GSplatStreamRenderer = class extends RenderNode {
55006
55171
  * Update node before rendering
55007
55172
  */
55008
55173
  nodeUpdate(view, passType, renderPassState, clusterLightingBuffer) {
55174
+ if (this._validCount > 0 && view?.camera) {
55175
+ if (view.camera.viewMatrix) {
55176
+ this.scheduleOrder(view.camera.viewMatrix);
55177
+ }
55178
+ }
55009
55179
  if (this._pendingUpdates.size > 0 && this._frameCount >= 60) {
55010
55180
  this.flushUpdates();
55011
55181
  }
@@ -55013,6 +55183,7 @@ let GSplatStreamRenderer = class extends RenderNode {
55013
55183
  this._frameCount = 0;
55014
55184
  }
55015
55185
  this._frameCount++;
55186
+ this._updateTexParams();
55016
55187
  const worldMatrix = this.object3D.transform.worldMatrix;
55017
55188
  this.gsplatMaterial.setTransformMatrix(worldMatrix);
55018
55189
  const currentParams = `${this._minPixelCoverage},${this._maxPixelCoverage},${this._maxPixelCullDistance},${this._batchSize}`;
@@ -55094,7 +55265,6 @@ let GSplatStreamRenderer = class extends RenderNode {
55094
55265
  this.splatOrder = null;
55095
55266
  }
55096
55267
  this._positions = null;
55097
- this._worldPositions = null;
55098
55268
  this._orderData = null;
55099
55269
  this._colorData = null;
55100
55270
  this._transformAData = null;