@woosh/meep-engine 2.165.7 → 2.166.0

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 (136) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/package.json +1 -1
  3. package/src/CORRECTNESS_HUNT_2026_07_24.md +142 -0
  4. package/src/core/binary/BinaryBuffer.js +1 -1
  5. package/src/core/binary/EncodingBinaryBuffer.d.ts.map +1 -1
  6. package/src/core/binary/EncodingBinaryBuffer.js +3 -1
  7. package/src/core/cache/Cache.d.ts.map +1 -1
  8. package/src/core/cache/Cache.js +0 -4
  9. package/src/core/cache/CacheElement.d.ts.map +1 -1
  10. package/src/core/cache/CacheElement.js +4 -0
  11. package/src/core/cache/FrequencySketch.d.ts +0 -21
  12. package/src/core/cache/FrequencySketch.d.ts.map +1 -1
  13. package/src/core/cache/FrequencySketch.js +66 -65
  14. package/src/core/cache/wtinylfu/CacheElementWTinylfu.d.ts +17 -0
  15. package/src/core/cache/wtinylfu/CacheElementWTinylfu.d.ts.map +1 -0
  16. package/src/core/cache/wtinylfu/CacheElementWTinylfu.js +18 -0
  17. package/src/core/cache/wtinylfu/CacheRegionType.d.ts +10 -0
  18. package/src/core/cache/wtinylfu/CacheRegionType.d.ts.map +1 -0
  19. package/src/core/cache/wtinylfu/CacheRegionType.js +10 -0
  20. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts +66 -0
  21. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts.map +1 -0
  22. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.js +183 -0
  23. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts +279 -0
  24. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts.map +1 -0
  25. package/src/core/cache/wtinylfu/CacheWTinylfu.js +807 -0
  26. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +243 -0
  27. package/src/core/cache/wtinylfu/wtinylfuDecisions.d.ts +80 -0
  28. package/src/core/cache/wtinylfu/wtinylfuDecisions.d.ts.map +1 -0
  29. package/src/core/cache/wtinylfu/wtinylfuDecisions.js +102 -0
  30. package/src/core/collection/RingBuffer.d.ts.map +1 -1
  31. package/src/core/collection/RingBuffer.js +15 -3
  32. package/src/core/collection/map/HashMap.d.ts +1 -1
  33. package/src/core/collection/map/HashMap.d.ts.map +1 -1
  34. package/src/core/collection/map/HashMap.js +5 -17
  35. package/src/core/geom/2d/line/line2_compute_segment_point_distance_sqr.d.ts.map +1 -1
  36. package/src/core/geom/2d/line/line2_compute_segment_point_distance_sqr.js +5 -0
  37. package/src/core/geom/ConicRay.d.ts.map +1 -1
  38. package/src/core/geom/ConicRay.js +9 -2
  39. package/src/core/geom/Quaternion.d.ts.map +1 -1
  40. package/src/core/geom/Quaternion.js +7 -3
  41. package/src/core/math/build_gaussian_kernel_1d.d.ts +2 -2
  42. package/src/core/math/build_gaussian_kernel_1d.d.ts.map +1 -1
  43. package/src/core/math/build_gaussian_kernel_1d.js +4 -2
  44. package/src/core/math/build_gaussian_kernel_2d.d.ts +2 -2
  45. package/src/core/math/build_gaussian_kernel_2d.d.ts.map +1 -1
  46. package/src/core/math/build_gaussian_kernel_2d.js +4 -2
  47. package/src/core/math/gaussian.d.ts +2 -2
  48. package/src/core/math/gaussian.js +2 -2
  49. package/src/core/math/spline/spline3_bezier_bounds.d.ts.map +1 -1
  50. package/src/core/math/spline/spline3_bezier_bounds.js +10 -3
  51. package/src/core/math/spline/spline3_bezier_to_hermite.d.ts +8 -7
  52. package/src/core/math/spline/spline3_bezier_to_hermite.d.ts.map +1 -1
  53. package/src/core/math/spline/spline3_bezier_to_hermite.js +13 -12
  54. package/src/core/math/spline/spline3_hermite_bounds.d.ts.map +1 -1
  55. package/src/core/math/spline/spline3_hermite_bounds.js +10 -3
  56. package/src/core/math/spline/spline3_hermite_bounds_t.d.ts.map +1 -1
  57. package/src/core/math/spline/spline3_hermite_bounds_t.js +115 -109
  58. package/src/core/math/spline/spline3_hermite_to_bezier.d.ts +2 -0
  59. package/src/core/math/spline/spline3_hermite_to_bezier.d.ts.map +1 -1
  60. package/src/core/math/spline/spline3_hermite_to_bezier.js +2 -0
  61. package/src/core/math/statistics/computeStatisticalMean.js +1 -1
  62. package/src/core/math/statistics/gaussian_amplitude.d.ts.map +1 -1
  63. package/src/core/math/statistics/gaussian_amplitude.js +3 -1
  64. package/src/engine/animation/clip/ecd_bind_animation_curve.d.ts.map +1 -1
  65. package/src/engine/animation/clip/ecd_bind_animation_curve.js +10 -1
  66. package/src/engine/animation/clip/hemisphere_align_quaternion_values.d.ts +20 -0
  67. package/src/engine/animation/clip/hemisphere_align_quaternion_values.d.ts.map +1 -0
  68. package/src/engine/animation/clip/hemisphere_align_quaternion_values.js +37 -0
  69. package/src/engine/animation/keyed2/AnimationTrackPlayback.d.ts.map +1 -1
  70. package/src/engine/animation/keyed2/AnimationTrackPlayback.js +5 -1
  71. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  72. package/src/engine/ecs/EntityComponentDataset.js +5 -21
  73. package/src/engine/ecs/fow/FogOfWar.d.ts +9 -0
  74. package/src/engine/ecs/fow/FogOfWar.d.ts.map +1 -1
  75. package/src/engine/ecs/fow/FogOfWar.js +133 -54
  76. package/src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.d.ts.map +1 -1
  77. package/src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js +3 -0
  78. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts.map +1 -1
  79. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js +3 -1
  80. package/src/engine/graphics/GraphicsEngine.d.ts +5 -1
  81. package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
  82. package/src/engine/graphics/GraphicsEngine.js +14 -3
  83. package/src/engine/graphics/composit/CompositLayer.d.ts.map +1 -1
  84. package/src/engine/graphics/composit/CompositLayer.js +258 -255
  85. package/src/engine/graphics/composit/LayerCompositer.d.ts +12 -0
  86. package/src/engine/graphics/composit/LayerCompositer.d.ts.map +1 -1
  87. package/src/engine/graphics/composit/LayerCompositer.js +19 -10
  88. package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.d.ts +1 -1
  89. package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.d.ts.map +1 -1
  90. package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +10 -4
  91. package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.d.ts +6 -0
  92. package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.d.ts.map +1 -1
  93. package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.js +21 -0
  94. package/src/engine/graphics/ecs/path/ribbon/RibbonPathBuilder.d.ts.map +1 -1
  95. package/src/engine/graphics/ecs/path/ribbon/RibbonPathBuilder.js +5 -23
  96. package/src/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.d.ts.map +1 -1
  97. package/src/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.js +6 -4
  98. package/src/engine/graphics/ecs/water/WaterSystem.d.ts.map +1 -1
  99. package/src/engine/graphics/ecs/water/WaterSystem.js +9 -3
  100. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts +12 -0
  101. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts.map +1 -1
  102. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +46 -9
  103. package/src/engine/graphics/particles/particular/engine/ParticularEngine.d.ts +5 -0
  104. package/src/engine/graphics/particles/particular/engine/ParticularEngine.d.ts.map +1 -1
  105. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +8 -0
  106. package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.d.ts +7 -0
  107. package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.d.ts.map +1 -1
  108. package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.js +8 -0
  109. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.d.ts +10 -2
  110. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.d.ts.map +1 -1
  111. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +42 -10
  112. package/src/engine/graphics/render/buffer/FrameBuffer.d.ts.map +1 -1
  113. package/src/engine/graphics/render/buffer/FrameBuffer.js +5 -2
  114. package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts +13 -1
  115. package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts.map +1 -1
  116. package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +40 -7
  117. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.d.ts.map +1 -1
  118. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +10 -4
  119. package/src/engine/graphics/render/forward_plus/LightManager.d.ts.map +1 -1
  120. package/src/engine/graphics/render/forward_plus/LightManager.js +1235 -1232
  121. package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +5 -0
  122. package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts.map +1 -1
  123. package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +11 -10
  124. package/src/engine/graphics/trail/tube/TubeX.d.ts.map +1 -1
  125. package/src/engine/graphics/trail/tube/TubeX.js +557 -555
  126. package/src/engine/graphics/trail/x/RibbonXPlugin.d.ts +12 -1
  127. package/src/engine/graphics/trail/x/RibbonXPlugin.d.ts.map +1 -1
  128. package/src/engine/graphics/trail/x/RibbonXPlugin.js +15 -8
  129. package/src/engine/input/ecs/systems/InputControllerSystem.d.ts.map +1 -1
  130. package/src/engine/input/ecs/systems/InputControllerSystem.js +9 -6
  131. package/src/engine/navigation/ecs/components/Path.d.ts +5 -2
  132. package/src/engine/navigation/ecs/components/Path.d.ts.map +1 -1
  133. package/src/engine/navigation/ecs/components/Path.js +10 -4
  134. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +1 -1
  135. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  136. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationTrackPlayback.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/keyed2/AnimationTrackPlayback.js"],"names":[],"mappings":";AAGA;IACI;;;;;;;;OAQG;IACH,4EAuBC;IAtBG,sBAAkB;IAClB,cAA+B;IAE/B,oBAAoC;IACpC,kBAAgC;IAEhC,uBAAuB;IACvB,8BAA8B;IAE9B,uBAAuB;IACvB,sBAAsB;IAEtB,gBAAmB;IAEnB,4BAA0D;IAG1D;;MAEC;IAKL;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,gBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;OAGG;IACH,WAFW,OAAO,QAIjB;IAED,cAEC;IAED;;;OAGG;IACH,kBAFW,MAAM,QA2BhB;IAED;;;OAGG;IACH,cAFa,OAAO,CA2CnB;IAED;;;OAGG;IACH,mBAFW,MAAM,QA+BhB;IAED,eAOC;IAED;;;OAGG;IACH,0BAFW,MAAM,EAAE,QA2ClB;CACJ;mBAhPkB,uCAAuC"}
