@woosh/meep-engine 2.33.38 → 2.33.42

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 (40) hide show
  1. package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
  2. package/core/collection/array/typed/typed_array_copy.js +2 -2
  3. package/core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js +1 -1
  4. package/core/geom/3d/morton/mortonEncode_magicbits.js +7 -6
  5. package/core/geom/3d/morton/v3_morton_encode_transformed.js +15 -11
  6. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +193 -18
  7. package/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +2 -1
  8. package/engine/asset/loaders/GLTFAssetLoader.js +4 -8
  9. package/engine/ecs/System.d.ts +24 -1
  10. package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +1 -1
  11. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +20 -24
  12. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +1 -1
  13. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -2
  14. package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +9 -4
  15. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +7 -1
  16. package/engine/graphics/render/forward_plus/LightManager.js +295 -51
  17. package/engine/graphics/render/forward_plus/LightManager.spec.js +1 -1
  18. package/engine/graphics/render/forward_plus/PointLightData.js +9 -13
  19. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +10 -1
  20. package/engine/graphics/render/forward_plus/debug/LightClusterVolumeMaterial.js +1 -1
  21. package/engine/graphics/render/forward_plus/debug/buildLightClusterWidget.js +3 -1
  22. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +31 -18
  23. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +1 -0
  24. package/engine/graphics/render/forward_plus/model/AbstractLight.js +50 -0
  25. package/engine/graphics/render/forward_plus/model/Decal.js +68 -0
  26. package/engine/graphics/render/forward_plus/{PointLight.js → model/PointLight.js} +19 -11
  27. package/engine/graphics/render/forward_plus/{SpotLight.js → model/SpotLight.js} +20 -12
  28. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +6 -5
  29. package/engine/graphics/render/forward_plus/{prototypeLightManager.js → prototype/prototypeLightManager.js} +100 -25
  30. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +29 -20
  31. package/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +2 -0
  32. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  33. package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +19 -0
  34. package/engine/graphics/texture/atlas/CachingTextureAtlas.js +99 -0
  35. package/engine/graphics/texture/atlas/ManagedTextureAtlas.js +19 -39
  36. package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +75 -0
  37. package/engine/graphics/texture/atlas/TextureAtlas.js +22 -2
  38. package/engine/reference/v2/Reference.d.ts +4 -0
  39. package/engine/reference/v2/Reference.js +3 -1
  40. package/package.json +1 -1
@@ -1,6 +1,18 @@
1
1
  import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
2
2
  import { PointLightData } from "./PointLightData.js";
3
- import { DataTexture, DataTexture3D, Frustum, NearestFilter, RGBIntegerFormat, UnsignedShortType } from "three";
3
+ import {
4
+ ClampToEdgeWrapping,
5
+ DataTexture,
6
+ DataTexture3D,
7
+ Frustum,
8
+ LinearFilter,
9
+ LinearMipMapLinearFilter,
10
+ NearestFilter,
11
+ RGBAFormat,
12
+ RGBIntegerFormat,
13
+ UnsignedByteType,
14
+ UnsignedShortType
15
+ } from "three";
4
16
  import { frustumFromCamera } from "../../ecs/camera/CameraSystem.js";
5
17
  import Vector3 from "../../../../core/geom/Vector3.js";
6
18
  import { query_bvh_frustum_from_objects } from "./query/query_bvh_frustum_from_objects.js";
@@ -23,9 +35,15 @@ import { read_frustum_corner } from "./read_frustum_corner.js";
23
35
  import { BinaryUint32BVH } from "../../../../core/bvh2/binary/2/BinaryUint32BVH.js";
24
36
  import { query_bvh_frustum_from_texture } from "./query/query_bvh_frustum_from_texture.js";
25
37
  import { mat4 } from "gl-matrix";
26
- import { mortonEncode_magicbits } from "../../../../core/geom/3d/morton/mortonEncode_magicbits.js";
38
+ import { TextureAtlas } from "../../texture/atlas/TextureAtlas.js";
39
+ import { CachingTextureAtlas } from "../../texture/atlas/CachingTextureAtlas.js";
40
+ import { writeSample2DDataToDataTexture } from "../../texture/sampler/writeSampler2DDataToDataTexture.js";
41
+ import { Decal } from "./model/Decal.js";
42
+ import { ReferencedTextureAtlas } from "../../texture/atlas/ReferencedTextureAtlas.js";
43
+ import { v3_morton_encode_transformed } from "../../../../core/geom/3d/morton/v3_morton_encode_transformed.js";
44
+ import { v3_distance } from "../../../../core/geom/v3_distance.js";
27
45
 
