@woosh/meep-engine 3.60.6 → 3.60.8

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 (328) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/binary/BitSet.d.ts.map +1 -1
  4. package/src/core/binary/BitSet.js +2 -1
  5. package/src/{format/image/avif/av1/util → core/binary/operations}/ceil_log2.d.ts +2 -2
  6. package/src/core/binary/operations/ceil_log2.d.ts.map +1 -0
  7. package/src/{format/image/avif/av1/util → core/binary/operations}/ceil_log2.js +18 -18
  8. package/src/core/binary/zstd/ZstdReverseBitReader.d.ts.map +1 -1
  9. package/src/core/binary/zstd/ZstdReverseBitReader.js +225 -223
  10. package/src/core/binary/zstd/zstd_fse.d.ts.map +1 -1
  11. package/src/core/binary/zstd/zstd_fse.js +267 -265
  12. package/src/core/binary/zstd/zstd_huffman.d.ts.map +1 -1
  13. package/src/core/binary/zstd/zstd_huffman.js +246 -244
  14. package/src/core/bvh2/binary/2/BinaryUint32BVH.d.ts.map +1 -1
  15. package/src/core/bvh2/binary/2/BinaryUint32BVH.js +8 -2
  16. package/src/core/bvh2/bvh3/ebvh_optimize_treelet.d.ts.map +1 -1
  17. package/src/core/bvh2/bvh3/ebvh_optimize_treelet.js +8 -7
  18. package/src/core/collection/PairUint32Map.d.ts.map +1 -1
  19. package/src/core/collection/PairUint32Map.js +2 -2
  20. package/src/core/collection/Uint32Map.d.ts.map +1 -1
  21. package/src/core/collection/Uint32Map.js +2 -4
  22. package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -1
  23. package/src/core/collection/heap/FibonacciHeap.js +2 -1
  24. package/src/core/geom/2d/r-tree/StaticR2Tree.d.ts.map +1 -1
  25. package/src/core/geom/2d/r-tree/StaticR2Tree.js +8 -2
  26. package/src/core/geom/3d/shape/util/mesh_compute_triangle_edge_flags.d.ts.map +1 -1
  27. package/src/core/geom/3d/shape/util/mesh_compute_triangle_edge_flags.js +2 -3
  28. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  29. package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -14
  30. package/src/engine/graphics/texture/atlas/sprite_atlas_border.d.ts.map +1 -1
  31. package/src/engine/graphics/texture/atlas/sprite_atlas_border.js +70 -69
  32. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.d.ts.map +1 -1
  33. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +2 -1
  34. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  35. package/src/engine/graphics3/GPUParticleEmitterSystem.js +2 -1
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +2 -1
  38. package/src/engine/graphics3/decal/chunk_decal_record.d.ts +14 -0
  39. package/src/engine/graphics3/decal/chunk_decal_record.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_record.js +44 -0
  41. package/src/engine/graphics3/decal/shader_cluster_assign_decals.d.ts.map +1 -1
  42. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +2 -15
  43. package/src/engine/graphics3/decal/shader_cull_decals_frustum.d.ts.map +1 -1
  44. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +3 -16
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +3 -23
  47. package/src/engine/graphics3/terrain/TERRAIN_MATERIAL_TEMPLATE.d.ts.map +1 -1
  48. package/src/engine/graphics3/terrain/TERRAIN_MATERIAL_TEMPLATE.js +2 -1
  49. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  50. package/src/engine/physics/queries/shape_cast.js +2 -2
  51. package/src/format/image/avif/av1/decode/decode_palette.js +442 -442
  52. package/src/format/image/avif/av1/entropy/SymbolWriter.d.ts.map +1 -1
  53. package/src/format/image/avif/av1/entropy/SymbolWriter.js +2 -1
  54. package/src/generation/foliage/material/foliage_tile.d.ts.map +1 -1
  55. package/src/generation/foliage/material/foliage_tile.js +2 -1
  56. package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
  57. package/src/generation/markers/GridActionRuleSet.js +12 -3
  58. package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
  59. package/src/shade/device/mock/SoftwareGPUDevice.js +6 -13
  60. package/src/shade/playground/caldera/main.js +3 -2
  61. package/src/shade/playground/probe_clipmap/README.md +2 -1
  62. package/src/shade/playground/probe_clipmap/index.html +7 -2
  63. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  64. package/src/shade/playground/probe_clipmap/main.js +17 -7
  65. package/src/shade/playground/sh_exponential/sh_exp_playground_shaders.d.ts.map +1 -1
  66. package/src/shade/playground/sh_exponential/sh_exp_playground_shaders.js +7 -13
  67. package/src/shade/playground/vgeo_scene/main.js +2 -1
  68. package/src/shade/playground/vsm/VSMDebugOverlay.d.ts.map +1 -1
  69. package/src/shade/playground/vsm/VSMDebugOverlay.js +3 -1
  70. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  71. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  72. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  73. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  74. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_coarsest.d.ts.map +1 -1
  75. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_coarsest.js +5 -4
  76. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_residual_restrict.d.ts.map +1 -1
  77. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_residual_restrict.js +168 -166
  78. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_smooth.d.ts.map +1 -1
  79. package/src/shade/renderer/fluid/pressure/shader_fluid_mg_smooth.js +221 -219
  80. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  81. package/src/shade/renderer/fow/shader_fog_of_war.d.ts.map +1 -1
  82. package/src/shade/renderer/fow/shader_fog_of_war.js +8 -19
  83. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +6 -6
  85. package/src/shade/renderer/geometry/sdf/MeshSDFLayout.d.ts.map +1 -1
  86. package/src/shade/renderer/geometry/sdf/MeshSDFLayout.js +2 -1
  87. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  88. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +2 -1
  89. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +2 -1
  91. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v1/chunk_brick4_sh3_color_decode_from_storage.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v1/chunk_brick4_sh3_color_decode_from_storage.js +10 -31
  93. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v1/chunk_brick4_sh3_color_encode_to_storage.d.ts.map +1 -1
  94. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v1/chunk_brick4_sh3_color_encode_to_storage.js +9 -15
  95. package/src/shade/renderer/global_illumination/clipmap/shader_debug_clipmap.d.ts +2 -1
  96. package/src/shade/renderer/global_illumination/clipmap/shader_debug_clipmap.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/clipmap/shader_debug_clipmap.js +6 -5
  98. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +15 -3
  101. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +168 -18
  103. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +98 -57
  104. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +168 -77
  106. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +4 -2
  107. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  108. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +27 -12
  109. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts.map +1 -1
  110. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.js +12 -7
  111. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +8 -2
  113. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.js +5 -2
  115. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.js +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts.map +1 -1
  117. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.js +5 -3
  118. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.js +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts.map +1 -1
  120. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.js +1 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_movers_command.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_movers_command.js +4 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_scroll.d.ts.map +1 -1
  124. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_scroll.js +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_store.d.ts.map +1 -1
  126. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_store.js +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_take.d.ts.map +1 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_take.js +3 -1
  129. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_mesh_cards.js +2 -2
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +114 -41
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +424 -207
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +34 -25
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +41 -31
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts +7 -5
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.js +7 -5
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapHitWants.d.ts +47 -0
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapHitWants.d.ts.map +1 -0
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapHitWants.js +84 -0
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +48 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +101 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +58 -4
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +127 -30
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.d.ts +18 -7
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.js +39 -13
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +29 -8
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -1
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +112 -56
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resample.d.ts +19 -0
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resample.d.ts.map +1 -0
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resample.js +35 -0
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +9 -3
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +3 -3
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +5 -5
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +8 -12
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +23 -56
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +0 -3
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +11 -15
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts +26 -0
  168. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts.map +1 -0
  169. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.js +173 -0
  170. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts +32 -0
  171. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts.map +1 -0
  172. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.js +166 -0
  173. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +3 -4
  174. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  175. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +3 -4
  176. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts.map +1 -1
  177. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.js +3 -1
  178. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +6 -12
  179. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -1
  180. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +15 -65
  181. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts.map +1 -1
  182. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.js +7 -2
  183. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +4 -4
  184. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  185. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +24 -17
  186. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_publish.d.ts +7 -5
  187. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_publish.d.ts.map +1 -1
  188. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_publish.js +18 -10
  189. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts +2 -2
  190. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts.map +1 -1
  191. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.js +9 -5
  192. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts +3 -0
  193. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  194. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +9 -6
  195. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts +1 -1
  196. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts.map +1 -1
  197. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.js +16 -16
  198. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample_rays.d.ts +36 -0
  199. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample_rays.d.ts.map +1 -0
  200. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample_rays.js +233 -0
  201. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  202. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +7 -5
  203. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  204. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +5 -3
  205. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  206. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +10 -4
  207. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts +2 -1
  208. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts.map +1 -1
  209. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.js +12 -6
  210. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +1 -2
  211. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  212. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +5 -6
  213. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +14 -18
  214. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -1
  215. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +25 -35
  216. package/src/shade/renderer/gpu_primitive/WEBGPU_GUARANTEED_MAX_UNIFORM_BUFFER_BINDING_SIZE.d.ts +13 -0
  217. package/src/shade/renderer/gpu_primitive/WEBGPU_GUARANTEED_MAX_UNIFORM_BUFFER_BINDING_SIZE.d.ts.map +1 -0
  218. package/src/shade/renderer/gpu_primitive/WEBGPU_GUARANTEED_MAX_UNIFORM_BUFFER_BINDING_SIZE.js +12 -0
  219. package/src/shade/renderer/gpu_primitive/hash_table/cpu_build_hash_table.d.ts +27 -2
  220. package/src/shade/renderer/gpu_primitive/hash_table/cpu_build_hash_table.d.ts.map +1 -1
  221. package/src/shade/renderer/gpu_primitive/hash_table/cpu_build_hash_table.js +62 -6
  222. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
  223. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +10 -19
  224. package/src/shade/renderer/gpu_primitive/indirect/chunk_folded_dispatch.d.ts.map +1 -1
  225. package/src/shade/renderer/gpu_primitive/indirect/chunk_folded_dispatch.js +6 -3
  226. package/src/shade/renderer/hiz/hzb_pick_alignment.d.ts.map +1 -1
  227. package/src/shade/renderer/hiz/hzb_pick_alignment.js +149 -148
  228. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_environment_cells.d.ts.map +1 -1
  229. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_environment_cells.js +4 -2
  230. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_log_floor.d.ts.map +1 -1
  231. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_log_floor.js +6 -5
  232. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_project.d.ts.map +1 -1
  233. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_project.js +3 -1
  234. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_reference_reflectance.d.ts.map +1 -1
  235. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_reference_reflectance.js +3 -1
  236. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_solve.d.ts.map +1 -1
  237. package/src/shade/renderer/light/environment/sh_exponential/shader_sh_exp_solve.js +3 -1
  238. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts +0 -5
  239. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts.map +1 -1
  240. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.js +0 -7
  241. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts +15 -2
  242. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts.map +1 -1
  243. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.js +51 -16
  244. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts.map +1 -1
  245. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.js +3 -2
  246. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  247. package/src/shade/renderer/postprocess/dof/raymarch/chunk_dof_lds_coc_cache.d.ts +17 -0
  248. package/src/shade/renderer/postprocess/dof/raymarch/chunk_dof_lds_coc_cache.d.ts.map +1 -0
  249. package/src/shade/renderer/postprocess/dof/raymarch/chunk_dof_lds_coc_cache.js +81 -0
  250. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.d.ts.map +1 -1
  251. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +5 -48
  252. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.d.ts.map +1 -1
  253. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +4 -44
  254. package/src/shade/renderer/postprocess/gtao/chunk_integrate_lighting_sample.d.ts.map +1 -1
  255. package/src/shade/renderer/postprocess/gtao/chunk_integrate_lighting_sample.js +4 -1
  256. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  257. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +8 -7
  258. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  259. package/src/shade/renderer/postprocess/nss/chunk_nss_luma_derivative.d.ts.map +1 -1
  260. package/src/shade/renderer/postprocess/nss/chunk_nss_luma_derivative.js +5 -7
  261. package/src/shade/renderer/postprocess/nss/chunk_nss_tonemap.d.ts +17 -0
  262. package/src/shade/renderer/postprocess/nss/chunk_nss_tonemap.d.ts.map +1 -0
  263. package/src/shade/renderer/postprocess/nss/chunk_nss_tonemap.js +56 -0
  264. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
  265. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +2 -22
  266. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.d.ts.map +1 -1
  267. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +2 -13
  268. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  269. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +10 -13
  270. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts.map +1 -1
  271. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.js +39 -38
  272. package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.d.ts.map +1 -1
  273. package/src/shade/renderer/rasterize/expand/mesh/shader_prefix_sum_to_command.js +7 -12
  274. package/src/shade/renderer/shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.d.ts +8 -6
  275. package/src/shade/renderer/shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.d.ts.map +1 -1
  276. package/src/shade/renderer/shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js +10 -7
  277. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_key.d.ts +16 -0
  278. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_key.d.ts.map +1 -0
  279. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_key.js +35 -0
  280. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_select_finest.d.ts +5 -2
  281. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_select_finest.d.ts.map +1 -1
  282. package/src/shade/renderer/shader/chunk/clipmap/chunk_clipmap_select_finest.js +27 -18
  283. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh2_color_get_irradiance_at.d.ts.map +1 -1
  284. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh2_color_get_irradiance_at.js +5 -15
  285. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_convolve_with_cosine_kernel.d.ts.map +1 -1
  286. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_convolve_with_cosine_kernel.js +5 -19
  287. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh3_windowing.d.ts.map +1 -1
  288. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh3_windowing.js +3 -22
  289. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.d.ts.map +1 -1
  290. package/src/shade/renderer/shadow/map/ShadowmapDrawSelector.js +2 -1
  291. package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_shadow_group_list.d.ts.map +1 -1
  292. package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_shadow_group_list.js +154 -152
  293. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
  294. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +2 -1
  295. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts +3 -1
  296. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts.map +1 -1
  297. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.js +4 -3
  298. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts +7 -1
  299. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts.map +1 -1
  300. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.js +54 -47
  301. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.d.ts.map +1 -1
  302. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.js +371 -370
  303. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  304. package/src/shade/renderer/water/GPUWaterRenderer.js +2 -1
  305. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  306. package/src/shade/renderer/water/surface/lod/shader_water_lod.d.ts.map +1 -1
  307. package/src/shade/renderer/water/surface/lod/shader_water_lod.js +12 -14
  308. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
  309. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +2 -9
  310. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -1
  311. package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +2 -1
  312. package/src/shade/renderer/wind/WIND_FIELD.d.ts +3 -1
  313. package/src/shade/renderer/wind/WIND_FIELD.d.ts.map +1 -1
  314. package/src/shade/renderer/wind/WIND_FIELD.js +4 -3
  315. package/src/shade/renderer/wind/WIND_FIELD_STRUCT.d.ts +8 -2
  316. package/src/shade/renderer/wind/WIND_FIELD_STRUCT.d.ts.map +1 -1
  317. package/src/shade/renderer/wind/WIND_FIELD_STRUCT.js +11 -4
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -2
  319. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  320. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +13 -4
  321. package/src/shade/util/texture_mip_extent.d.ts.map +1 -1
  322. package/src/shade/util/texture_mip_extent.js +88 -87
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +9 -7
  325. package/src/format/image/avif/av1/util/ceil_log2.d.ts.map +0 -1
  326. package/src/shade/renderer/shader/chunk/color/chunk_hash_squirrel3.d.ts +0 -1
  327. package/src/shade/renderer/shader/chunk/color/chunk_hash_squirrel3.d.ts.map +0 -1
  328. package/src/shade/renderer/shader/chunk/color/chunk_hash_squirrel3.js +0 -0