1
+ {"version":3,"file":"AnimationTrackPlayback.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/keyed2/AnimationTrackPlayback.js"],"names":[],"mappings":";AAGA;IACI;;;;;;;;OAQG;IACH,4EAuBC;IAtBG,sBAAkB;IAClB,cAA+B;IAE/B,oBAAoC;IACpC,kBAAgC;IAEhC,uBAAuB;IACvB,8BAA8B;IAE9B,uBAAuB;IACvB,sBAAsB;IAEtB,gBAAmB;IAEnB,4BAA0D;IAG1D;;MAEC;IAKL;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,gBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;OAGG;IACH,WAFW,OAAO,QAIjB;IAED,cAEC;IAED;;;OAGG;IACH,kBAFW,MAAM,QA2BhB;IAED;;;OAGG;IACH,cAFa,OAAO,CA2CnB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAmChB;IAED,eAOC;IAED;;;OAGG;IACH,0BAFW,MAAM,EAAE,QA2ClB;CACJ;mBApPkB,uCAAuC"}
@@ -159,7 +159,11 @@ class AnimationTrackPlayback {
159
159
  if (timeDelta < 0) {
160
160
  //negative delta, going back in time
161
161
  this.setPosition(newPosition);
162
- } else if (newPosition > this.__nextKeyTime) {
162
+ // the `>= timeEnd` term catches a frame that lands EXACTLY on the end: __nextKeyTime equals
163
+ // timeEnd on the final segment, so the strict `> __nextKeyTime` test would skip it, and the
164
+ // one-shot `ended` (guarded by position < timeEnd) would then never fire. Mid-track exact
165
+ // landings do not reach timeEnd, so they stay on the plain else branch as before.
166
+ } else if (newPosition > this.__nextKeyTime || newPosition >= this.track.timeEnd) {
163
167
 
164
168
  if (newPosition >= this.track.timeEnd) {
165
169
  if (this.__loop) {
@@ -1 +1 @@
1
- {"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { assert } from "../../core/assert.js";
2
2
  import { BitSet } from "../../core/binary/BitSet.js";
3
3
  import { array_set_diff } from "../../core/collection/array/array_set_diff.js";
4
- import { array_shrink_to_size } from "../../core/collection/array/array_shrink_to_size.js";
5
4
  import { findSignalHandlerIndexByHandle } from "../../core/events/signal/findSignalHandlerIndexByHandle.js";
6
5
  import {
7
6
  findSignalHandlerIndexByHandleAndContext
@@ -107,18 +106,6 @@ function buildObserverCallbackArgs(entityIndex, mask, componentIndexMap, compone
107
106
  }
108
107
  }
109
108
 
110
- /**
111
- *
112
- * @type {number[]}
113
- */
114
- const scratch_indices = [];
115
-
116
- /**
117
- * Used for constructing arguments prior to traversal visitor call
118
- * @type {*[]}
119
- */
120
- const scratch_args = [];
121
-
122
109
  /**
123
110
  * Represents a storage for entities and their associated components.
124
111
  * Entities are just integer IDs and components are stored in a virtual table, where each component type has a separate column and each entity is a row in that table.
@@ -1327,8 +1314,10 @@ export class EntityComponentDataset {
1327
1314
 
1328
1315
  let entityIndex, i;
1329
1316
 
1330
- //map classes to indices
1331
- const indices = scratch_indices;
1317
+ // Local arrays rather than the module-shared scratch pools: the visitor may itself call
1318
+ // traverseEntities (an ordinary "for each A, scan the B entities" pattern), and a shared pool
1319
+ // would let the inner call clobber this call's indices/args mid-scan. Matches traverseEntitiesExact.
1320
+ const indices = [];
1332
1321
 
1333
1322
  // prepare sorted array of component indices
1334
1323
  const numClasses = classes.length;
@@ -1348,12 +1337,7 @@ export class EntityComponentDataset {
1348
1337
  indices[i] = componentIndex;
1349
1338
  }
1350
1339
 
1351
- const args = scratch_args;
1352
-
1353
- // crop args array to the right length (since we're re-using a scratch array)
1354
- const args_length_intended = numClasses + 1;
1355
-
1356
- array_shrink_to_size(scratch_args, args_length_intended);
1340
+ const args = [];
1357
1341
 
1358
1342
  const entityOccupancy = this.entityOccupancy;
1359
1343
 
@@ -74,6 +74,14 @@ export class FogOfWar {
74
74
  * @param {number} radius
75
75
  */
76
76
  conceal(x: number, y: number, radius: number): void;
77
+ /**
78
+ * Rebuild the cell -> fade row index from the current {@link fadeMask}
79
+ * contents. Must be invoked whenever the fade mask is populated without
80
+ * going through {@link reveal}/{@link conceal}/{@link revealPoint} (e.g.
81
+ * after deserialization), otherwise those methods could stack duplicate
82
+ * fade rows for a cell.
83
+ */
84
+ rebuildFadeIndex(): void;
77
85
  dispose(): void;
78
86
  updateTexture(): void;
79
87
  /**
@@ -117,6 +125,7 @@ export class FogOfWar {
117
125
  * @param scale
118
126
  */
119
127
  resize(w: number, h: number, scale: any): void;
128
+ #private;
120
129
  }
121
130
  export namespace FogOfWar {
122
131
  let typeName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"FogOfWar.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWar.js"],"names":[],"mappings":"AA+CA;;GAEG;AACH;IAEI;;;OAGG;IACH,oBAFU,OAAO,CAES;IAC1B;;;OAGG;IACH,0BAFU,OAAO,CAEgB;IAEjC;;;OAGG;IACH,SAFU,WAAW,GAAC,IAAI,CAEX;IAEf;;;OAGG;IACH,OAFU,OAAO,CAEM;IAEvB;;;OAGG;IACH,MAFU,OAAO,CAEQ;IAEzB,eAAsC;IAEtC;;;OAGG;IACH,UAFU,aAAa,CAE2B;IAElD;;MAEE;IAEF;;;OAGG;IACH,SAFU,SAAS,CAEgB;IAEnC;;;OAGG;IACH,iBAFU,SAAS,CAEwB;IAE3C;;;OAGG;IACH,sBAFW,MAAM,QAqDhB;IAED;;;;OAIG;IACH,eAHW,MAAM,KACN,MAAM,QAyBhB;IAED,cAOC;IAED,kBAOC;IAED,mBAEC;IAED;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,UACN,MAAM,QA+ChB;IAED;;;;;OAKG;IACH,WAJW,MAAM,KACN,MAAM,UACN,MAAM,QAgDhB;IAED,gBAIC;IAED,sBAqCC;IAED;;;OAGG;IACH,kBAFW,MAAM,QAYhB;IAED;;;OAGG;IACH,0DA+BC;IAED;;;;;OAKG;IACH,yBAJW,MAAM,KACN,MAAM,UACN,MAAM,EAAE,QAelB;IAED;;;;;OAKG;IACH,yEAFW,MAAM,WA+EhB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CASlB;IAED,6BAKC;IAED,+BASC;IAED,uBAyBC;IAGD;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,oBAUhB;CACJ;;;;4BAxlB2F,OAAO;oBAM/E,+BAA+B;oBAC/B,+BAA+B;oBAC/B,+BAA+B;8BALrB,iDAAiD;mBAE5D,uCAAuC;0BAQhC,6CAA6C"}
1
+ {"version":3,"file":"FogOfWar.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWar.js"],"names":[],"mappings":"AA+CA;;GAEG;AACH;IAEI;;;OAGG;IACH,oBAFU,OAAO,CAES;IAC1B;;;OAGG;IACH,0BAFU,OAAO,CAEgB;IAEjC;;;OAGG;IACH,SAFU,WAAW,GAAC,IAAI,CAEX;IAEf;;;OAGG;IACH,OAFU,OAAO,CAEM;IAEvB;;;OAGG;IACH,MAFU,OAAO,CAEQ;IAEzB,eAAsC;IAEtC;;;OAGG;IACH,UAFU,aAAa,CAE2B;IAWlD;;MAEE;IAEF;;;OAGG;IACH,SAFU,SAAS,CAEgB;IAEnC;;;OAGG;IACH,iBAFU,SAAS,CAEwB;IAE3C;;;OAGG;IACH,sBAFW,MAAM,QA6EhB;IA4DD;;;;OAIG;IACH,eAHW,MAAM,KACN,MAAM,QAUhB;IAED,cAQC;IAED,kBAQC;IAED,mBAEC;IAED;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,UACN,MAAM,QAmChB;IAED;;;;;OAKG;IACH,WAJW,MAAM,KACN,MAAM,UACN,MAAM,QAmChB;IAED;;;;;;OAMG;IACH,yBAcC;IAED,gBAIC;IAED,sBAqCC;IAED;;;OAGG;IACH,kBAFW,MAAM,QAYhB;IAED;;;OAGG;IACH,0DA+BC;IAED;;;;;OAKG;IACH,yBAJW,MAAM,KACN,MAAM,UACN,MAAM,EAAE,QAelB;IAED;;;;;OAKG;IACH,yEAFW,MAAM,WA+EhB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CASlB;IAED,6BAKC;IAED,+BASC;IAED,uBAyBC;IAGD;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,oBAahB;;CACJ;;;;4BAvqB2F,OAAO;oBAM/E,+BAA+B;oBAC/B,+BAA+B;oBAC/B,+BAA+B;8BALrB,iDAAiD;mBAE5D,uCAAuC;0BAQhC,6CAA6C"}
@@ -87,6 +87,15 @@ export class FogOfWar {
87
87
  */
88
88
  fadeMask = new RowFirstTable(revealMaskTableSpec);
89
89
 
90
+ /**
91
+ * Maps a sampler cell index to the row index of its in-progress fade in
92
+ * {@link fadeMask}. Enforces at most one fade row per cell, so that the
93
+ * latest reveal/conceal command for a cell re-aims its existing fade
94
+ * instead of stacking a second, opposing row.
95
+ * @type {Map<number, number>}
96
+ */
97
+ #fadeRowByCell = new Map();
98
+
90
99
  on = {
91
100
  textureChanged: new Signal()
92
101
  };
@@ -112,6 +121,8 @@ export class FogOfWar {
112
121
 
113
122
  const fadeMask = this.fadeMask;
114
123
 
124
+ const rowByCell = this.#fadeRowByCell;
125
+
115
126
  let numRows = fadeMask.length;
116
127
 
117
128
  let i = 0;
@@ -130,25 +141,24 @@ export class FogOfWar {
130
141
 
131
142
  let writeValue = value | 0;
132
143
 
133
- //write new value
144
+ //store the advanced precise value
134
145
  fadeMask.writeCellValue(i, 1, value);
135
146
 
147
+ let completed = false;
148
+
136
149
  if (value <= 0) {
150
+ writeValue = 0;
151
+
137
152
  if (speed < 0) {
138
- //we were going down and reached the end, clear row
139
- fadeMask.removeRows(i, 1);
140
- i--;
141
- numRows--;
153
+ //revealing fade reached the bottom
154
+ completed = true;
142
155
  }
143
- writeValue = 0;
144
156
  } else if (value >= 255) {
145
157
  writeValue = 255;
146
158
 
147
159
  if (speed > 0) {
148
- //we were going down and reached the end, clear row
149
- fadeMask.removeRows(i, 1);
150
- i--;
151
- numRows--;
160
+ //concealing fade reached the top
161
+ completed = true;
152
162
  }
153
163
  }
154
164
 
@@ -157,41 +167,108 @@ export class FogOfWar {
157
167
  samplerData[index] = writeValue;
158
168
  this.textureNeedsUpdate = true;
159
169
  }
170
+
171
+ if (completed) {
172
+ //Drop the finished row while keeping the cell->row index
173
+ //consistent. Swap the last row into this slot (O(1)) instead of
174
+ //shifting the whole tail forward, so only one other row's index
175
+ //needs to be patched in the map.
176
+ rowByCell.delete(index);
177
+
178
+ const lastRow = numRows - 1;
179
+
180
+ if (i !== lastRow) {
181
+ const movedCell = fadeMask.readCellValue(lastRow, 0);
182
+
183
+ fadeMask.copyRow(lastRow, i);
184
+
185
+ rowByCell.set(movedCell, i);
186
+ }
187
+
188
+ fadeMask.removeRows(lastRow, 1);
189
+
190
+ i--;
191
+ numRows--;
192
+ }
160
193
  }
161
194
  }
162
195
 
163
196
  /**
164
- *
165
- * @param {number} x
166
- * @param {number} y
197
+ * Schedule (or re-aim) a fade for a single sampler cell so that it converges
198
+ * to `target`. Guarantees at most one fade row per cell: if the cell already
199
+ * has an in-progress fade its direction is updated in place, so the latest
200
+ * command wins instead of stacking a second, opposing row.
201
+ * @param {number} index sampler cell index
202
+ * @param {number} target target sampler value, either 0 (revealed) or 255 (concealed)
203
+ * @returns {boolean} whether the visible sampler value was changed (i.e. the distance field may need a rebuild)
167
204
  */
168
- revealPoint(x, y) {
205
+ #scheduleCellFade(index, target) {
169
206
  const fadeMask = this.fadeMask;
207
+ const rowByCell = this.#fadeRowByCell;
170
208
 
171
- const sampler = this.sampler;
209
+ const speed = target === 0 ? -FADE_SPEED : FADE_SPEED;
172
210
 
173
- const samplerData = sampler.data;
211
+ const existingRow = rowByCell.get(index);
174
212
 
175
- const samplerWidth = sampler.width;
213
+ if (existingRow !== undefined) {
214
+ //A fade is already in progress for this cell, re-aim it in place.
215
+ //The precise value column is left untouched so the fade resumes from
216
+ //its current progress and never snaps back through the far end.
217
+ fadeMask.writeCellValue(existingRow, 2, speed);
176
218
 
177
- const index = (y + 1) * samplerWidth + (x + 1);
219
+ return false;
220
+ }
178
221
 
179
- if (samplerData[index] === 255) {
222
+ const samplerData = this.sampler.data;
223
+
224
+ const current = samplerData[index];
225
+
226
+ if (current === target) {
227
+ //already fully at the target, nothing to fade
228
+ return false;
229
+ }
230
+
231
+ let seedValue = current;
232
+ let visibleChanged = false;
233
+
234
+ if (target === 0 && current === 255) {
235
+ //pre-fade off the fully-concealed value so the distance field
236
+ //immediately treats this cell as being revealed
237
+ seedValue = INITIAL_FADE_VALUE;
180
238
  samplerData[index] = INITIAL_FADE_VALUE;
239
+ visibleChanged = true;
240
+ }
241
+
242
+ //add record to fade mask
243
+ fadeRow[0] = index;
244
+ fadeRow[1] = seedValue;
245
+ fadeRow[2] = speed;
181
246
 
182
- //add record to fade mask
183
- fadeRow[0] = index;
184
- fadeRow[1] = INITIAL_FADE_VALUE;
185
- fadeRow[2] = -FADE_SPEED;
247
+ const rowIndex = fadeMask.addRow(fadeRow);
186
248
 
187
- fadeMask.addRow(fadeRow);
249
+ rowByCell.set(index, rowIndex);
188
250
 
251
+ return visibleChanged;
252
+ }
253
+
254
+ /**
255
+ *
256
+ * @param {number} x
257
+ * @param {number} y
258
+ */
259
+ revealPoint(x, y) {
260
+ const samplerWidth = this.sampler.width;
261
+
262
+ const index = (y + 1) * samplerWidth + (x + 1);
263
+
264
+ if (this.#scheduleCellFade(index, 0)) {
189
265
  this.distanceFieldNeedsUpdate = true;
190
266
  }
191
267
  }
192
268
 
193
269
  clear() {
194
270
  this.fadeMask.clear();
271
+ this.#fadeRowByCell.clear();
195
272
 
196
273
  this.sampler.data.fill(255);
197
274
 
@@ -201,6 +278,7 @@ export class FogOfWar {
201
278
 
202
279
  revealAll() {
203
280
  this.fadeMask.clear();
281
+ this.#fadeRowByCell.clear();
204
282
 
205
283
  this.sampler.data.fill(0);
206
284
 
@@ -230,11 +308,8 @@ export class FogOfWar {
230
308
  const lastPixelX = samplerWidth - 1;
231
309
 
232
310
  let changeFlag = false;
233
- const samplerData = sampler.data;
234
-
235
- const fadeMask = this.fadeMask;
236
311
 
237
- sampler.traverseCircle(x + 1, y + 1, radius, function (x, y, sampler) {
312
+ sampler.traverseCircle(x + 1, y + 1, radius, (x, y) => {
238
313
 
239
314
  if (x <= 0 || x >= lastPixelX || y <= 0 || y >= lastPixelY) {
240
315
  //edges are reserved to preserve cover outside of the working area
@@ -243,16 +318,7 @@ export class FogOfWar {
243
318
 
244
319
  const index = y * samplerWidth + x;
245
320
 
246
- if (samplerData[index] === 255) {
247
- samplerData[index] = INITIAL_FADE_VALUE;
248
-
249
- //add record to fade mask
250
- fadeRow[0] = index;
251
- fadeRow[1] = INITIAL_FADE_VALUE;
252
- fadeRow[2] = -FADE_SPEED;
253
-
254
- fadeMask.addRow(fadeRow);
255
-
321
+ if (this.#scheduleCellFade(index, 0)) {
256
322
  changeFlag = true;
257
323
  }
258
324
 
@@ -283,11 +349,8 @@ export class FogOfWar {
283
349
  const lastPixelX = samplerWidth - 1;
284
350
 
285
351
  let changeFlag = false;
286
- const samplerData = sampler.data;
287
-
288
- const fadeMask = this.fadeMask;
289
352
 
290
- sampler.traverseCircle(x + 1, y + 1, radius, function (x, y, sampler) {
353
+ sampler.traverseCircle(x + 1, y + 1, radius, (x, y) => {
291
354
 
292
355
  if (x <= 0 || x >= lastPixelX || y <= 0 || y >= lastPixelY) {
293
356
  //edges are reserved to preserve cover outside of the working area
@@ -296,17 +359,7 @@ export class FogOfWar {
296
359
 
297
360
  const index = y * samplerWidth + x;
298
361
 
299
- const value = samplerData[index];
300
-
301
- if (value !== 255) {
302
-
303
- //add record to fade mask
304
- fadeRow[0] = index;
305
- fadeRow[1] = value;
306
- fadeRow[2] = FADE_SPEED;
307
-
308
- fadeMask.addRow(fadeRow);
309
-
362
+ if (this.#scheduleCellFade(index, 255)) {
310
363
  changeFlag = true;
311
364
  }
312
365
 
@@ -319,6 +372,29 @@ export class FogOfWar {
319
372
  }
320
373
  }
321
374
 
375
+ /**
376
+ * Rebuild the cell -> fade row index from the current {@link fadeMask}
377
+ * contents. Must be invoked whenever the fade mask is populated without
378
+ * going through {@link reveal}/{@link conceal}/{@link revealPoint} (e.g.
379
+ * after deserialization), otherwise those methods could stack duplicate
380
+ * fade rows for a cell.
381
+ */
382
+ rebuildFadeIndex() {
383
+ const rowByCell = this.#fadeRowByCell;
384
+
385
+ rowByCell.clear();
386
+
387
+ const fadeMask = this.fadeMask;
388
+
389
+ const numRows = fadeMask.length;
390
+
391
+ for (let i = 0; i < numRows; i++) {
392
+ const index = fadeMask.readCellValue(i, 0);
393
+
394
+ rowByCell.set(index, i);
395
+ }
396
+ }
397
+
322
398
  dispose() {
323
399
  if (this.texture !== null) {
324
400
  this.texture.dispose();
@@ -594,7 +670,10 @@ export class FogOfWar {
594
670
  this.size.set(w, h);
595
671
  this.scale.set(scale);
596
672
 
597
- //TODO update fade mask as necessary
673
+ //TODO update fade mask as necessary - the sampler indices change with the
674
+ //new width, so any in-progress fade rows (and the #fadeRowByCell index that
675
+ //mirrors them) would need remapping or clearing. Only reachable at link time
676
+ //today, when both are empty.
598
677
 
599
678
  this.rebuildSampler();
600
679
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FogOfWarSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js"],"names":[],"mappings":"AAQA;;IAEI,uBAAiB;IAGjB,oDAA2D;IAE3D;;;;OAIG;IACH,uCAFW,QAAQ,QAyBlB;IAED;;;;OAIG;IACH,yCAFW,QAAQ,QAgClB;CACJ;gDAjF+C,yDAAyD;yBAChF,gBAAgB;8CAKlC,kFAAkF"}
1
+ {"version":3,"file":"FogOfWarSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js"],"names":[],"mappings":"AAQA;;IAEI,uBAAiB;IAGjB,oDAA2D;IAE3D;;;;OAIG;IACH,uCAFW,QAAQ,QAyBlB;IAED;;;;OAIG;IACH,yCAFW,QAAQ,QAmClB;CACJ;gDApF+C,yDAAyD;yBAChF,gBAAgB;8CAKlC,kFAAkF"}
@@ -75,6 +75,9 @@ export class FogOfWarSerializationAdapter extends BinaryClassSerializationAdapte
75
75
  //deserialize reveal state
76
76
  deserializeRowFirstTable(buffer, value.fadeMask);
77
77
 
78
+ //rebuild the cell -> fade row index to match the restored fade mask
79
+ value.rebuildFadeIndex();
80
+
78
81
  //
79
82
  value.textureNeedsUpdate = true;
80
83
  value.rebuildDistanceSampler();
@@ -1 +1 @@
1
- {"version":3,"file":"BinaryCollectionDeSerializer.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH;IAEI;;;OAGG;IACH,iBAAgB;IAEhB;;;OAGG;IACH,eAAc;IAEd;;;;OAIG;IACH,4BAA4B;IAC5B;;;;OAIG;IACH,0BAA0B;IAE1B;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,gBAAe;IAEf;;;OAGG;IACH,kBAAiB;IAEjB;;;;OAIG;IACH,yBAAsC;IACtC;;;;OAIG;IACH,yBAAsC;IAEtC;;;OAGG;IACH,cAAsB;IAGtB;;;OAGG;IACH,yDAKC;IAED;;;OAGG;IACH,2CAEC;IAED;;;OAGG;IACH,kBAFW,YAAY,QAOtB;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,mBAFa,WAAS,IAAI,CAUzB;IAED;;;OAGG;IACH,wDAFyB,MAAM,QAgF9B;IAED,iBAWC;IAED;;;OAGG;IACH,uBAeC;IAED;;;OAGG;IACH;;aAF6B,MAAM;MA8DlC;CAEJ;6BAvV4B,4CAA4C"}
1
+ {"version":3,"file":"BinaryCollectionDeSerializer.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH;IAEI;;;OAGG;IACH,iBAAgB;IAEhB;;;OAGG;IACH,eAAc;IAEd;;;;OAIG;IACH,4BAA4B;IAC5B;;;;OAIG;IACH,0BAA0B;IAE1B;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,qBAAiB;IAEjB;;;OAGG;IACH,gBAAe;IAEf;;;OAGG;IACH,kBAAiB;IAEjB;;;;OAIG;IACH,yBAAsC;IACtC;;;;OAIG;IACH,yBAAsC;IAEtC;;;OAGG;IACH,cAAsB;IAGtB;;;OAGG;IACH,yDAKC;IAED;;;OAGG;IACH,2CAEC;IAED;;;OAGG;IACH,kBAFW,YAAY,QAOtB;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED;;;OAGG;IACH,mBAFa,WAAS,IAAI,CAUzB;IAED;;;OAGG;IACH,wDAFyB,MAAM,QAgF9B;IAED,iBAWC;IAED;;;OAGG;IACH,uBAeC;IAED;;;OAGG;IACH;;aAF6B,MAAM;MAgElC;CAEJ;6BAzV4B,4CAA4C"}
@@ -315,7 +315,9 @@ export class BinaryCollectionDeSerializer {
315
315
  header = buffer.readUint32LE();
316
316
  }
317
317
 
318
- const offset = header >> 2;
318
+ // unsigned: for a first-occurrence offset >= 2^29 the header sets bit 31, and a signed
319
+ // shift would sign-extend it into a negative (wrong) offset
320
+ const offset = header >>> 2;
319
321
 
320
322
  //read address
321
323
  const address = offset + this.startAddress;
@@ -35,7 +35,11 @@ export class GraphicsEngine {
35
35
  */
36
36
  pixelRatio: Vector1;
37
37
  /**
38
- * Final render-target resolution, in device pixels: `viewport.size × pixelRatio × devicePixelRatio`.
38
+ * Final render-target resolution, in whole device pixels: `viewport.size × pixelRatio ×
39
+ * devicePixelRatio`, floored and clamped the same way the attachments themselves are. This is
40
+ * the authority every full-resolution buffer is sized from -- frame buffers, composit layers,
41
+ * and anything that has to sample them on their own texel grid. Zero until the viewport has
42
+ * been sized for the first time.
39
43
  * Kept in sync by {@link GraphicsEngine#updateSize}. Subscribe to `output_resolution.onChanged` to
40
44
  * react to any change in the actual rendered resolution (viewport resize, supersample, or DPR change).
41
45
  * @readonly
@@ -1 +1 @@
1
- {"version":3,"file":"GraphicsEngine.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics/GraphicsEngine.js"],"names":[],"mappings":"AAiEA;IAOI;;;;;OAKG;IACH,+BAJW,MAAM,EAgLhB;IAtLD,gCAEC;IAgBG;;;;OAIG;IACH,2BAA+C;IAK/C;;;;;QAOI;;WAEG;;QAEH;;WAEG;;;;;MAMN;IAED;;OAEG;IACH,YAFU,OAAO,CAEe;IAEhC;;;;;;OAMG;IACH,4BAFU,OAAO,CAEyB;IAE1C;;;OAGG;IACH,QAFU,kBAAkB,CAEU;IAWtC;;;OAGG;IACH,aAAkB;IAGlB;;;OAGG;IACH,cAFU,KAAK,CAEgB;IAK/B;;;OAGG;IACH,QAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,UAFU,aAAa,CAEH;IAGpB,+BAA0C;IAU1C;;OAEG;IACH,eAA+B;IAI/B;;;OAGG;IACH,uBAFU,kBAAkB,CAEgB;IAE5C;;;OAGG;IACH,oBAFU,iBAAiB,CAEsB;IAEjD;;;OAGG;IACH,gBAFU,iBAAiB,CAES;IAEpC;;;OAGG;IACH,sBAAoC;IAGpC;;;;OAIG;IACH,UAFU,OAAO,CAEG;IAEpB;;;OAGG;IACH,UAFU,OAAO,CAEG;IAEpB;;;OAGG;IACH,YAFU,MAAM,CAEG;IACnB,kKAcI;IAGR;;;OAGG;IACH,sBAFa,eAAe,CAI3B;IAED;;;OAGG;IACH,eAFa,aAAa,CAIzB;IAED;;;;;;;;;;;;;OAaG;IACH,iCAHW,MAAM,OAAO,eACb,4BAA4B,QAkCtC;IAED,mBA8BC;IAED;;;;OAIG;IACH,iCAEC;IAED;;;OAGG;IACH,0BAFa,MAAM,CAIlB;IAED,+BAcC;IAED,cAgEC;IAzBsB,8BAA0C;IA2BjE;;;OAGG;IACH,cAFa,MAAM,CAYlB;IAED;;OAEG;IACH,aAQC;IAED;;OAEG;IACH,yBAQC;IAED;;;;;;OAMG;IACH,yBALW,MAAM,KACN,MAAM,6CAMhB;IAED;;;;OAIG;IACH,8BAHW,OAAO,UAAQ,UACf,OAAO,UAAQ,QAczB;IAED;;;;;OAKG;IACH,8BAQC;IAED,0BAEC;IAED;;;OAGG;IACH,4BAFW,cAAc,QA8BxB;IAED;;OAEG;IACH,qBAqBC;IAED;;OAEG;IACH,0BAeC;IAED;;OAEG;IACH,eA8CC;;CACJ;mBA7oBkB,oCAAoC;oBACnC,4BAA4B;wBACxB,4BAA4B;mCAajB,uCAAuC;sBAlBnE,OAAO;uBAaS,wBAAwB;8BAbxC,OAAO;4BAYc,+BAA+B;mCAKxB,uCAAuC;kCAKxC,gCAAgC;kCADhC,oCAAoC;gCAPtC,uCAAuC;6CAW1B,2CAA2C;+BANzD,4BAA4B"}
1
+ {"version":3,"file":"GraphicsEngine.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics/GraphicsEngine.js"],"names":[],"mappings":"AAiEA;IAOI;;;;;OAKG;IACH,+BAJW,MAAM,EAoLhB;IA1LD,gCAEC;IAgBG;;;;OAIG;IACH,2BAA+C;IAK/C;;;;;QAOI;;WAEG;;QAEH;;WAEG;;;;;MAMN;IAED;;OAEG;IACH,YAFU,OAAO,CAEe;IAEhC;;;;;;;;;;OAUG;IACH,4BAFU,OAAO,CAEyB;IAE1C;;;OAGG;IACH,QAFU,kBAAkB,CAEU;IAWtC;;;OAGG;IACH,aAAkB;IAGlB;;;OAGG;IACH,cAFU,KAAK,CAEgB;IAK/B;;;OAGG;IACH,QAFU,MAAM,CAEI;IAEpB;;;OAGG;IACH,UAFU,aAAa,CAEH;IAGpB,+BAA0C;IAU1C;;OAEG;IACH,eAA+B;IAI/B;;;OAGG;IACH,uBAFU,kBAAkB,CAEgB;IAE5C;;;OAGG;IACH,oBAFU,iBAAiB,CAEsB;IAEjD;;;OAGG;IACH,gBAFU,iBAAiB,CAES;IAEpC;;;OAGG;IACH,sBAAoC;IAGpC;;;;OAIG;IACH,UAFU,OAAO,CAEG;IAEpB;;;OAGG;IACH,UAFU,OAAO,CAEG;IAEpB;;;OAGG;IACH,YAFU,MAAM,CAEG;IACnB,kKAcI;IAGR;;;OAGG;IACH,sBAFa,eAAe,CAI3B;IAED;;;OAGG;IACH,eAFa,aAAa,CAIzB;IAED;;;;;;;;;;;;;OAaG;IACH,iCAHW,MAAM,OAAO,eACb,4BAA4B,QAkCtC;IAED,mBAqCC;IAED;;;;OAIG;IACH,iCAEC;IAED;;;OAGG;IACH,0BAFa,MAAM,CAIlB;IAED,+BAcC;IAED,cAgEC;IAzBsB,8BAA0C;IA2BjE;;;OAGG;IACH,cAFa,MAAM,CAYlB;IAED;;OAEG;IACH,aAQC;IAED;;OAEG;IACH,yBAQC;IAED;;;;;;OAMG;IACH,yBALW,MAAM,KACN,MAAM,6CAMhB;IAED;;;;OAIG;IACH,8BAHW,OAAO,UAAQ,UACf,OAAO,UAAQ,QAczB;IAED;;;;;OAKG;IACH,8BAQC;IAED,0BAEC;IAED;;;OAGG;IACH,4BAFW,cAAc,QA8BxB;IAED;;OAEG;IACH,qBAqBC;IAED;;OAEG;IACH,0BAeC;IAED;;OAEG;IACH,eA8CC;;CACJ;mBAxpBkB,oCAAoC;oBACnC,4BAA4B;wBACxB,4BAA4B;mCAajB,uCAAuC;sBAlBnE,OAAO;uBAaS,wBAAwB;8BAbxC,OAAO;4BAYc,+BAA+B;mCAKxB,uCAAuC;kCAKxC,gCAAgC;kCADhC,oCAAoC;gCAPtC,uCAAuC;6CAW1B,2CAA2C;+BANzD,4BAA4B"}
@@ -121,7 +121,11 @@ export class GraphicsEngine {
121
121
  this.pixelRatio = new Vector1(1);
122
122
 
123
123
  /**
124
- * Final render-target resolution, in device pixels: `viewport.size × pixelRatio × devicePixelRatio`.
124
+ * Final render-target resolution, in whole device pixels: `viewport.size × pixelRatio ×
125
+ * devicePixelRatio`, floored and clamped the same way the attachments themselves are. This is
126
+ * the authority every full-resolution buffer is sized from -- frame buffers, composit layers,
127
+ * and anything that has to sample them on their own texel grid. Zero until the viewport has
128
+ * been sized for the first time.
125
129
  * Kept in sync by {@link GraphicsEngine#updateSize}. Subscribe to `output_resolution.onChanged` to
126
130
  * react to any change in the actual rendered resolution (viewport resize, supersample, or DPR change).
127
131
  * @readonly
@@ -342,8 +346,15 @@ export class GraphicsEngine {
342
346
  this.frameBuffers.setSize(_w, _h);
343
347
 
344
348
  // publish the final device-pixel render resolution; `_w/_h` already fold in the engine pixelRatio,
345
- // so this matches the framebuffers/composit layers and what getResolution historically computed
346
- this.output_resolution.set(_w * devicePixelRatio, _h * devicePixelRatio);
349
+ // so this matches the framebuffers/composit layers and what getResolution historically computed.
350
+ // Floored for the same reason three.js floors the drawing buffer: these are whole texels, and
351
+ // every buffer sized off this value must land on exactly the same grid. Clamped to 1 to match
352
+ // those buffers too -- a collapsed viewport still allocates 1x1 attachments, because a 0-sized
353
+ // one trips GL_INVALID_FRAMEBUFFER_OPERATION on clear/draw
354
+ this.output_resolution.set(
355
+ max2(1, Math.floor(_w * devicePixelRatio)),
356
+ max2(1, Math.floor(_h * devicePixelRatio))
357
+ );
347
358
  }
348
359
 
349
360
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"CompositLayer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/composit/CompositLayer.js"],"names":[],"mappings":"AAsCA;IACI;;;;;OAKG;IACH,2DAJW,MAAM,iBAAiB,EAyDjC;IAhDG;;;OAGG;IACH,MAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,YAFU,YAAY,CAEI;IAC1B;;;OAGG;IACH,gCAAgC;IAEhC;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C,6DAA2E;IAE3E;;;OAGG;IACH,OAFU,MAAM,CAEF;IAEd,cAAyB;IAEzB;;;OAGG;IACH,WAFU,OAAO,CAEI;IAErB;;;OAGG;IACH,SAFU,MAAM,CAEA;IAEhB;;MAEC;IAOL,0BAQC;IAZD,uBAEC;IAYD;;;OAGG;IACH,uBAIC;IAED;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,0BAMC;IAED;;;OAGG;IACH,uBAEC;IAED,eAKC;IAED,gBAKC;IAED;;;;OAIG;IACH,WAHW,MAAM,KACN,MAAM,QAKhB;IAED,+BAaC;IAED;;;OAGG;IACH,4BAFW,MAAM,QAShB;IAED;;;;OAIG;IACH,4CAKC;IAGD,gCAoCC;CACJ;6BA/O4B,oCAAoC;+BAN1D,OAAO;qBAAP,OAAO;oBAGM,+BAA+B;mBADhC,uCAAuC"}
1
+ {"version":3,"file":"CompositLayer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/composit/CompositLayer.js"],"names":[],"mappings":"AAsCA;IACI;;;;;OAKG;IACH,2DAJW,MAAM,iBAAiB,EAyDjC;IAhDG;;;OAGG;IACH,MAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,YAFU,YAAY,CAEI;IAC1B;;;OAGG;IACH,gCAAgC;IAEhC;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C,6DAA2E;IAE3E;;;OAGG;IACH,OAFU,MAAM,CAEF;IAEd,cAAyB;IAEzB;;;OAGG;IACH,WAFU,OAAO,CAEI;IAErB;;;OAGG;IACH,SAFU,MAAM,CAEA;IAEhB;;MAEC;IAOL,0BAQC;IAZD,uBAEC;IAYD;;;OAGG;IACH,uBAIC;IAED;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,0BAMC;IAED;;;OAGG;IACH,uBAEC;IAED,eAKC;IAED,gBAKC;IAED;;;;OAIG;IACH,WAHW,MAAM,KACN,MAAM,QAKhB;IAED,+BAgBC;IAED;;;OAGG;IACH,4BAFW,MAAM,QAShB;IAED;;;;OAIG;IACH,4CAKC;IAGD,gCAoCC;CACJ;6BAlP4B,oCAAoC;+BAN1D,OAAO;qBAAP,OAAO;oBAGM,+BAA+B;mBADhC,uCAAuC"}