28
- const LOOKUP_CACHE_SIZE = 16384; // must be power of two
46
+ const LOOKUP_CACHE_SIZE = 1024; // must be power of two
29
47
 
30
48
  /**
31
49
  * Using continuous buffer for related attributes to get better cache utilization
@@ -65,6 +83,38 @@ const LOOKUP_CACHE = new Uint32Array(_scratch_array_buffer, (24 + 24) * 4, LOOKU
65
83
  */
66
84
  const scratch_light_nodes = [];
67
85
 
86
+ /**
87
+ * How many bits are used to encode light type
88
+ * @type {number}
89
+ */
90
+ const LIGHT_ENCODING_TYPE_BIT_COUNT = 2;
91
+
92
+ /**
93
+ *
94
+ * @param {AbstractLight|PointLight|Decal} light
95
+ * @returns {number}
96
+ */
97
+ function encode_light_type(light) {
98
+ if (light.isPointLight === true) {
99
+ return 0;
100
+ } else if (light.isDecal === true) {
101
+ return 3;
102
+ } else {
103
+ throw new Error('Unsupported light type');
104
+ }
105
+ }
106
+
107
+ /**
108
+ *
109
+ * @param {number} index
110
+ * @param {AbstractLight} light
111
+ * @returns {number}
112
+ */
113
+ function encode_light_descriptor(index, light) {
114
+ const light_type = encode_light_type(light);
115
+ return light_type | (index << 2);
116
+ }
117
+
68
118
  export class LightManager {
69
119
 
70
120
  constructor() {
@@ -77,7 +127,7 @@ export class LightManager {
77
127
 
78
128
  /**
79
129
  *
80
- * @type {Map<PointLight, PointLightData>}
130
+ * @type {Map<AbstractLight, PointLightData>}
81
131
  * @private
82
132
  */
83
133
  this.__light_point_data = new Map();
@@ -98,6 +148,7 @@ export class LightManager {
98
148
  1,
99
149
  );
100
150
 
151
+ this.__cluster_texture.flipY = false;
101
152
  this.__cluster_texture.generateMipmaps = false;
102
153
 
103
154
  this.__cluster_texture.magFilter = NearestFilter;
@@ -107,6 +158,12 @@ export class LightManager {
107
158
  this.__cluster_texture.format = RGBIntegerFormat;
108
159
  this.__cluster_texture.internalFormat = "RGB16UI";
109
160
 
161
+ /**
162
+ *
163
+ * @type {TextureBackedMemoryRegion}
164
+ * @readonly
165
+ * @private
166
+ */
110
167
  this.__lookup_data = new TextureBackedMemoryRegion();
111
168
  this.__lookup_data.type = NumericType.Uint;
112
169
  this.__lookup_data.channel_count = 1;
@@ -116,6 +173,7 @@ export class LightManager {
116
173
  /**
117
174
  *
118
175
  * @type {TextureBackedMemoryRegion}
176
+ * @readonly
119
177
  * @private
120
178
  */
121
179
  this.__light_data = new TextureBackedMemoryRegion();
@@ -124,9 +182,49 @@ export class LightManager {
124
182
  this.__light_data.channel_count = 4;
125
183
  this.__light_data.resize(8);
126
184
 
185
+ /**
186
+ * @type {DataTexture}
187
+ * @readonly
188
+ * @private
189
+ */
190
+ this.__decal_atlas_texture = new DataTexture(new Uint8Array(4), 1, 1, RGBAFormat);
191
+ this.__decal_atlas_texture.type = UnsignedByteType;
192
+ this.__decal_atlas_texture.flipY = false;
193
+ this.__decal_atlas_texture.wrapS = ClampToEdgeWrapping;
194
+ this.__decal_atlas_texture.wrapT = ClampToEdgeWrapping;
195
+ this.__decal_atlas_texture.minFilter = LinearMipMapLinearFilter;
196
+ this.__decal_atlas_texture.magFilter = LinearFilter;
197
+ this.__decal_atlas_texture.generateMipmaps = true;
198
+ this.__decal_atlas_texture.anisotropy = 4;
199
+
200
+ /**
201
+ *
202
+ * @type {CachingTextureAtlas}
203
+ * @readonly
204
+ * @private
205
+ */
206
+ this.__decal_atlas = new CachingTextureAtlas({
207
+ atlas: new TextureAtlas(16)
208
+ });
209
+
210
+ /**
211
+ *
212
+ * @type {ReferencedTextureAtlas}
213
+ * @private
214
+ */
215
+ this.__decal_patch_references = new ReferencedTextureAtlas(this.__decal_atlas);
216
+
217
+ /**
218
+ *
219
+ * @type {Map<Decal, Reference>}
220
+ * @private
221
+ */
222
+ this.__decal_references = new Map();
223
+
127
224
  /**
128
225
  *
129
226
  * @type {IncrementalDeltaSet<PointLightData>}
227
+ * @readonly
130
228
  * @private
131
229
  */
132
230
  this.__visible_lights = new IncrementalDeltaSet();
@@ -174,25 +272,43 @@ export class LightManager {
174
272
  */
175
273
  this.__cluster_frustum_points = new Float32Array(1);
176
274
 
177
-
178
275
  this.setTileMapResolution(32, 16, 16);
179
276
 
180
-
181
277
  this.__visible_lights.onAdded.add(this.__handle_visible_added, this);
182
278
  this.__visible_lights.onRemoved.add(this.__handle_visible_removed, this);
183
279
 
280
+ /**
281
+ *
282
+ * @type {boolean}
283
+ * @private
284
+ */
285
+ this.__light_data_needs_update = true;
286
+
287
+ /**
288
+ *
289
+ * @type {boolean}
290
+ * @private
291
+ */
184
292
  this.__visible_bvh_needs_update = true;
293
+
294
+ this.__decal_atlas.atlas.on.painted.add(this.__update_decal_atlas_texture, this);
295
+ }
296
+
297
+ __update_decal_atlas_texture() {
298
+ const sampler = this.__decal_atlas.atlas.sampler;
299
+
300
+ writeSample2DDataToDataTexture(sampler, this.__decal_atlas_texture);
185
301
  }
186
302
 
187
303
  /**
188
304
  * Sometimes light lookup table can get quite large, to make sure we can store these addresses in the cluster texture,
189
305
  * we may need to switch to a larger data type, such as Uint8->Uint16 or Uint16->Uint32
190
- * @param {number} value How many bits should be addressable from the cluster content
306
+ * @param {number} bit_count How many bits should be addressable from the cluster content
191
307
  * @returns {boolean} true if texture was rebuilt (underlying type change), false otherwise
192
308
  * @private
193
309
  */
194
- __set_cluster_addressable_bit_range(value) {
195
- const rounded_value = Math.ceil(value);
310
+ __set_cluster_addressable_bit_range(bit_count) {
311
+ const rounded_value = Math.ceil(bit_count);
196
312
 
197
313
  this.__cluster_texture_precision = rounded_value;
198
314
  const dataType = computeDataType(NumericType.Uint, rounded_value);
@@ -272,13 +388,23 @@ export class LightManager {
272
388
  }
273
389
 
274
390
  /**
275
- *
276
391
  * @returns {DataTexture3D}
277
392
  */
278
393
  getTextureClusters() {
279
394
  return this.__cluster_texture;
280
395
  }
281
396
 
397
+ /**
398
+ * @returns {DataTexture}
399
+ */
400
+ getDecalTexture() {
401
+ return this.__decal_atlas_texture;
402
+ }
403
+
404
+ /**
405
+ * NOTE: do not modify the value
406
+ * @returns {Readonly<Vector3>}
407
+ */
282
408
  getResolution() {
283
409
  return this.__tiles_resolution;
284
410
  }
@@ -297,9 +423,17 @@ export class LightManager {
297
423
  * @private
298
424
  */
299
425
  __handle_visible_added(data) {
300
- this.__visible_bvh_needs_update = true;
426
+ this.__light_data_needs_update = true;
427
+
428
+ const light = data.light;
301
429
 
302
- data.light.onDimensionChanged(this.__request_update_visible_bvh, this);
430
+ light.onDimensionChanged(this.__request_update_visible_bvh, this);
431
+
432
+ if (light instanceof Decal) {
433
+ const ref = this.__decal_patch_references.acquire(light.texture_diffuse);
434
+
435
+ this.__decal_references.set(light, ref);
436
+ }
303
437
  }
304
438
 
305
439
  /**
@@ -308,24 +442,77 @@ export class LightManager {
308
442
  * @private
309
443
  */
310
444
  __handle_visible_removed(data) {
311
- this.__visible_bvh_needs_update = true;
445
+ this.__light_data_needs_update = true;
446
+
447
+ const light = data.light;
448
+ light.offDimensionChanged(this.__request_update_visible_bvh, this);
312
449
 
313
- data.bvh_leaf_visible.disconnect();
450
+ if (light instanceof Decal) {
451
+ const ref = this.__decal_references.get(light);
314
452
 
315
- data.light.offDimensionChanged(this.__request_update_visible_bvh, this);
453
+ ref.release();
454
+
455
+ this.__decal_references.delete(light);
456
+ }
316
457
  }
317
458
 
318
459
  /**
319
460
  *
320
461
  * @param {PointLightData} light
321
462
  * @returns {number}
322
- * @private
463
+ * @protected
323
464
  */
324
465
  __sort_visible_light_score(light) {
325
- const p = light.light.position;
466
+ const center = scratch_corners;
467
+
468
+ light.light.getCenter(center)
469
+
470
+ const x = center[0];
471
+ const y = center[1];
472
+ const z = center[2];
326
473
 
327
- // return v3_morton_encode_transformed(p.x, p.y, p.z, this.__projection_matrix);
328
- return mortonEncode_magicbits(p.x, p.y, p.z);
474
+ return v3_morton_encode_transformed(x, y, z, this.__projection_matrix);
475
+ }
476
+
477
+ /**
478
+ * DEBUG method
479
+ * @param {PointLightData} lights
480
+ * @param {number} count
481
+ * @returns {number} lower = better sorting score
482
+ * @private
483
+ */
484
+ __assess_sorting_score(lights, count) {
485
+
486
+ let r = 0;
487
+
488
+ const center_a = [];
489
+ const center_b = [];
490
+
491
+ for (let i = 0; i < count; i++) {
492
+ const a = lights[i];
493
+
494
+ const score_a = this.__sort_visible_light_score(a);
495
+ a.light.getCenter(center_a);
496
+
497
+ for (let j = i + 1; j < count; j++) {
498
+ const b = lights[j];
499
+
500
+ const score_b = this.__sort_visible_light_score(b);
501
+ b.light.getCenter(center_b);
502
+
503
+ //
504
+ const score_distance = Math.abs(score_a - score_b);
505
+ const position_distance = v3_distance(
506
+ center_a[0], center_a[1], center_a[2],
507
+ center_b[0], center_b[1], center_b[2],
508
+ );
509
+
510
+ r += score_distance / position_distance;
511
+ }
512
+ }
513
+
514
+
515
+ return r / (count * (count - 1) * 0.5);
329
516
  }
330
517
 
331
518
  /**
@@ -333,7 +520,10 @@ export class LightManager {
333
520
  * @private
334
521
  */
335
522
  __sort_visible_light() {
336
- this.__visible_lights.sort(this.__sort_visible_light_score, this);
523
+ this.__visible_lights.sort(
524
+ this.__sort_visible_light_score,
525
+ this
526
+ );
337
527
  }
338
528
 
339
529
  __update_visible_bvh() {
@@ -342,8 +532,6 @@ export class LightManager {
342
532
  const lights = this.__visible_lights.elements;
343
533
  const light_count = lights.length;
344
534
 
345
- // sort light for better search and query locality
346
- this.__sort_visible_light();
347
535
 
348
536
  const vbvh = this.__visible_bvh;
349
537
 
@@ -360,8 +548,10 @@ export class LightManager {
360
548
 
361
549
  const bb = datum.bvh_leaf_main;
362
550
 
551
+ const payload = encode_light_descriptor(datum.address, datum.light);
552
+
363
553
  vbvh.setLeafData(
364
- i, i,
554
+ i, payload,
365
555
  bb.x0, bb.y0, bb.z0,
366
556
  bb.x1, bb.y1, bb.z1
367
557
  );
@@ -417,9 +607,6 @@ export class LightManager {
417
607
 
418
608
  visible_lights.finalizeUpdate();
419
609
 
420
- if (this.__visible_bvh_needs_update) {
421
- this.__update_visible_bvh();
422
- }
423
610
  }
424
611
 
425
612
  __write_light_data_texture() {
@@ -433,14 +620,33 @@ export class LightManager {
433
620
  // write light data into texture
434
621
  const visible_light_count = visible_lights.length;
435
622
 
436
- this.__light_data.resize(visible_light_count * 2);
623
+ // compute amount of space required for the lights
624
+ let address = 0;
625
+ for (let i = 0; i < visible_light_count; i++) {
626
+ const datum = visible_lights[i];
627
+
628
+ /**
629
+ *
630
+ * @type {PointLight}
631
+ */
632
+ const light = datum.light;
633
+
634
+ address += light.ENCODED_SLOT_COUNT;
635
+ }
636
+
437
637
 
438
- this.__light_data.update();
638
+ const light_data = this.__light_data;
639
+ light_data.resize(Math.ceil(address / 4));
640
+
641
+ light_data.update();
439
642
 
440
643
  // update required lookup precision
441
- this.__lookup_data.precision = Math.max(0, Math.ceil(Math.log2(this.__light_data.size)));
644
+ this.__lookup_data.precision = Math.max(
645
+ 0,
646
+ Math.ceil(Math.log2(light_data.size))
647
+ ) + LIGHT_ENCODING_TYPE_BIT_COUNT;
442
648
 
443
- const tx_light = this.__light_data.getTexture();
649
+ const tx_light = light_data.getTexture();
444
650
 
445
651
  /**
446
652
  *
@@ -448,13 +654,12 @@ export class LightManager {
448
654
  */
449
655
  const tx_light_data = tx_light.image.data;
450
656
 
657
+ address = 0;
658
+
451
659
  for (let i = 0; i < visible_light_count; i++) {
452
660
  const datum = visible_lights[i];
453
661
 
454
-
455
- const address = i * 8;
456
-
457
- assert.lessThan(address, tx_light_data.length, "overflow")
662
+ assert.lessThan(address, tx_light_data.length, "overflow");
458
663
 
459
664
  /**
460
665
  *
@@ -462,10 +667,21 @@ export class LightManager {
462
667
  */
463
668
  const light = datum.light;
464
669
 
465
- light.toArray(tx_light_data, address);
670
+ datum.address = address >> 2;
671
+
672
+ const written_slots = light.toArray(tx_light_data, address);
673
+
674
+ address += written_slots;
675
+
676
+ // align address to 4 slot boundary
677
+ if ((address & 3) !== 0) {
678
+ address = ((address >> 2) + 1) << 2;
679
+ }
466
680
  }
467
681
 
468
682
  tx_light.needsUpdate = true;
683
+
684
+ this.__visible_bvh_needs_update = true;
469
685
  }
470
686
 
471
687
  __assign_lights_to_clusters() {
@@ -522,11 +738,15 @@ export class LightManager {
522
738
  // clear cache
523
739
  LOOKUP_CACHE.fill(0xFFFFFFFF);
524
740
 
741
+ // console.log('Assignment Start');
742
+
525
743
  for (i_z_0 = 0; i_z_0 < tr_z; i_z_0++) {
526
744
  const i_z_1 = i_z_0 + 1;
527
745
 
528
746
  // construct z planes
529
747
 
748
+ const slice_offset = i_z_0 * tile_slice_size;
749
+
530
750
  const z_plane_index_offset_0 = cluster_planes_z_offset + i_z_0 * 4;
531
751
 
532
752
  read_plane_pair(cluster_planes, z_plane_index_offset_0, scratch_frustum_planes, 16);
@@ -553,25 +773,25 @@ export class LightManager {
553
773
  const frustum_point_index_000 = i_z_0 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_0;
554
774
  read_frustum_corner(cluster_frustum_points, frustum_point_index_000, scratch_corners, 0);
555
775
 
556
- const frustum_point_index_001 = i_z_1 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_0;
557
- read_frustum_corner(cluster_frustum_points, frustum_point_index_001, scratch_corners, 3);
776
+ const i_x_1 = i_x_0 + 1;
777
+
778
+ const frustum_point_index_100 = i_z_0 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_1;
779
+ read_frustum_corner(cluster_frustum_points, frustum_point_index_100, scratch_corners, 12);
558
780
 
559
781
  const frustum_point_index_010 = i_z_0 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_0;
560
782
  read_frustum_corner(cluster_frustum_points, frustum_point_index_010, scratch_corners, 6);
561
783
 
562
- const frustum_point_index_011 = i_z_1 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_0;
563
- read_frustum_corner(cluster_frustum_points, frustum_point_index_011, scratch_corners, 9);
564
-
565
- const i_x_1 = i_x_0 + 1;
784
+ const frustum_point_index_110 = i_z_0 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_1;
785
+ read_frustum_corner(cluster_frustum_points, frustum_point_index_110, scratch_corners, 18);
566
786
 
567
- const frustum_point_index_100 = i_z_0 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_1;
568
- read_frustum_corner(cluster_frustum_points, frustum_point_index_100, scratch_corners, 12);
787
+ const frustum_point_index_001 = i_z_1 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_0;
788
+ read_frustum_corner(cluster_frustum_points, frustum_point_index_001, scratch_corners, 3);
569
789
 
570
790
  const frustum_point_index_101 = i_z_1 * tr_xy_1 + i_y_0 * tr_x_1 + i_x_1;
571
791
  read_frustum_corner(cluster_frustum_points, frustum_point_index_101, scratch_corners, 15);
572
792
 
573
- const frustum_point_index_110 = i_z_0 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_1;
574
- read_frustum_corner(cluster_frustum_points, frustum_point_index_110, scratch_corners, 18);
793
+ const frustum_point_index_011 = i_z_1 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_0;
794
+ read_frustum_corner(cluster_frustum_points, frustum_point_index_011, scratch_corners, 9);
575
795
 
576
796
  const frustum_point_index_111 = i_z_1 * tr_xy_1 + i_y_1 * tr_x_1 + i_x_1;
577
797
  read_frustum_corner(cluster_frustum_points, frustum_point_index_111, scratch_corners, 21);
@@ -587,7 +807,7 @@ export class LightManager {
587
807
  scratch_corners
588
808
  );
589
809
 
590
- const tile_index = (i_z_0 * tile_slice_size) + (i_y_0 * tr_x) + (tr_x - i_x_1);
810
+ const tile_index = slice_offset + (i_y_0 * tr_x) + i_x_0;
591
811
 
592
812
  const tile_address = tile_index * 3;
593
813
 
@@ -607,7 +827,6 @@ export class LightManager {
607
827
  Through experimentation, sorting was taking around 20% of the whole assignment time
608
828
  while improving number of cache hits by around 40% (8000 without sorting -> 11000 with sorting)
609
829
  */
610
-
611
830
  const cluster_data_hash = compute_light_data_hash_0(scratch_light_nodes, match_count) & (LOOKUP_CACHE_SIZE - 1);
612
831
 
613
832
  const existing_lookup_address = LOOKUP_CACHE[cluster_data_hash];
@@ -641,12 +860,12 @@ export class LightManager {
641
860
  for (i = 0; i < match_count; i++) {
642
861
  /**
643
862
  *
644
- * @type {number[]}
863
+ * @type {number}
645
864
  */
646
- const light_index = scratch_light_nodes[i];
865
+ const light_descriptor = scratch_light_nodes[i];
647
866
 
648
867
  // construct lookup table
649
- light_lookup_texture_data[lookup_address_offset] = light_index * 2;
868
+ light_lookup_texture_data[lookup_address_offset] = light_descriptor;
650
869
 
651
870
  lookup_address_offset++;
652
871
  }
@@ -818,11 +1037,22 @@ export class LightManager {
818
1037
  this.__build_visible_light_list();
819
1038
  // console.timeEnd('__build_visible_light_list');
820
1039
 
1040
+ // update decal atlas
1041
+ this.__decal_atlas.atlas.update();
821
1042
 
822
1043
  // console.time('__write_light_data_texture');
823
- this.__write_light_data_texture();
1044
+ if (this.__light_data_needs_update) {
1045
+ // sort light for better search and query locality
1046
+ this.__sort_visible_light();
1047
+
1048
+ this.__write_light_data_texture();
1049
+ }
824
1050
  // console.timeEnd('__write_light_data_texture');
825
1051
 
1052
+ if (this.__visible_bvh_needs_update) {
1053
+ this.__update_visible_bvh();
1054
+ }
1055
+
826
1056
  this.__build_cluster_frustum_points();
827
1057
  // console.time('__build_cluster_frustum_planes');
828
1058
  this.__build_cluster_frustum_planes();
@@ -848,6 +1078,11 @@ export class LightManager {
848
1078
  setTileMapResolution(x, y, z) {
849
1079
  const r = this.__tiles_resolution;
850
1080
 
1081
+ if (x === r.x && y === r.y && z === r.z) {
1082
+ // special case, no change
1083
+ return;
1084
+ }
1085
+
851
1086
  r.set(x, y, z);
852
1087
 
853
1088
  this.__cluster_texture_needs_rebuild = true;
@@ -868,6 +1103,10 @@ export class LightManager {
868
1103
  );
869
1104
  }
870
1105
 
1106
+ /**
1107
+ *
1108
+ * @param {AbstractLight} light
1109
+ */
871
1110
  addLight(light) {
872
1111
  const lightData = new PointLightData(light);
873
1112
 
@@ -878,6 +1117,11 @@ export class LightManager {
878
1117
  this.__light_point_data.set(light, lightData);
879
1118
  }
880
1119
 
1120
+ /**
1121
+ *
1122
+ * @param {AbstractLight} light
1123
+ * @returns {boolean}
1124
+ */
881
1125
  removeLight(light) {
882
1126
 
883
1127
  const data = this.__light_point_data.get(light);
@@ -1,5 +1,5 @@
1
1
  import { LightManager } from "./LightManager.js";
2
- import { PointLight } from "./PointLight.js";
2
+ import { PointLight } from "./model/PointLight.js";
3
3
  import { PerspectiveCamera } from "three";
4
4
 
5
5
  test('addLight does not throw', () => {
@@ -3,35 +3,33 @@ import { LeafNode } from "../../../../core/bvh2/LeafNode.js";
3
3
  export class PointLightData {
4
4
  /**
5
5
  *
6
- * @param {PointLight|SpotLight} light
6
+ * @param {AbstractLight} light
7
7
  */
8
8
  constructor(light) {
9
+ /**
10
+ *
11
+ * @type {AbstractLight}
12
+ */
9
13
  this.light = light;
10
14
 
11
-
12
- this.bvh_leaf_main = new LeafNode(this, 0, 0, 0, 0, 0, 0);
13
-
14
- this.bvh_leaf_visible = new LeafNode(this, 0, 0, 0, 0, 0, 0);
15
-
16
15
  /**
17
- * @deprecated
16
+ *
18
17
  * @type {number}
19
18
  */
20
- this.visible_index = 0;
19
+ this.address = 0;
20
+
21
+ this.bvh_leaf_main = new LeafNode(this, 0, 0, 0, 0, 0, 0);
21
22
  }
22
23
 
23
24
  update() {
24
25
 
25
26
  const leaf = this.bvh_leaf_main;
26
- const leaf_2 = this.bvh_leaf_visible;
27
27
 
28
28
  this.light.getAABB(leaf);
29
29
 
30
30
  if (leaf.parentNode !== null) {
31
31
  leaf.parentNode.bubbleRefit();
32
32
  }
33
-
34
- leaf_2.resize(leaf.x0, leaf.y0, leaf.z0, leaf.x1, leaf.y1, leaf.z1);
35
33
  }
36
34
 
37
35
  link() {
@@ -46,7 +44,5 @@ export class PointLightData {
46
44
 
47
45
  // disconnect from bvh
48
46
  this.bvh_leaf_main.disconnect();
49
-
50
- this.bvh_leaf_visible.disconnect();
51
47
  }
52
48
  }
@@ -86,6 +86,10 @@ export class TextureBackedMemoryRegion {
86
86
  this.__data_type = DataType.Uint8;
87
87
  }
88
88
 
89
+ get concrete_type(){
90
+ return this.__data_type;
91
+ }
92
+
89
93
  /**
90
94
  *
91
95
  * @param {number} v
@@ -228,9 +232,14 @@ export class TextureBackedMemoryRegion {
228
232
  * @param {number} size
229
233
  */
230
234
  resize(size) {
235
+ assert.isNonNegativeInteger(size, 'size');
236
+
231
237
  this.size = size;
232
238
 
233
- const target_height = max2(Math.ceil(size / DATA_TEXTURE_WIDTH), 1);
239
+ const target_height = max2(
240
+ Math.ceil(size / DATA_TEXTURE_WIDTH),
241
+ 1
242
+ );
234
243
 
235
244
  const current_height = this.__texture.image.height;
236
245
 
@@ -41,7 +41,7 @@ const fragmentShader = /* glsl */`
41
41
  return vec2( t0, t1 );
42
42
  }
43
43
  float sample1( vec3 p ) {
44
- return float( texture( map, vec3( 1.0 - p.x, p.yz )).g );
44
+ return float( texture( map, p ).g );
45
45
  }
46
46
  #define epsilon .0001
47
47
  vec3 normal( vec3 coord ) {