@@ -1,56 +1,69 @@
1
1
  import { assert } from "../../../../../core/assert.js";
2
+ import { ceil_log2 } from "../../../../../core/binary/operations/ceil_log2.js";
3
+ import { ceilPowerOfTwo } from "../../../../../core/binary/operations/ceilPowerOfTwo.js";
2
4
  import { ClipmapCascadePlacement } from "../../../../../core/geom/clipmap/ClipmapCascadePlacement.js";
3
5
  import { BufferDescriptor } from "../../../../descriptor/buffer/BufferDescriptor.js";
4
6
  import { graph_read_buffer } from "../../../buffer/graph_read_buffer.js";
5
- import { graph_build_world_light_clusters } from "../../../light/world_cluster/graph_build_world_light_clusters.js";
6
- import { WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION } from "../../../gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.js";
7
+ import {
8
+ WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION
9
+ } from "../../../gpu_primitive/indirect/WEBGPU_GUARANTEED_MAX_COMPUTE_WORKGROUPS_PER_DIMENSION.js";
7
10
  import {
8
11
  PREFIX_SCAN_CSDLDF_PARTITION_SIZE,
9
12
  shader_prefix_scan_csdldf,
10
13
  shader_prefix_scan_csdldf_prepare
11
14
  } from "../../../gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js";
12
- import { shader_slot_stack_fill, SLOT_STACK_FILL_WORKGROUP_SIZE } from "../../../gpu_primitive/slot_stack/shader_slot_stack_fill.js";
15
+ import {
16
+ shader_slot_stack_fill,
17
+ SLOT_STACK_FILL_WORKGROUP_SIZE
18
+ } from "../../../gpu_primitive/slot_stack/shader_slot_stack_fill.js";
13
19
  import {
14
20
  shader_slot_stack_push_range,
15
21
  SLOT_STACK_PUSH_RANGE_WORKGROUP_SIZE
16
22
  } from "../../../gpu_primitive/slot_stack/shader_slot_stack_push_range.js";
17
- import { CLIPMAP_LEVEL_ARRAY, CLIPMAP_LEVEL_STRUCT } from "../../../shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js";
18
- import { graph_import_buffer } from "../../../shader/graph/graph_import_buffer.js";
23
+ import {
24
+ CLIPMAP_LEVEL_ARRAY,
25
+ CLIPMAP_LEVEL_LIMIT,
26
+ CLIPMAP_LEVEL_STRUCT
27
+ } from "../../../shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js";
19
28
  import { ShaderSwitchSet } from "../../../shader/compiler/ShaderSwitchSet.js";
29
+ import { graph_import_buffer } from "../../../shader/graph/graph_import_buffer.js";
20
30
  import { GPUTileAtlas2D } from "../../../texture/atlas/GPUTileAtlas2D.js";
21
31
  import {
22
- PROBE_CLIPMAP_CASCADE_COUNT_MAX,
23
- PROBE_CLIPMAP_CASCADE_RESOLUTIONS,
24
- PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MAX,
25
- PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MIN
26
- } from "../ProbeClipmapSettings.js";
27
- import { PROBE_EVICTION_STRUCT, PROBE_PROJECTION_ROW_STRUCT, PROBE_RAY_STRUCT, PROBE_RECORD_STRUCT, PROBE_REQUEST_STRUCT } from "./chunk_probe_clipmap.js";
32
+ PROBE_CANDIDATE_STRUCT,
33
+ PROBE_EVICTION_STRUCT,
34
+ PROBE_PROJECTION_ROW_STRUCT,
35
+ PROBE_RAY_STRUCT,
36
+ PROBE_RECORD_STRUCT,
37
+ PROBE_REQUEST_STRUCT
38
+ } from "./chunk_probe_clipmap.js";
28
39
  import { PROBE_SAMPLING_STRUCT } from "./chunk_probe_clipmap_pick.js";
29
40
  import {
41
+ probe_clipmap_guide_words,
42
+ probe_clipmap_maps_words,
30
43
  PROBE_COUNTER_FREE,
31
44
  PROBE_COUNTER_STARVED,
32
45
  PROBE_COUNTER_WORDS,
46
+ PROBE_DEAD_RAYS,
33
47
  PROBE_DISPATCH_ACTIVE,
34
48
  PROBE_DISPATCH_ADMIT,
49
+ PROBE_DISPATCH_ORDER,
35
50
  PROBE_DISPATCH_PUBLISH,
36
51
  PROBE_DISPATCH_RAYS,
37
52
  PROBE_DISPATCH_ROWS,
38
53
  PROBE_DISPATCH_TEXELS,
39
- PROBE_DISPATCH_ORDER,
40
54
  PROBE_DISPATCH_TRACED,
41
55
  PROBE_DISPATCH_WORDS,
42
56
  PROBE_FREE_SLACK,
43
57
  PROBE_RAYS_PER_TEXEL_MAX,
44
58
  PROBE_RAYS_PER_TEXEL_MIN,
59
+ PROBE_RECORD_CASCADE_SHIFT,
45
60
  PROBE_THREAD_WORKGROUP_SIZE,
46
- PROBE_WANT_TILE,
47
- PROBE_WANT_WORKGROUP_TILES,
48
- PROBE_UNIFORM_PERIOD,
49
- probe_clipmap_guide_words,
50
- probe_clipmap_maps_words
61
+ PROBE_UNIFORM_PERIOD
51
62
  } from "./PROBE_CLIPMAP.js";
63
+ import { PROBE_CLIPMAP_RESAMPLING } from "./PROBE_CLIPMAP_RESAMPLING.js";
52
64
  import { shader_probe_clipmap_accumulate } from "./shader_probe_clipmap_accumulate.js";
53
65
  import { shader_probe_clipmap_admit, shader_probe_clipmap_admit_command } from "./shader_probe_clipmap_admit.js";
66
+ import { shader_probe_clipmap_bounce } from "./shader_probe_clipmap_bounce.js";
54
67
  import { shader_probe_clipmap_due } from "./shader_probe_clipmap_due.js";
55
68
  import { shader_probe_clipmap_fill } from "./shader_probe_clipmap_fill.js";
56
69
  import {
@@ -58,29 +71,29 @@ import {
58
71
  shader_probe_clipmap_guide_starts,
59
72
  shader_probe_clipmap_guide_weights
60
73
  } from "./shader_probe_clipmap_guide.js";
74
+ import { shader_probe_clipmap_light } from "./shader_probe_clipmap_light.js";
75
+ import { shader_probe_clipmap_order } from "./shader_probe_clipmap_order.js";
61
76
  import { shader_probe_clipmap_project, shader_probe_clipmap_project_rows } from "./shader_probe_clipmap_project.js";
62
77
  import { shader_probe_clipmap_publish } from "./shader_probe_clipmap_publish.js";
63
- import { shader_probe_clipmap_relocate } from "./shader_probe_clipmap_relocate.js";
64
- import { shader_probe_clipmap_resample } from "./shader_probe_clipmap_resample.js";
65
- import { shader_probe_clipmap_retire } from "./shader_probe_clipmap_retire.js";
66
- import { shader_probe_clipmap_schedule } from "./shader_probe_clipmap_schedule.js";
67
- import { shader_probe_clipmap_light } from "./shader_probe_clipmap_light.js";
68
78
  import {
69
79
  shader_probe_clipmap_ray_command,
70
80
  shader_probe_clipmap_ray_counts,
71
81
  shader_probe_clipmap_ray_layout
72
82
  } from "./shader_probe_clipmap_ray_layout.js";
83
+ import { shader_probe_clipmap_relocate } from "./shader_probe_clipmap_relocate.js";
84
+ import { shader_probe_clipmap_candidate } from "./shader_probe_clipmap_candidate.js";
85
+ import { shader_probe_clipmap_resample } from "./shader_probe_clipmap_resample.js";
86
+ import { shader_probe_clipmap_resample_rays } from "./shader_probe_clipmap_resample_rays.js";
87
+ import { shader_probe_clipmap_retire } from "./shader_probe_clipmap_retire.js";
88
+ import { shader_probe_clipmap_schedule } from "./shader_probe_clipmap_schedule.js";
73
89
  import { shader_probe_clipmap_shade } from "./shader_probe_clipmap_shade.js";
74
90
  import { shader_probe_clipmap_trace } from "./shader_probe_clipmap_trace.js";
75
- import { shader_probe_clipmap_order } from "./shader_probe_clipmap_order.js";
76
91
  import { shader_probe_clipmap_trace_command } from "./shader_probe_clipmap_trace_command.js";
77
- import { shader_probe_clipmap_want } from "./shader_probe_clipmap_want.js";
78
- import { shader_probe_clipmap_want_hits } from "./shader_probe_clipmap_want_hits.js";
79
- import { PROBE_CLIPMAP_RESAMPLING } from "./PROBE_CLIPMAP_RESAMPLING.js";
80
92
 
81
93
  /**
82
94
  * @typedef {import("../ProbeClipmapSettings.js").ProbeClipmapSettings} ProbeClipmapSettings
83
95
  * @typedef {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
96
+ * @typedef {import("./ProbeClipmapScreenWants.js").ProbeClipmapScreenWants|import("./ProbeClipmapHitWants.js").ProbeClipmapHitWants} ProbeClipmapWants
84
97
  */
85
98
 
86
99
  /**
@@ -117,9 +130,12 @@ const SAMPLING_RADIANCE_TILES_PER_ROW_RECIPROCAL = PROBE_SAMPLING_STRUCT.get("ra
117
130
  /**
118
131
  * What shading samples (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8): {@link cascade_count} cascades of
119
132
  * {@link resolution}³ lattice points around the view, {@link spacing} metres apart in the finest
120
- * cascade and twice as far apart in each one around it. A point gets a probe when a pixel wants it, or
121
- * a hit of a probe a pixel wants, and keeps it until its window leaves it or the slots are wanted for
122
- * others, so probes are a sparse cache over the lattice.
133
+ * cascade and twice as far apart in each one around it. A point gets a probe when its wants want it, and
134
+ * keeps it until its window leaves it or the slots are wanted for others, so probes are a sparse cache
135
+ * over the lattice. Two of them make the mode (WORLD_PROBE_CACHE_SCOPE_2026_11_01.md): the frustum's probes,
136
+ * wanted by the frame's pixels ({@link ProbeClipmapScreenWants}), and the world cache, wanted by the
137
+ * frustum's hits where the frustum has no probe ({@link ProbeClipmapHitWants}), its windows the frustum's at
138
+ * 2^k its lattice ({@link place_within}).
123
139
  *
124
140
  * **Storage** (§8.2):
125
141
  * - {@link indirection}, `r32uint`, a texel a lattice point in storage that wraps, the cascades
@@ -127,22 +143,25 @@ const SAMPLING_RADIANCE_TILES_PER_ROW_RECIPROCAL = PROBE_SAMPLING_STRUCT.get("ra
127
143
  * from the structure alone.
128
144
  * - a slot each: a state of two words, the kind and updates and then where relocation moved it
129
145
  * (`PROBE_CLIPMAP.js`), a 48-byte record (`PROBE_RECORD_STRUCT`), an octahedral radiance tile of
130
- * {@link radiance_resolution}² texels and a depth-moment tile of {@link depth_resolution}², each with
131
- * a one-texel skirt, in two 2-D tile atlases. The slots are handed out by a free list on the device.
146
+ * {@link radiance_resolution}² texels and a depth-moment tile of {@link depth_resolution}², in two 2-D
147
+ * tile atlases. The depth tile has a one-texel skirt, which the pick's bilinear tap reads; the radiance
148
+ * tile has one where {@link radiance_skirt}, for the specular's tap, and none where nothing samples it.
149
+ * The slots are handed out by a free list on the device.
132
150
  * - the active lists, double-buffered: each frame's retire reads the last frame's and writes the
133
151
  * frame's; a wanted bit a lattice point and the wanted list, made again every frame; the trace list
134
152
  * of the frame's updates, at most U = ⌊ray_budget / rays_per_probe⌋.
135
153
  *
136
- * **A frame's lifetime** ({@link graph_update}, §8.3, §8.5): the windows are placed around the anchor,
137
- * coarsest first, each a parent cell inside its parent. Retire frees the probes whose points left
138
- * their windows and those the last frame's schedule evicted, want marks the cages one pixel of each
139
- * screen tile reads, the hits' wants the cages the last frame's hits read their bounce from, admit
154
+ * **A frame's windows** ({@link place}, {@link place_within}): around the anchor, coarsest first, each a
155
+ * parent cell inside its parent; or another clipmap's.
156
+ *
157
+ * **A frame's lifetime** ({@link graph_update}, §8.3, §8.5): retire frees the probes whose points left
158
+ * their windows and those the last frame's schedule evicted, the wants mark the cages they read, admit
140
159
  * gives each wanted point without a probe a NEW one, schedule sets the period T from the probes waiting
141
160
  * for an update and the next frame's eviction from the pressure on the slots (`PROBE_FREE_SLACK`), and
142
161
  * the due passes list the frame's updates, NEW probes first.
143
162
  *
144
163
  * **The frame's rays** (§8.6): the lifetime's last passes lay them out. Each listed probe's rays this update
145
- * are a count the budget does not scale (a uniform update's R, a DEAD probe's fewest) and a request it
164
+ * are a count the budget does not scale (a uniform update's R, a DEAD probe's `PROBE_DEAD_RAYS`) and a request it
146
165
  * does (a guided update's, `probe_requests`, which projection sets after each update). Both are scanned
147
166
  * (`graph_prefix_scan_csdldf`'s shaders), the requests are scaled into what the budget leaves, and the
148
167
  * sums of the two are `probe_ray_sums`: a probe's rays follow one another in the trace list's order, and
@@ -150,13 +169,13 @@ const SAMPLING_RADIANCE_TILES_PER_ROW_RECIPROCAL = PROBE_SAMPLING_STRUCT.get("ra
150
169
  *
151
170
  * **The frame's update** (§8.4, §8.6), once the brick clipmap is built: relocate; then the guide, the
152
171
  * CDF over each listed probe's history that its guided updates' rays follow (`PROBE_UNIFORM_PERIOD`);
153
- * then trace, a ray a thread, each with its hit and the suns' shadow rays from there.
172
+ * then trace, a ray a thread, each with its hit and the suns' shadow rays from there; shade, the local
173
+ * lights, and the bounce from two clipmaps, the second where the first has no probe (§8.7).
154
174
  *
155
- * Retire, admit, due and the update run through commands written on the device, want over the screen's
175
+ * Retire, admit, due and the update run through commands written on the device, the screen's wants over its
156
176
  * tiles: nothing is sized by the capacity.
157
177
  *
158
- * **Capacity** starts at `2·N²·C` slots, rounded up to a power of two: a visible surface crosses each
159
- * cascade as a shell a cell thick, doubled for the cage. An admission the free list could not serve is
178
+ * **Capacity** starts at what its maker gives, a power of two. An admission the free list could not serve is
160
179
  * counted on the device and read back, and the next frame doubles the capacity (§7.10's pattern). Nothing
161
180
  * shrinks.
162
181
  */
@@ -195,12 +214,30 @@ export class GPUProbeClipmap {
195
214
  */
196
215
  depth_resolution;
197
216
 
217
+ /**
218
+ * Whether a radiance tile has a skirt of a texel, which a reader's bilinear tap needs; a clipmap whose
219
+ * radiance is only loaded texel by texel, never sampled, has none.
220
+ * @type {boolean}
221
+ * @readonly
222
+ */
223
+ radiance_skirt;
224
+
225
+ /**
226
+ * What its GPU objects' labels begin with.
227
+ * @type {string}
228
+ * @readonly
229
+ */
230
+ label;
231
+
198
232
  /** @type {GPUDevice} */
199
233
  #device;
200
234
 
201
235
  /** @type {ClipmapCascadePlacement} */
202
236
  #placement;
203
237
 
238
+ /** The frame {@link place} or {@link place_within} last placed the windows in, of {@link graph_update}'s count. */
239
+ #placed_frame = -1;
240
+
204
241
  /** @type {GPUTexture} */
205
242
  #indirection;
206
243
 
@@ -261,8 +298,21 @@ export class GPUProbeClipmap {
261
298
  */
262
299
  #resamples = null;
263
300
 
264
- /** Whether the frame's updates re-sample their neighbours, and the switches accumulate is recorded with. */
265
- #resampling = false;
301
+ /**
302
+ * Each listed probe's candidate, the place in the list of the neighbour whose rays it re-samples and their weight,
303
+ * as many as the trace list holds. @type {GPUBuffer|null}
304
+ */
305
+ #candidates = null;
306
+
307
+ /** A word a slot: its place in the frame's trace list, as relocation writes it. @type {GPUBuffer|null} */
308
+ #listed = null;
309
+
310
+ /**
311
+ * Whether the frame's updates re-sample their neighbours' histories, and their rays, and the switches accumulate
312
+ * is recorded with.
313
+ */
314
+ #history_resampling = false;
315
+ #ray_resampling = false;
266
316
  #accumulate_switches = ShaderSwitchSet.EMPTY;
267
317
 
268
318
  /** The listed probes' projected rows, n_r a probe, as many as the trace list holds. @type {GPUBuffer|null} */
@@ -311,6 +361,9 @@ export class GPUProbeClipmap {
311
361
  /** Lattice points over every cascade. */
312
362
  #key_count = 0;
313
363
 
364
+ /** Points the wanted list holds: the fewer of the keys and what the wants can want, as it last grew. */
365
+ #wanted_capacity = 0;
366
+
314
367
  /** Whether the next frame is the first, which fills the indirection and the free list. */
315
368
  #fill_pending = true;
316
369
 
@@ -338,37 +391,48 @@ export class GPUProbeClipmap {
338
391
  #levels_f32 = new Float32Array(this.#levels_data);
339
392
 
340
393
  #retire_settings = { capacity: 0, resolution: 0, frame: 0 };
341
- #want_settings = { cascade_count: 0, resolution: 0, frame: 0, key_count: 0 };
342
- #want_hits_settings = { cascade_count: 0, resolution: 0, key_count: 0 };
343
- #admit_command_settings = { key_count: 0 };
344
- #admit_settings = { capacity: 0, resolution: 0, key_count: 0, frame: 0 };
345
- #schedule_settings = { capacity: 0, key_count: 0, trace_capacity: 0, slack: 0 };
394
+ #want_settings = { cascade_count: 0, resolution: 0, frame: 0, wanted_capacity: 0 };
395
+ #admit_command_settings = { wanted_capacity: 0 };
396
+ #admit_settings = { capacity: 0, resolution: 0, wanted_capacity: 0, frame: 0 };
397
+ #schedule_settings = { capacity: 0, wanted_capacity: 0, trace_capacity: 0, slack: 0 };
346
398
  #due_settings = { capacity: 0, trace_capacity: 0, frame: 0, new_only: 0 };
347
- #trace_command_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0 };
399
+ #trace_command_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0, radiance_skirt: 0 };
348
400
  #order_settings = { trace_capacity: 0, resolution: 0, axis_bits: 0 };
349
- #ray_counts_settings = { trace_capacity: 0, rays_per_probe: 0, rays_min: 0, radiance_resolution: 0, uniform_period: PROBE_UNIFORM_PERIOD };
401
+ #ray_counts_settings = { trace_capacity: 0, rays_per_probe: 0, rays_min: 0, rays_dead: 0, radiance_resolution: 0, uniform_period: PROBE_UNIFORM_PERIOD };
350
402
  #ray_layout_settings = { trace_capacity: 0, ray_budget: 0 };
351
403
  #relocate_settings = { trace_capacity: 0, brick_cascade_count: 0 };
352
- #guide_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, radiance_tiles_per_row: 0 };
404
+ #guide_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, radiance_tiles_per_row: 0, radiance_skirt: 0 };
353
405
  #trace_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, brick_cascade_count: 0, t_max: 0, uniform_period: PROBE_UNIFORM_PERIOD };
354
- #accumulate_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, depth_resolution: 0, radiance_tiles_per_row: 0, depth_tiles_per_row: 0, frame: 0, response_frames: 0, uniform_period: PROBE_UNIFORM_PERIOD };
355
- #project_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, depth_resolution: 0, frame: 0, uniform_period: PROBE_UNIFORM_PERIOD, rays_min: 0, rays_max: 0, response_frames: 0 };
356
- #publish_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0, radiance_tiles_per_row: 0, depth_tiles_per_row: 0 };
406
+ #accumulate_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, depth_resolution: 0, radiance_tiles_per_row: 0, radiance_skirt: 0, depth_tiles_per_row: 0, uniform_period: PROBE_UNIFORM_PERIOD };
407
+ #project_settings = { trace_capacity: 0, rays_per_probe: 0, radiance_resolution: 0, depth_resolution: 0, frame: 0, uniform_period: PROBE_UNIFORM_PERIOD, rays_min: 0, rays_max: 0 };
408
+ #publish_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0, radiance_tiles_per_row: 0, radiance_skirt: 0, depth_tiles_per_row: 0 };
357
409
  #resample_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0, frame: 0, response_frames: 0 };
410
+ #candidate_settings = { trace_capacity: 0 };
411
+ #resample_rays_settings = { trace_capacity: 0, radiance_resolution: 0, depth_resolution: 0, rays_per_probe: 0, uniform_period: PROBE_UNIFORM_PERIOD };
358
412
  #push_settings = { first: 0, count: 0, counter: PROBE_COUNTER_FREE };
359
413
 
360
414
  #bindings = {};
361
415
 
416
+ /** What a want binds of this clipmap: its levels, wanted list and bits, and its want settings. */
417
+ #want_bindings = {};
418
+
419
+ /** The bounce's sets as their clipmaps hold them, under the bounce pass's names. */
420
+ #set_bindings = {};
421
+
362
422
  /** The ray counts' scan's, which names its buffers its own way. */
363
423
  #ray_scan_bindings = { scan_in: null, scan_out: null, spine: null, command: null };
364
424
 
365
- #lifetime_data = { counters: -1, depth: -1, normal: -1, stbn: -1 };
425
+ #lifetime_data = { counters: -1, stbn: -1, want_depth: -1, want_normal: -1 };
366
426
 
367
427
  #update_data = { counters: -1, bricks: -1, world_cluster_lookup: -1, world_cluster_data: -1 };
368
428
 
369
- /** The coarsest brick window's box, metres, which the world light clusters cull lights against. */
370
- #clusters_min = [0, 0, 0];
371
- #clusters_max = [0, 0, 0];
429
+ /** The frame's wants. @type {ProbeClipmapWants|null} */
430
+ #wants = null;
431
+
432
+ /** The clipmaps the frame's hits take their bounce from, the second where the first has no probe. @type {GPUProbeClipmap|null} */
433
+ #bounce_first = null;
434
+ /** @type {GPUProbeClipmap|null} */
435
+ #bounce_fallback = null;
372
436
 
373
437
  /** The frame's brick clipmap, which the update's rays read. @type {import("../brick/GPUBrickClipmap.js").GPUBrickClipmap|null} */
374
438
  #brick_clipmap = null;
@@ -383,37 +447,50 @@ export class GPUProbeClipmap {
383
447
  /** The frame's row → card set table. @type {GPUBuffer|null} */
384
448
  #card_rows = null;
385
449
 
386
- /** The frame's: the want's launch and what it reads. */
387
- #want_groups = [0, 0];
388
-
389
- /** @type {GPUBuffer|null} */
390
- #camera = null;
391
-
392
450
  /**
393
451
  * @param {GPUDevice} device
394
452
  * @param {object} options
395
- * @param {number} options.cascade_count
396
- * @param {number} options.resolution one of {@link PROBE_CLIPMAP_CASCADE_RESOLUTIONS}
453
+ * @param {number} options.cascade_count at most the levels table holds, {@link CLIPMAP_LEVEL_LIMIT}, and
454
+ * the record's cascade field, {@link PROBE_RECORD_CASCADE_SHIFT}
455
+ * @param {number} options.resolution a power of two, at most 1024: the order's Morton code takes 10 bits
456
+ * an axis; the indirection's height, resolution · cascade_count, at most the device's
457
+ * `maxTextureDimension3D`
397
458
  * @param {number} options.spacing metres
398
- * @param {number} options.radiance_resolution a power of two
459
+ * @param {number} options.radiance_resolution a power of two from 2, which the update's bit-reversed
460
+ * walk of the texels needs
399
461
  * @param {number} options.depth_resolution a power of two
462
+ * @param {boolean} options.radiance_skirt whether a radiance tile has a skirt for a reader's bilinear tap
463
+ * (`chunk_probe_clipmap_sample_radiance`): a clipmap whose radiance nothing samples has none
464
+ * @param {string} options.label what its GPU objects' labels begin with
465
+ * @param {number} options.capacity the slots it starts with, a power of two: a start, which admissions the
466
+ * free list cannot serve grow
400
467
  */
401
- constructor(device, { cascade_count, resolution, spacing, radiance_resolution, depth_resolution }) {
468
+ constructor(device, { cascade_count, resolution, spacing, radiance_resolution, depth_resolution, radiance_skirt, label, capacity }) {
402
469
  assert.isPositiveInteger(cascade_count, 'cascade_count');
403
- assert.lessThanOrEqual(cascade_count, PROBE_CLIPMAP_CASCADE_COUNT_MAX, 'cascade_count');
404
- assert.isOneOf(resolution, PROBE_CLIPMAP_CASCADE_RESOLUTIONS, 'resolution');
470
+ assert.lessThanOrEqual(cascade_count, CLIPMAP_LEVEL_LIMIT, "cascade_count, the levels table's length");
471
+ assert.lessThanOrEqual(cascade_count, 2 ** (32 - PROBE_RECORD_CASCADE_SHIFT), "cascade_count, the record's cascade field");
472
+ assert.isPositiveInteger(resolution, 'resolution');
473
+ assert.lessThanOrEqual(ceil_log2(resolution), 10, "resolution, the order's Morton code's 10 bits an axis");
474
+ // the order's key: the cascade above the Morton code of a lattice point in its window
475
+ assert.lessThanOrEqual(3 * ceil_log2(resolution) + ceil_log2(cascade_count), 32, 'the order key fits a word');
476
+ assert.lessThanOrEqual(resolution * cascade_count, device.limits.maxTextureDimension3D, "resolution · cascade_count, the indirection's height, past maxTextureDimension3D");
405
477
  assert.isFinite(spacing, 'spacing');
406
478
  assert.greaterThan(spacing, 0, 'spacing');
407
- assert.greaterThanOrEqual(radiance_resolution, PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MIN, 'radiance_resolution');
408
- assert.lessThanOrEqual(radiance_resolution, PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MAX, 'radiance_resolution');
409
- assert.greaterThanOrEqual(depth_resolution, PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MIN, 'depth_resolution');
410
- assert.lessThanOrEqual(depth_resolution, PROBE_CLIPMAP_OCTAHEDRAL_RESOLUTION_MAX, 'depth_resolution');
479
+ assert.isPositiveInteger(radiance_resolution, 'radiance_resolution');
480
+ assert.greaterThanOrEqual(radiance_resolution, 2, 'radiance_resolution');
481
+ assert.isPositiveInteger(depth_resolution, 'depth_resolution');
482
+ assert.isBoolean(radiance_skirt, 'radiance_skirt');
483
+ assert.isString(label, 'label');
484
+ assert.isPositiveInteger(capacity, 'capacity');
485
+ assert.equal(ceilPowerOfTwo(capacity), capacity, 'capacity must be a power of two');
411
486
 
412
487
  this.cascade_count = cascade_count;
413
488
  this.resolution = resolution;
414
489
  this.spacing = spacing;
415
490
  this.radiance_resolution = radiance_resolution;
416
491
  this.depth_resolution = depth_resolution;
492
+ this.radiance_skirt = radiance_skirt;
493
+ this.label = label;
417
494
 
418
495
  this.#device = device;
419
496
 
@@ -427,7 +504,7 @@ export class GPUProbeClipmap {
427
504
  });
428
505
 
429
506
  this.#indirection = device.createTexture({
430
- label: 'Probe clipmap / probe indirection',
507
+ label: `${label} / probe indirection`,
431
508
  size: [resolution, resolution, resolution * cascade_count],
432
509
  dimension: '3d',
433
510
  format: 'r32uint',
@@ -436,17 +513,16 @@ export class GPUProbeClipmap {
436
513
 
437
514
  this.#indirection_view = this.#indirection.createView();
438
515
 
439
- // a power of two at least 2·N²·C
440
- const capacity = this.#capacity = 2 ** Math.ceil(Math.log2(2 * resolution * resolution * cascade_count));
516
+ this.#capacity = capacity;
441
517
  const keys = this.#key_count = resolution ** 3 * cascade_count;
442
518
 
443
519
  this.#radiance = new GPUTileAtlas2D({
444
520
  device,
445
521
  formats: ['rgba16float'],
446
- tile_size: [radiance_resolution + 2, radiance_resolution + 2],
522
+ tile_size: [radiance_resolution + 2 * this.#radiance_skirt_texels(), radiance_resolution + 2 * this.#radiance_skirt_texels()],
447
523
  // sampled by the readers and the accumulation's history, stored into by publish
448
524
  usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
449
- label: 'Probe clipmap / probe radiance',
525
+ label: `${label} / probe radiance`,
450
526
  capacity,
451
527
  });
452
528
 
@@ -455,7 +531,7 @@ export class GPUProbeClipmap {
455
531
  formats: ['rg16float'],
456
532
  tile_size: [depth_resolution + 2, depth_resolution + 2],
457
533
  usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
458
- label: 'Probe clipmap / probe depth',
534
+ label: `${label} / probe depth`,
459
535
  capacity,
460
536
  });
461
537
 
@@ -465,11 +541,12 @@ export class GPUProbeClipmap {
465
541
  this.#requests = this.#create_buffer('probe requests', PROBE_REQUEST_STRUCT.size * capacity, GPUBufferUsage.COPY_SRC);
466
542
  this.#records = this.#create_buffer('probe records', PROBE_RECORD_STRUCT.size * capacity, GPUBufferUsage.COPY_SRC);
467
543
  this.#free = this.#create_buffer('probe free list', 4 * capacity, GPUBufferUsage.COPY_SRC);
544
+ // anything: only the trace list confirms an entry
545
+ this.#listed = this.#create_buffer('probe listed', 4 * capacity, GPUBufferUsage.COPY_SRC);
468
546
  this.#active.push(
469
547
  this.#create_buffer('probe active 0', LIST_HEADER_BYTES + 4 * capacity, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST),
470
548
  this.#create_buffer('probe active 1', LIST_HEADER_BYTES + 4 * capacity, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST),
471
549
  );
472
- this.#wanted = this.#create_buffer('probe wanted', LIST_HEADER_BYTES + 4 * keys, GPUBufferUsage.COPY_DST);
473
550
  this.#wanted_bits = this.#create_buffer('probe wanted bits', 4 * Math.ceil(keys / 32), GPUBufferUsage.COPY_DST);
474
551
  this.#counters = this.#create_buffer('probe counters', 4 * PROBE_COUNTER_WORDS, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
475
552
  // zero: the first frame's retire dispatches nothing
@@ -485,13 +562,13 @@ export class GPUProbeClipmap {
485
562
  device.queue.writeBuffer(this.#counters, 0, counters);
486
563
 
487
564
  this.#levels = device.createBuffer(BufferDescriptor.fromJSON({
488
- label: 'Probe clipmap / probe levels',
565
+ label: `${label} / probe levels`,
489
566
  size: CLIPMAP_LEVEL_ARRAY.size,
490
567
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
491
568
  }));
492
569
 
493
570
  this.#sampling = device.createBuffer(BufferDescriptor.fromJSON({
494
- label: 'Probe clipmap / probe sampling',
571
+ label: `${label} / probe sampling`,
495
572
  size: PROBE_SAMPLING_STRUCT.size,
496
573
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
497
574
  }));
@@ -525,6 +602,41 @@ export class GPUProbeClipmap {
525
602
  return this.#indirection;
526
603
  }
527
604
 
605
+ /**
606
+ * The last update's probes, in its order: the list the rays name their probe by. With {@link origins},
607
+ * {@link rays} and {@link dispatch}, what another clipmap's hits' wants read (`ProbeClipmapHitWants`),
608
+ * before this clipmap's next lifetime writes them over.
609
+ * @returns {GPUBuffer}
610
+ */
611
+ get trace() {
612
+ return this.#trace;
613
+ }
614
+
615
+ /**
616
+ * Where relocation left each of the last update's probes, `vec4<f32>(origin, spacing)`.
617
+ * @returns {GPUBuffer}
618
+ */
619
+ get origins() {
620
+ return this.#origins;
621
+ }
622
+
623
+ /**
624
+ * The last update's rays, `PROBE_RAY_STRUCT`.
625
+ * @returns {GPUBuffer}
626
+ */
627
+ get rays() {
628
+ return this.#rays;
629
+ }
630
+
631
+
632
+ /**
633
+ * The indirect commands, `PROBE_DISPATCH_RAYS` the last update's rays' launch among them.
634
+ * @returns {GPUBuffer}
635
+ */
636
+ get dispatch() {
637
+ return this.#dispatch;
638
+ }
639
+
528
640
  /**
529
641
  * The cascades' cage windows, a {@link CLIPMAP_LEVEL_ARRAY} as a uniform, finest first, as placed by
530
642
  * the last {@link graph_update}: a cell is a cage of eight lattice points, so a window is one cell
@@ -546,10 +658,10 @@ export class GPUProbeClipmap {
546
658
  /**
547
659
  * @param {number} cascade
548
660
  * @param {number} axis
549
- * @returns {number} the cascade's lattice window's least point on the axis, in its spacing
661
+ * @returns {number} the cascade's lattice window's least point on the axis, in its spacing, as last placed
550
662
  */
551
663
  corner(cascade, axis) {
552
- return this.#placement.corner(cascade, axis);
664
+ return this.#levels_i32[((cascade * CLIPMAP_LEVEL_STRUCT.aligned_size) >>> 2) + axis];
553
665
  }
554
666
 
555
667
  /**
@@ -557,7 +669,7 @@ export class GPUProbeClipmap {
557
669
  * @returns {number} metres between the cascade's probes
558
670
  */
559
671
  cell_size(cascade) {
560
- return this.#placement.cell_size(cascade);
672
+ return this.spacing * 2 ** cascade;
561
673
  }
562
674
 
563
675
  /**
@@ -573,21 +685,87 @@ export class GPUProbeClipmap {
573
685
  }
574
686
 
575
687
  /**
576
- * Record the frame's lifetime (§8.3): place the windows around the anchor, retire, want from the
577
- * G-buffer, admit and schedule; then, once the bricks are built, its updates: relocate, trace and
578
- * shade the listed probes' rays (§8.4–§8.7). Allocates nothing per frame.
688
+ * Place the windows around the anchor, coarsest first, each a parent cell inside its parent, for the
689
+ * frame's {@link graph_update}.
690
+ *
691
+ * @param {number} x the anchor, world metres
692
+ * @param {number} y
693
+ * @param {number} z
694
+ */
695
+ place(x, y, z) {
696
+ assert.isFinite(x, 'x');
697
+ assert.isFinite(y, 'y');
698
+ assert.isFinite(z, 'z');
699
+
700
+ const placement = this.#placement;
701
+ const n = this.resolution;
702
+
703
+ placement.begin();
704
+
705
+ for (let c = this.cascade_count - 1; c >= 0; c--) {
706
+ placement.place(c, x, y, z);
707
+ }
708
+
709
+ for (let c = 0; c < this.cascade_count; c++) {
710
+ const level = (c * CLIPMAP_LEVEL_STRUCT.aligned_size) >>> 2;
711
+
712
+ for (let axis = 0; axis < 3; axis++) {
713
+ this.#levels_i32[level + axis] = placement.corner(c, axis);
714
+ // the cages: a cell between two lattice points
715
+ this.#levels_i32[level + 4 + axis] = n - 1;
716
+ }
717
+
718
+ this.#levels_f32[level + 3] = placement.cell_size(c);
719
+ }
720
+
721
+ this.#placed_frame = this.#frame;
722
+ }
723
+
724
+ /**
725
+ * Take another clipmap's windows, as {@link place} last placed them, at 2^k this clipmap's lattice
726
+ * (WORLD_PROBE_CACHE_SCOPE_2026_11_01.md §1.2): the same cascades, each the other's window and spacing over
727
+ * 2^k, its corner 2^k the other's, so every point of the other's lattice is one of this clipmap's and the
728
+ * two scroll together. k is the ratio of the resolutions, a power of two from 2.
729
+ *
730
+ * @param {GPUProbeClipmap} clipmap placed this frame
731
+ */
732
+ place_within(clipmap) {
733
+ assert.defined(clipmap, 'clipmap');
734
+ assert.equal(clipmap.cascade_count, this.cascade_count, 'cascade_count, the other clipmap\'s');
735
+
736
+ const ratio = this.resolution / clipmap.resolution;
737
+ const shift = Math.log2(ratio);
738
+
739
+ assert.isPositiveInteger(shift, 'resolution, the other clipmap\'s times a power of two from 2');
740
+ assert.equal(this.spacing * ratio, clipmap.spacing, 'spacing, the other clipmap\'s over the ratio of the resolutions');
741
+
742
+ const n = clipmap.resolution;
743
+
744
+ for (let c = 0; c < this.cascade_count; c++) {
745
+ const level = (c * CLIPMAP_LEVEL_STRUCT.aligned_size) >>> 2;
746
+
747
+ for (let axis = 0; axis < 3; axis++) {
748
+ this.#levels_i32[level + axis] = clipmap.corner(c, axis) * ratio;
749
+ // the other's cages, each 2^k of this clipmap's cells across
750
+ this.#levels_i32[level + 4 + axis] = (n - 1) * ratio;
751
+ }
752
+
753
+ this.#levels_f32[level + 3] = this.cell_size(c);
754
+ }
755
+
756
+ this.#placed_frame = this.#frame;
757
+ }
758
+
759
+ /**
760
+ * Record the frame's lifetime in the windows {@link place} or {@link place_within} placed this frame
761
+ * (§8.3): retire, the wants, admit and schedule; then, once the bricks are built, its updates: relocate,
762
+ * trace, shade, light and bounce the listed probes' rays (§8.4–§8.7). Allocates nothing per frame.
579
763
  *
580
764
  * @param {Object} options
581
765
  * @param {FrameGraph} options.graph
582
- * @param {number} options.x the anchor, world metres
583
- * @param {number} options.y
584
- * @param {number} options.z
585
- * @param {number} options.depth graph handle of the frame's depth
586
- * @param {number} options.normal graph handle of the G-buffer's normals
587
- * @param {GPUBuffer} options.camera the view's camera uniform
766
+ * @param {ProbeClipmapWants} options.wants who wants the frame's probes
588
767
  * @param {*} options.stbn the 2-channel spatio-temporal blue noise, `STATIC_GRAPHICS_ENGINE_ASSETS.stbn_vec2`
589
- * @param {ArrayLike<number>} options.resolution the frame's pixels, x and y
590
- * @param {number} options.response_frames frames of the blend's response, τ (§8.8)
768
+ * @param {number} options.response_frames frames over which a re-sampled neighbour's history goes stale, τ
591
769
  * @param {number} options.ray_budget rays a frame
592
770
  * @param {number} options.rays_per_probe rays an update, R: the frame updates ⌊ray_budget / R⌋ probes at most
593
771
  * @param {import("../brick/GPUBrickClipmap.js").GPUBrickClipmap} options.brick_clipmap the world the
@@ -597,12 +775,18 @@ export class GPUProbeClipmap {
597
775
  * @param {import("../../../scene/GPUSceneContext.js").GPUSceneContext} options.scene the scene the rays
598
776
  * light and shade: its lights, its environment, its rows and their geometry caches' cards
599
777
  * @param {GPUBuffer} options.card_rows the row → card set table, a word a `meshes` row
600
- * @param {boolean} options.resampling whether each update re-samples its neighbours, adding what they have
601
- * seen to its rays (`shader_probe_clipmap_resample`)
778
+ * @param {boolean} options.history_resampling whether each update re-samples its neighbours' histories, adding
779
+ * what they have seen to its rays (`shader_probe_clipmap_resample`); never where the radiance has no skirt
780
+ * @param {boolean} options.ray_resampling whether each update re-samples one neighbour's rays of the frame,
781
+ * adding them to its own (`shader_probe_clipmap_candidate`, `shader_probe_clipmap_resample_rays`)
782
+ * @param {{lookup: number, data: number}} options.clusters graph handles of the world light clusters over the
783
+ * bricks' cascades, which the hits' local lights come from
784
+ * @param {GPUProbeClipmap} options.bounce_first the clipmap a hit takes its next bounce from first
785
+ * @param {GPUProbeClipmap} options.bounce_fallback the clipmap it takes it from where the first has no probe
602
786
  */
603
- graph_update({ graph, x, y, z, depth, normal, camera, stbn, resolution, response_frames, ray_budget, rays_per_probe, brick_clipmap, bricks, scene, card_rows, resampling }) {
787
+ graph_update({ graph, wants, stbn, response_frames, ray_budget, rays_per_probe, brick_clipmap, bricks, scene, card_rows, history_resampling, ray_resampling, clusters, bounce_first, bounce_fallback }) {
604
788
  assert.defined(graph, 'graph');
605
- assert.defined(camera, 'camera');
789
+ assert.defined(wants, 'wants');
606
790
  assert.defined(stbn, 'stbn');
607
791
  assert.isFinite(response_frames, 'response_frames');
608
792
  assert.greaterThan(response_frames, 0, 'response_frames');
@@ -612,7 +796,14 @@ export class GPUProbeClipmap {
612
796
  assert.isNonNegativeInteger(bricks, 'bricks');
613
797
  assert.defined(scene, 'scene');
614
798
  assert.defined(card_rows, 'card_rows');
615
- assert.isBoolean(resampling, 'resampling');
799
+ assert.isBoolean(history_resampling, 'history_resampling');
800
+ assert.ok(!history_resampling || this.radiance_skirt, 'history_resampling taps the neighbours\' radiance, which a clipmap without a skirt cannot');
801
+ assert.isBoolean(ray_resampling, 'ray_resampling');
802
+ assert.isNonNegativeInteger(clusters.lookup, 'clusters.lookup');
803
+ assert.isNonNegativeInteger(clusters.data, 'clusters.data');
804
+ assert.defined(bounce_first, 'bounce_first');
805
+ assert.defined(bounce_fallback, 'bounce_fallback');
806
+ assert.equal(this.#placed_frame, this.#frame, 'windows placed this frame: place() or place_within() first');
616
807
  assert.notOk(this.#destroyed, 'destroyed');
617
808
 
618
809
  if (this.#grow_pending) {
@@ -622,16 +813,15 @@ export class GPUProbeClipmap {
622
813
 
623
814
  const trace_capacity = Math.floor(ray_budget / rays_per_probe);
624
815
  const texels = this.radiance_resolution * this.radiance_resolution;
625
- const rays_min = PROBE_RAYS_PER_TEXEL_MIN * texels;
816
+ const rays_min = Math.min(PROBE_RAYS_PER_TEXEL_MIN * texels, rays_per_probe);
817
+ const rays_dead = Math.min(PROBE_DEAD_RAYS, rays_per_probe);
626
818
  const rays_max = PROBE_RAYS_PER_TEXEL_MAX * texels;
627
819
 
628
820
  this.#ensure_trace(trace_capacity);
629
821
  // the requests share what the counts leave of the budget, so the frame's rays are at most it
630
822
  this.#ensure_rays(ray_budget);
631
823
 
632
- this.#place(x, y, z);
633
-
634
- this.#device.queue.writeBuffer(this.#levels, 0, this.#levels_data);
824
+ this.#device.queue.writeBuffer(this.#levels, 0, this.#levels_data, 0, this.cascade_count * CLIPMAP_LEVEL_STRUCT.aligned_size);
635
825
 
636
826
  // the readers' view of the clipmap: its shape, and the depth and radiance atlases', which grow by rows
637
827
  const depth_texture = this.#depth.texture_at(0);
@@ -660,24 +850,20 @@ export class GPUProbeClipmap {
660
850
  this.#want_settings.cascade_count = this.cascade_count;
661
851
  this.#want_settings.resolution = this.resolution;
662
852
  this.#want_settings.frame = this.#frame;
663
- this.#want_settings.key_count = this.#key_count;
853
+ this.#ensure_wanted(Math.min(this.#key_count, wants.wanted_bound()));
664
854
 
665
- // the hits' wants read the last frame's rays, each naming its probe
666
- const want_hits = this.#want_hits_settings;
855
+ this.#want_settings.wanted_capacity = this.#wanted_capacity;
667
856
 
668
- want_hits.cascade_count = this.cascade_count;
669
- want_hits.resolution = this.resolution;
670
- want_hits.key_count = this.#key_count;
671
857
 
672
- this.#admit_command_settings.key_count = this.#key_count;
858
+ this.#admit_command_settings.wanted_capacity = this.#wanted_capacity;
673
859
 
674
860
  this.#admit_settings.capacity = this.#capacity;
675
861
  this.#admit_settings.resolution = this.resolution;
676
- this.#admit_settings.key_count = this.#key_count;
862
+ this.#admit_settings.wanted_capacity = this.#wanted_capacity;
677
863
  this.#admit_settings.frame = this.#frame;
678
864
 
679
865
  this.#schedule_settings.capacity = this.#capacity;
680
- this.#schedule_settings.key_count = this.#key_count;
866
+ this.#schedule_settings.wanted_capacity = this.#wanted_capacity;
681
867
  this.#schedule_settings.trace_capacity = trace_capacity;
682
868
  this.#schedule_settings.slack = Math.ceil(this.#capacity * PROBE_FREE_SLACK);
683
869
 
@@ -688,19 +874,18 @@ export class GPUProbeClipmap {
688
874
  this.#trace_command_settings.trace_capacity = trace_capacity;
689
875
  this.#trace_command_settings.radiance_resolution = this.radiance_resolution;
690
876
  this.#trace_command_settings.depth_resolution = this.depth_resolution;
877
+ this.#trace_command_settings.radiance_skirt = this.#radiance_skirt_texels();
691
878
 
692
879
  const order = this.#order_settings;
693
880
 
694
881
  order.trace_capacity = trace_capacity;
695
882
  order.resolution = this.resolution;
696
- order.axis_bits = Math.ceil(Math.log2(this.resolution));
697
-
698
- // the order's key: the cascade above the Morton code of a lattice point in its window
699
- assert.lessThanOrEqual(3 * order.axis_bits + Math.ceil(Math.log2(this.cascade_count)), 32, 'the order key fits a word');
883
+ order.axis_bits = ceil_log2(this.resolution);
700
884
 
701
885
  this.#ray_counts_settings.trace_capacity = trace_capacity;
702
886
  this.#ray_counts_settings.rays_per_probe = rays_per_probe;
703
887
  this.#ray_counts_settings.rays_min = rays_min;
888
+ this.#ray_counts_settings.rays_dead = rays_dead;
704
889
  this.#ray_counts_settings.radiance_resolution = this.radiance_resolution;
705
890
 
706
891
  this.#ray_layout_settings.trace_capacity = trace_capacity;
@@ -712,6 +897,7 @@ export class GPUProbeClipmap {
712
897
  guide.rays_per_probe = rays_per_probe;
713
898
  guide.radiance_resolution = this.radiance_resolution;
714
899
  guide.radiance_tiles_per_row = this.#radiance.tiles_per_row;
900
+ guide.radiance_skirt = this.#radiance_skirt_texels();
715
901
 
716
902
  // past the coarsest window's far corner every ray has left the clipmap
717
903
  const coarsest = brick_clipmap.cascade_count - 1;
@@ -732,9 +918,8 @@ export class GPUProbeClipmap {
732
918
  accumulate.radiance_resolution = this.radiance_resolution;
733
919
  accumulate.depth_resolution = this.depth_resolution;
734
920
  accumulate.radiance_tiles_per_row = this.#radiance.tiles_per_row;
921
+ accumulate.radiance_skirt = this.#radiance_skirt_texels();
735
922
  accumulate.depth_tiles_per_row = this.#depth.tiles_per_row;
736
- accumulate.frame = this.#frame;
737
- accumulate.response_frames = response_frames;
738
923
 
739
924
  this.#project_settings.trace_capacity = trace_capacity;
740
925
  this.#project_settings.rays_per_probe = rays_per_probe;
@@ -743,7 +928,6 @@ export class GPUProbeClipmap {
743
928
  this.#project_settings.frame = this.#frame;
744
929
  this.#project_settings.rays_min = rays_min;
745
930
  this.#project_settings.rays_max = rays_max;
746
- this.#project_settings.response_frames = response_frames;
747
931
 
748
932
  const resample = this.#resample_settings;
749
933
 
@@ -753,8 +937,18 @@ export class GPUProbeClipmap {
753
937
  resample.frame = this.#frame;
754
938
  resample.response_frames = response_frames;
755
939
 
756
- this.#resampling = resampling;
757
- this.#accumulate_switches = ShaderSwitchSet.EMPTY.with(PROBE_CLIPMAP_RESAMPLING, resampling);
940
+ this.#candidate_settings.trace_capacity = trace_capacity;
941
+
942
+ const resample_rays = this.#resample_rays_settings;
943
+
944
+ resample_rays.trace_capacity = trace_capacity;
945
+ resample_rays.radiance_resolution = this.radiance_resolution;
946
+ resample_rays.depth_resolution = this.depth_resolution;
947
+ resample_rays.rays_per_probe = rays_per_probe;
948
+
949
+ this.#history_resampling = history_resampling;
950
+ this.#ray_resampling = ray_resampling;
951
+ this.#accumulate_switches = ShaderSwitchSet.EMPTY.with(PROBE_CLIPMAP_RESAMPLING, history_resampling || ray_resampling);
758
952
 
759
953
  const publish = this.#publish_settings;
760
954
 
@@ -762,53 +956,30 @@ export class GPUProbeClipmap {
762
956
  publish.radiance_resolution = this.radiance_resolution;
763
957
  publish.depth_resolution = this.depth_resolution;
764
958
  publish.radiance_tiles_per_row = this.#radiance.tiles_per_row;
959
+ publish.radiance_skirt = this.#radiance_skirt_texels();
765
960
  publish.depth_tiles_per_row = this.#depth.tiles_per_row;
766
961
 
767
962
  this.#brick_clipmap = brick_clipmap;
768
963
  this.#scene = scene;
769
964
  this.#card_rows = card_rows;
770
965
 
771
- const tiles_x = Math.ceil(resolution[0] / PROBE_WANT_TILE);
772
- const tiles_y = Math.ceil(resolution[1] / PROBE_WANT_TILE);
773
-
774
- this.#want_groups[0] = Math.ceil(tiles_x / PROBE_WANT_WORKGROUP_TILES);
775
- this.#want_groups[1] = Math.ceil(tiles_y / PROBE_WANT_WORKGROUP_TILES);
776
-
777
- this.#camera = camera;
966
+ this.#wants = wants;
967
+ this.#bounce_first = bounce_first;
968
+ this.#bounce_fallback = bounce_fallback;
778
969
 
779
970
  const data = this.#lifetime_data;
780
- const pass = graph.add("Probe Clipmap Lifetime", data, this.#execute_lifetime);
971
+ const pass = graph.add(`${this.label} Lifetime`, data, this.#execute_lifetime);
781
972
 
782
- data.counters = pass.write(graph_import_buffer(graph, this.#counters, "probe_counters"));
783
- data.depth = pass.read(depth);
784
- data.normal = pass.read(normal);
973
+ data.counters = pass.write(graph_import_buffer(graph, this.#counters, `${this.label} counters`));
785
974
  data.stbn = stbn;
786
975
 
787
- pass.make_side_effect();
788
-
789
- // the local lights the rays' hits take, clustered over the bricks' cascades, where every hit is (§8.7)
790
- const coarsest_cell = brick_clipmap.cell_size(coarsest);
791
-
792
- for (let axis = 0; axis < 3; axis++) {
793
- const corner = brick_clipmap.corner(coarsest, axis);
794
-
795
- this.#clusters_min[axis] = corner * coarsest_cell;
796
- this.#clusters_max[axis] = (corner + brick_clipmap.resolution) * coarsest_cell;
797
- }
976
+ wants.graph_declare(pass, data);
798
977
 
799
- const clusters = graph_build_world_light_clusters({
800
- graph,
801
- lights: scene.lights,
802
- levels: graph_import_buffer(graph, brick_clipmap.levels, "probe_brick_levels"),
803
- cascade_count: brick_clipmap.cascade_count,
804
- border: 0,
805
- coarsest_min: this.#clusters_min,
806
- coarsest_max: this.#clusters_max,
807
- });
978
+ pass.make_side_effect();
808
979
 
809
980
  // the frame's updates, once its bricks are built
810
981
  const update_data = this.#update_data;
811
- const update = graph.add("Probe Clipmap Update", update_data, this.#execute_update);
982
+ const update = graph.add(`${this.label} Update`, update_data, this.#execute_update);
812
983
 
813
984
  update_data.counters = update.write(data.counters);
814
985
  update_data.bricks = update.read(bricks);
@@ -839,29 +1010,10 @@ export class GPUProbeClipmap {
839
1010
  }
840
1011
 
841
1012
  /**
842
- * Place every window, coarsest first, and write the cage windows the readers take.
1013
+ * @returns {number} texels of skirt on each side of a radiance tile's map
843
1014
  */
844
- #place(x, y, z) {
845
- const placement = this.#placement;
846
- const n = this.resolution;
847
-
848
- placement.begin();
849
-
850
- for (let c = this.cascade_count - 1; c >= 0; c--) {
851
- placement.place(c, x, y, z);
852
- }
853
-
854
- for (let c = 0; c < this.cascade_count; c++) {
855
- const level = (c * CLIPMAP_LEVEL_STRUCT.aligned_size) >>> 2;
856
-
857
- for (let axis = 0; axis < 3; axis++) {
858
- this.#levels_i32[level + axis] = placement.corner(c, axis);
859
- // the cages: a cell between two lattice points
860
- this.#levels_i32[level + 4 + axis] = n - 1;
861
- }
862
-
863
- this.#levels_f32[level + 3] = placement.cell_size(c);
864
- }
1015
+ #radiance_skirt_texels() {
1016
+ return this.radiance_skirt ? 1 : 0;
865
1017
  }
866
1018
 
867
1019
  /**
@@ -884,6 +1036,7 @@ export class GPUProbeClipmap {
884
1036
  this.#requests = this.#regrow(this.#requests, 'probe requests', PROBE_REQUEST_STRUCT.size * capacity);
885
1037
  this.#records = this.#regrow(this.#records, 'probe records', PROBE_RECORD_STRUCT.size * capacity);
886
1038
  this.#free = this.#regrow(this.#free, 'probe free list', 4 * capacity);
1039
+ this.#listed = this.#regrow(this.#listed, 'probe listed', 4 * capacity);
887
1040
  this.#active[0] = this.#regrow(this.#active[0], 'probe active 0', LIST_HEADER_BYTES + 4 * capacity);
888
1041
  this.#active[1] = this.#regrow(this.#active[1], 'probe active 1', LIST_HEADER_BYTES + 4 * capacity);
889
1042
 
@@ -905,6 +1058,7 @@ export class GPUProbeClipmap {
905
1058
  this.#maps?.destroy();
906
1059
  this.#guide?.destroy();
907
1060
  this.#resamples?.destroy();
1061
+ this.#candidates?.destroy();
908
1062
  this.#projection?.destroy();
909
1063
  this.#ray_counts?.destroy();
910
1064
  this.#ray_requests?.destroy();
@@ -927,10 +1081,26 @@ export class GPUProbeClipmap {
927
1081
  this.#origins = this.#create_buffer('probe origins', 16 * trace_capacity, 0);
928
1082
  this.#maps = this.#create_buffer('probe maps', 4 * probe_clipmap_maps_words(this.radiance_resolution, this.depth_resolution) * trace_capacity, 0);
929
1083
  this.#guide = this.#create_buffer('probe guide', 4 * probe_clipmap_guide_words(this.radiance_resolution) * trace_capacity, 0);
930
- this.#resamples = this.#create_buffer('probe resamples', 16 * this.radiance_resolution * this.radiance_resolution * trace_capacity, 0);
1084
+ // cleared where the rays add to it without the history pass's stores
1085
+ this.#resamples = this.#create_buffer('probe resamples', 16 * this.radiance_resolution * this.radiance_resolution * trace_capacity, GPUBufferUsage.COPY_DST);
1086
+ this.#candidates = this.#create_buffer('probe candidates', PROBE_CANDIDATE_STRUCT.size * trace_capacity, 0);
931
1087
  this.#projection = this.#create_buffer('probe projection', PROBE_PROJECTION_ROW_STRUCT.size * this.radiance_resolution * trace_capacity, 0);
932
1088
  }
933
1089
 
1090
+ /**
1091
+ * A wanted list of at least `capacity` points: a frame's wants list each point once, at most every key, and
1092
+ * at most what the wants can want (`wanted_bound`), which follows the screen or the other clipmap's rays.
1093
+ */
1094
+ #ensure_wanted(capacity) {
1095
+ if (this.#wanted !== undefined && this.#wanted_capacity >= capacity) {
1096
+ return;
1097
+ }
1098
+
1099
+ this.#wanted?.destroy();
1100
+ this.#wanted_capacity = capacity;
1101
+ this.#wanted = this.#create_buffer('probe wanted', LIST_HEADER_BYTES + 4 * capacity, GPUBufferUsage.COPY_DST);
1102
+ }
1103
+
934
1104
  /**
935
1105
  * Room for `ray_count` rays, U·R, which the ray settings size, to the next whole workgroup: the last
936
1106
  * workgroup's threads past the frame's last ray write a record of no ray.
@@ -992,7 +1162,7 @@ export class GPUProbeClipmap {
992
1162
  this.#parity = 1 - this.#parity;
993
1163
 
994
1164
  // the frame's lists start empty, and no point is wanted yet; the trace list holds the last frame's
995
- // updates until the hits' wants have read their rays
1165
+ // updates until the wants have run, as another clipmap's hits' wants recorded before this lifetime read them
996
1166
  encoder.clearBuffer(active_write, 0, 4);
997
1167
  encoder.clearBuffer(this.#wanted, 0, 4);
998
1168
  encoder.clearBuffer(this.#wanted_bits);
@@ -1003,6 +1173,7 @@ export class GPUProbeClipmap {
1003
1173
  b.probe_records = this.#records;
1004
1174
  b.probe_counters = counters;
1005
1175
  b.probe_free = this.#free;
1176
+ b.probe_listed = this.#listed;
1006
1177
  b.probe_active_read = active_read;
1007
1178
  b.probe_active_write = active_write;
1008
1179
  b.probe_wanted = this.#wanted;
@@ -1020,31 +1191,17 @@ export class GPUProbeClipmap {
1020
1191
  command_offset: 4 * PROBE_DISPATCH_ACTIVE,
1021
1192
  });
1022
1193
 
1023
- b.gBufferDepth = resources.get(data.depth);
1024
- b.gBufferNormals = resources.get(data.normal);
1025
- b.camera = this.#camera;
1026
1194
  b.tSTBN_vec2 = data.stbn;
1027
- b.settings = this.#want_settings;
1028
1195
 
1029
- shader_probe_clipmap_want.dispatch({
1030
- encoder,
1031
- group_count_x: this.#want_groups[0],
1032
- group_count_y: this.#want_groups[1],
1033
- bindings: b,
1034
- });
1196
+ // the frame's wants, into the wanted bits and list
1197
+ const want = this.#want_bindings;
1035
1198
 
1036
- // the last frame's hits want the probes their bounce reads, through the launch their rays had,
1037
- // before the frame's trace command writes it over
1038
- b.probe_origins = this.#origins;
1039
- b.probe_rays = this.#rays;
1040
- b.settings = this.#want_hits_settings;
1199
+ want.probe_levels = this.#levels;
1200
+ want.probe_wanted = this.#wanted;
1201
+ want.probe_wanted_bits = this.#wanted_bits;
1202
+ want.settings = this.#want_settings;
1041
1203
 
1042
- shader_probe_clipmap_want_hits.dispatchIndirect({
1043
- encoder,
1044
- bindings: b,
1045
- command: this.#dispatch,
1046
- command_offset: 4 * PROBE_DISPATCH_RAYS,
1047
- });
1204
+ this.#wants.encode(encoder, data, resources, want);
1048
1205
 
1049
1206
  encoder.clearBuffer(this.#trace, 0, 4);
1050
1207
 
@@ -1158,6 +1315,7 @@ export class GPUProbeClipmap {
1158
1315
  b.probe_counters = resources.get(data.counters);
1159
1316
  b.probe_origins = this.#origins;
1160
1317
  b.probe_ray_sums = this.#ray_sums;
1318
+ b.probe_listed = this.#listed;
1161
1319
  b.settings = this.#relocate_settings;
1162
1320
 
1163
1321
  shader_probe_clipmap_relocate.dispatchIndirect({
@@ -1215,9 +1373,7 @@ export class GPUProbeClipmap {
1215
1373
  command_offset: 4 * PROBE_DISPATCH_RAYS,
1216
1374
  });
1217
1375
 
1218
- // the light each hit takes from beyond the trace: one of its cell's local lights through the bricks, and
1219
- // the next bounce from last frame's probes
1220
- this.write_sampling_bindings(b);
1376
+ // the light each hit takes from beyond the trace: one of its cell's local lights through the bricks
1221
1377
  b.world_cluster_lookup = resources.get(data.world_cluster_lookup);
1222
1378
  b.world_cluster_data = resources.get(data.world_cluster_data);
1223
1379
  b.settings = this.#trace_settings;
@@ -1229,12 +1385,43 @@ export class GPUProbeClipmap {
1229
1385
  command_offset: 4 * PROBE_DISPATCH_RAYS,
1230
1386
  });
1231
1387
 
1388
+ // and the next bounce, from the first clipmap's probes, or the fallback's where the first has none, as
1389
+ // their clipmaps hold them now
1390
+ const sets = this.#set_bindings;
1391
+
1392
+ this.#bounce_first.write_sampling_bindings(sets);
1393
+ b.bounce_first_levels = sets.probe_levels;
1394
+ b.bounce_first_sampling = sets.probe_sampling;
1395
+ b.bounce_first_indirection = sets.probe_indirection;
1396
+ b.bounce_first_states = sets.probe_states;
1397
+ b.bounce_first_records = sets.probe_records;
1398
+ b.bounce_first_depth = sets.probe_depth;
1399
+
1400
+ this.#bounce_fallback.write_sampling_bindings(sets);
1401
+ b.bounce_fallback_levels = sets.probe_levels;
1402
+ b.bounce_fallback_sampling = sets.probe_sampling;
1403
+ b.bounce_fallback_indirection = sets.probe_indirection;
1404
+ b.bounce_fallback_states = sets.probe_states;
1405
+ b.bounce_fallback_records = sets.probe_records;
1406
+ b.bounce_fallback_depth = sets.probe_depth;
1407
+
1408
+ b.probe_states = this.#states;
1409
+ b.probe_ray_sums = this.#ray_sums;
1410
+
1411
+ shader_probe_clipmap_bounce.dispatchIndirect({
1412
+ encoder,
1413
+ bindings: b,
1414
+ command: this.#dispatch,
1415
+ command_offset: 4 * PROBE_DISPATCH_RAYS,
1416
+ });
1417
+
1232
1418
  // what each listed probe's neighbours have already seen, from the atlases and estimators as they were,
1233
1419
  // where the frame re-samples; accumulate's variant without it reads none
1420
+ this.write_sampling_bindings(b);
1234
1421
  b.probe_resamples = this.#resamples;
1235
1422
  b.probe_estimators = this.#estimators;
1236
1423
 
1237
- if (this.#resampling) {
1424
+ if (this.#history_resampling) {
1238
1425
  b.settings = this.#resample_settings;
1239
1426
 
1240
1427
  shader_probe_clipmap_resample.dispatchIndirect({
@@ -1243,6 +1430,33 @@ export class GPUProbeClipmap {
1243
1430
  command: this.#dispatch,
1244
1431
  command_offset: 4 * PROBE_DISPATCH_TEXELS,
1245
1432
  });
1433
+ } else if (this.#ray_resampling) {
1434
+ // the rays add to the re-samples, here to nothing
1435
+ encoder.clearBuffer(this.#resamples);
1436
+ }
1437
+
1438
+ // every ray one neighbour of each listed probe traced this frame, drawn by its radiance and the probe's sight
1439
+ // of it, added in the texels the probe sees their hits in
1440
+ if (this.#ray_resampling) {
1441
+ b.probe_listed = this.#listed;
1442
+ b.probe_candidates = this.#candidates;
1443
+ b.settings = this.#candidate_settings;
1444
+
1445
+ shader_probe_clipmap_candidate.dispatchIndirect({
1446
+ encoder,
1447
+ bindings: b,
1448
+ command: this.#dispatch,
1449
+ command_offset: 4 * PROBE_DISPATCH_TRACED,
1450
+ });
1451
+
1452
+ b.settings = this.#resample_rays_settings;
1453
+
1454
+ shader_probe_clipmap_resample_rays.dispatchIndirect({
1455
+ encoder,
1456
+ bindings: b,
1457
+ command: this.#dispatch,
1458
+ command_offset: 4 * PROBE_DISPATCH_TEXELS,
1459
+ });
1246
1460
  }
1247
1461
 
1248
1462
  // the probes' maps from their rays, against the atlases as they were; their SH and kind from the
@@ -1294,8 +1508,11 @@ export class GPUProbeClipmap {
1294
1508
  * @returns {GPUBuffer}
1295
1509
  */
1296
1510
  #create_buffer(name, size, usage) {
1511
+ // bound whole, as storage
1512
+ assert.lessThanOrEqual(size, this.#device.limits.maxStorageBufferBindingSize, `${name} past maxStorageBufferBindingSize`);
1513
+
1297
1514
  return this.#device.createBuffer(BufferDescriptor.fromJSON({
1298
- label: `Probe clipmap / ${name}`,
1515
+ label: `${this.label} / ${name}`,
1299
1516
  size,
1300
1517
  usage: GPUBufferUsage.STORAGE | usage,
1301
1518
  }));
@@ -1314,7 +1531,7 @@ export class GPUProbeClipmap {
1314
1531
  const device = this.#device;
1315
1532
  const buffer = this.#create_buffer(name, size, GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST);
1316
1533
 
1317
- const encoder = device.createCommandEncoder({ label: `Probe clipmap / ${name} growth` });
1534
+ const encoder = device.createCommandEncoder({ label: `${this.label} / ${name} growth` });
1318
1535
 
1319
1536
  encoder.copyBufferToBuffer(old, 0, buffer, 0, old.size);
1320
1537
  device.queue.submit([encoder.finish()]);
@@ -1335,7 +1552,7 @@ export class GPUProbeClipmap {
1335
1552
  this.#radiance.destroy();
1336
1553
  this.#depth.destroy();
1337
1554
 
1338
- for (const buffer of [this.#levels, this.#states, this.#estimators, this.#records, this.#free, this.#counters, this.#dispatch, this.#eviction, ...this.#active, this.#wanted, this.#wanted_bits, this.#trace, this.#origins, this.#maps, this.#guide, this.#resamples, this.#projection, this.#requests, this.#ray_counts, this.#ray_requests, this.#ray_count_sums, this.#ray_request_sums, this.#ray_sums, this.#ray_scan_spine, this.#ray_scan_command, this.#rays, this.#sampling]) {
1555
+ for (const buffer of [this.#levels, this.#states, this.#estimators, this.#records, this.#free, this.#listed, this.#candidates, this.#counters, this.#dispatch, this.#eviction, ...this.#active, this.#wanted, this.#wanted_bits, this.#trace, this.#origins, this.#maps, this.#guide, this.#resamples, this.#projection, this.#requests, this.#ray_counts, this.#ray_requests, this.#ray_count_sums, this.#ray_request_sums, this.#ray_sums, this.#ray_scan_spine, this.#ray_scan_command, this.#rays, this.#sampling]) {
1339
1556
  buffer?.destroy();
1340
1557
  }
1341
1558
  }