@woosh/meep-engine 3.59.0 → 3.60.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 (326) hide show
  1. package/package.json +1 -1
  2. package/src/shade/playground/probe_clipmap/index.html +12 -0
  3. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  4. package/src/shade/playground/probe_clipmap/main.js +5 -0
  5. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  6. package/src/shade/renderer/Renderer.js +4 -6
  7. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +63 -1
  8. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  9. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +228 -16
  10. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +27 -4
  11. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  12. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +526 -23
  13. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts +11 -0
  14. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.d.ts.map +1 -0
  15. package/src/shade/renderer/geometry/sdf/cards/MeshCardCaptureMode.js +21 -0
  16. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts +65 -0
  17. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.d.ts.map +1 -0
  18. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +376 -0
  19. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts +7 -3
  20. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.d.ts.map +1 -1
  21. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_capture.js +70 -6
  22. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts +20 -0
  23. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.d.ts.map +1 -0
  24. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_args.js +80 -0
  25. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts +18 -0
  26. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.d.ts.map +1 -0
  27. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_raster_scatter.js +113 -0
  28. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +47 -0
  29. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +1 -0
  30. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +80 -0
  31. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +91 -0
  32. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -0
  33. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +902 -0
  34. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +16 -0
  35. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +1 -0
  36. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +67 -0
  37. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +17 -0
  38. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +1 -0
  39. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +145 -0
  40. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +12 -0
  41. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +1 -0
  42. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +105 -0
  43. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.d.ts.map +1 -1
  44. package/src/shade/renderer/global_illumination/probe/octahedral/shader_lpv_build_gbuffer.js +2 -1
  45. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +3 -9
  46. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  47. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +13 -31
  48. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +764 -48
  49. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +410 -0
  50. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +3 -2
  51. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  52. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +4 -3
  53. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +41 -17
  54. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  55. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +57 -33
  56. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts +11 -3
  57. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts.map +1 -1
  58. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.js +13 -4
  59. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +9 -18
  60. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  61. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +8 -10
  62. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts +12 -0
  63. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.d.ts.map +1 -1
  64. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap.js +28 -0
  65. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +1 -29
  66. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  67. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +1 -74
  68. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts +161 -0
  69. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.d.ts.map +1 -0
  70. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK.js +219 -0
  71. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts +1 -8
  72. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts.map +1 -1
  73. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.js +1 -9
  74. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts +40 -12
  75. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.d.ts.map +1 -1
  76. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MeshSDFBrickProvider.js +373 -31
  77. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -1
  78. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts.map +1 -1
  79. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -1
  80. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts +15 -8
  81. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.d.ts.map +1 -1
  82. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_texel.js +28 -14
  83. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts +23 -0
  84. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.d.ts.map +1 -0
  85. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_walk.js +66 -0
  86. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts +29 -0
  87. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.d.ts.map +1 -0
  88. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_batch.js +210 -0
  89. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts +29 -0
  90. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.d.ts.map +1 -0
  91. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_command.js +86 -0
  92. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts +41 -0
  93. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.d.ts.map +1 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_gather.js +439 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts +23 -0
  96. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.d.ts.map +1 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_resolve.js +135 -0
  98. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts +3 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.d.ts.map +1 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/shader_brick_clipmap_free.js +12 -3
  101. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +21 -18
  102. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  103. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +254 -73
  104. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +149 -8
  105. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  106. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +181 -13
  107. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +179 -7
  108. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +412 -31
  110. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +4 -4
  111. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +4 -3
  113. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +36 -10
  114. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  115. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +218 -29
  116. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +5 -1
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +24 -14
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +15 -6
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +21 -22
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts +36 -0
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.d.ts.map +1 -0
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_guide.js +257 -0
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +18 -7
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +157 -51
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts +23 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_order.js +110 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +24 -2
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +90 -10
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts +45 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.d.ts.map +1 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_ray_layout.js +205 -0
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts +16 -3
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +55 -10
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +19 -4
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +60 -6
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts +4 -8
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +21 -36
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +21 -14
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +100 -30
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts +6 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace_command.js +26 -10
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +3 -2
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +12 -12
  156. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts +10 -0
  157. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.d.ts.map +1 -0
  158. package/src/shade/renderer/gpu_primitive/sort/SORT_DIGIT_SETTINGS_STRUCT.js +21 -0
  159. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts +5 -2
  160. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.d.ts.map +1 -1
  161. package/src/shade/renderer/gpu_primitive/sort/SORT_PASS_SETTINGS_STRUCT.js +31 -23
  162. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts +10 -0
  163. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.d.ts.map +1 -0
  164. package/src/shade/renderer/gpu_primitive/sort/SORT_SIZE_STRUCT.js +22 -0
  165. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts +9 -0
  166. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.d.ts.map +1 -0
  167. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_constants.js +18 -0
  168. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts +8 -3
  169. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.d.ts.map +1 -1
  170. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_digit.js +41 -32
  171. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts +31 -0
  172. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.d.ts.map +1 -0
  173. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_histogram_tile.js +71 -0
  174. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts +47 -0
  175. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.d.ts.map +1 -0
  176. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_scatter_tile.js +210 -0
  177. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +5 -4
  178. package/src/shade/renderer/gpu_primitive/sort/defs.d.ts.map +1 -1
  179. package/src/shade/renderer/gpu_primitive/sort/defs.js +5 -4
  180. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +56 -15
  181. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  182. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +410 -61
  183. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts +4 -1
  184. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.d.ts.map +1 -1
  185. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram.js +16 -42
  186. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts +15 -0
  187. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.d.ts.map +1 -0
  188. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_histogram_indirect.js +60 -0
  189. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts +25 -0
  190. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.d.ts.map +1 -0
  191. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_prepare.js +89 -0
  192. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts +3 -8
  193. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.d.ts.map +1 -1
  194. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter.js +28 -160
  195. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts +12 -0
  196. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.d.ts.map +1 -0
  197. package/src/shade/renderer/gpu_primitive/sort/shader_radix_sort_scatter_indirect.js +74 -0
  198. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts +3 -1
  199. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.d.ts.map +1 -1
  200. package/src/shade/renderer/gpu_primitive/sort/verify_radix_sort.js +387 -188
  201. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +1 -1
  202. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +1 -1
  203. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  204. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +90 -72
  205. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts +5 -0
  206. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.d.ts.map +1 -1
  207. package/src/shade/renderer/material/resident/RESIDENT_MATERIAL_TEXTURE_LAYOUT.js +9 -0
  208. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts +13 -0
  209. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.d.ts.map +1 -0
  210. package/src/shade/renderer/path_tracer/shader/INDIRECT_TEXTURE_FILTER.js +14 -0
  211. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts +10 -0
  212. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.d.ts.map +1 -0
  213. package/src/shade/renderer/path_tracer/shader/IndirectTextureFilter.js +15 -0
  214. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts +4 -3
  215. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.d.ts.map +1 -1
  216. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_tangent_normal.js +6 -5
  217. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts +17 -2
  218. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.d.ts.map +1 -1
  219. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture.js +25 -57
  220. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts +13 -0
  221. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.d.ts.map +1 -0
  222. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_exact.js +70 -0
  223. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts +10 -0
  224. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.d.ts.map +1 -0
  225. package/src/shade/renderer/path_tracer/shader/chunk_indirect_sample_texture_stochastic.js +59 -0
  226. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts +12 -0
  227. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.d.ts.map +1 -0
  228. package/src/shade/renderer/path_tracer/shader/chunk_indirect_texture_load.js +49 -0
  229. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.d.ts.map +1 -1
  230. package/src/shade/renderer/path_tracer/shader/chunk_ray_hit_to_opacity.js +1 -0
  231. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.d.ts.map +1 -1
  232. package/src/shade/renderer/path_tracer/shader/chunk_render_trace_path.js +1 -0
  233. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.d.ts.map +1 -1
  234. package/src/shade/renderer/path_tracer/shader/chunk_sample_material.js +2 -1
  235. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts +7 -0
  236. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  237. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +15 -6
  238. package/src/shade/renderer/scene/GPUSceneContext.d.ts +7 -1
  239. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  240. package/src/shade/renderer/scene/GPUSceneContext.js +26 -1
  241. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts +7 -7
  242. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.d.ts.map +1 -1
  243. package/src/shade/renderer/shader/chunk/bvh/chunk_bvh_query_aabb_cooperative.js +262 -294
  244. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts +9 -0
  245. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.d.ts.map +1 -0
  246. package/src/shade/renderer/shader/chunk/filter/MULTISCALE_MEAN_STRUCT.js +21 -0
  247. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +43 -0
  248. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -0
  249. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +87 -0
  250. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts +7 -1
  251. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.d.ts.map +1 -1
  252. package/src/shade/renderer/shader/chunk/noise/r/chunk_r2_canonical.js +1 -1
  253. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts +21 -0
  254. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.d.ts.map +1 -0
  255. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_reserve_workgroup.js +42 -0
  256. package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
  257. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +19 -0
  258. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
  259. package/src/shade/wgsl/emulator/CPUBitmapData.js +27 -0
  260. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  261. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +39 -18
  262. package/src/view/elements/progress/segmented/GhostTrail.d.ts +56 -0
  263. package/src/view/elements/progress/segmented/GhostTrail.d.ts.map +1 -0
  264. package/src/view/elements/progress/segmented/GhostTrail.js +98 -0
  265. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts +3 -1
  266. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.d.ts.map +1 -1
  267. package/src/view/elements/progress/segmented/RESOURCE_BAR_SEGMENTS.js +3 -1
  268. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts +11 -0
  269. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.d.ts.map +1 -0
  270. package/src/view/elements/progress/segmented/SEGMENT_TIERS_DEFAULT.js +15 -0
  271. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts +3 -0
  272. package/src/view/elements/progress/segmented/SegmentDefinition.d.ts.map +1 -1
  273. package/src/view/elements/progress/segmented/SegmentDefinition.js +3 -0
  274. package/src/view/elements/progress/segmented/SegmentTier.d.ts +38 -0
  275. package/src/view/elements/progress/segmented/SegmentTier.d.ts.map +1 -0
  276. package/src/view/elements/progress/segmented/SegmentTier.js +50 -0
  277. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +155 -10
  278. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
  279. package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +427 -101
  280. package/src/view/elements/progress/segmented/playground/index.html +78 -0
  281. package/src/view/elements/progress/segmented/playground/main.d.ts +2 -0
  282. package/src/view/elements/progress/segmented/playground/main.d.ts.map +1 -0
  283. package/src/view/elements/progress/segmented/playground/main.js +173 -0
  284. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts +48 -0
  285. package/src/view/elements/progress/segmented/segment_cell_layout.d.ts.map +1 -0
  286. package/src/view/elements/progress/segmented/segment_cell_layout.js +75 -0
  287. package/src/view/elements/progress/segmented/segment_notch_place.d.ts +18 -0
  288. package/src/view/elements/progress/segmented/segment_notch_place.d.ts.map +1 -0
  289. package/src/view/elements/progress/segmented/segment_notch_place.js +28 -0
  290. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts +32 -0
  291. package/src/view/elements/progress/segmented/segment_tick_positions.d.ts.map +1 -0
  292. package/src/view/elements/progress/segmented/segment_tick_positions.js +103 -0
  293. package/src/view/elements/progress/segmented/segmented-resource-bar.css +142 -0
  294. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts +0 -35
  295. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts.map +0 -1
  296. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.js +0 -238
  297. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts +0 -99
  298. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts.map +0 -1
  299. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.js +0 -139
  300. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts +0 -65
  301. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts.map +0 -1
  302. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.js +0 -393
  303. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts +0 -17
  304. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts.map +0 -1
  305. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.js +0 -36
  306. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts +0 -29
  307. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts.map +0 -1
  308. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.js +0 -108
  309. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts +0 -31
  310. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts.map +0 -1
  311. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.js +0 -113
  312. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts +0 -36
  313. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts.map +0 -1
  314. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.js +0 -85
  315. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts +0 -23
  316. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts.map +0 -1
  317. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.js +0 -273
  318. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts +0 -13
  319. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts.map +0 -1
  320. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.js +0 -151
  321. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts +0 -13
  322. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts.map +0 -1
  323. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.js +0 -133
  324. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts +0 -22
  325. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts.map +0 -1
  326. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.js +0 -135
@@ -8,17 +8,43 @@ export const PROBE_ACCUMULATE_SETTINGS: WebGPUStruct;
8
8
  * gathers its own rays and writes the texel, blended with its history, to the probe's maps in
9
9
  * `probe_maps` (`probe_clipmap_maps_words`): two words a radiance texel, rgba as half floats; then a
10
10
  * word a radiance texel, its rays this update, resolved in the low half and back faces in the high,
11
- * which classification sums; then a word a depth texel, its moments as half floats.
11
+ * which classification sums; then a word a depth texel, its moments as half floats; then a word a
12
+ * radiance texel, how far its sample fell from its mean in its own deviation, luminance, held to
13
+ * `PROBE_CHANGE_SIGNIFICANCE`, and one for its blending one, as half floats, which the probe's ray request
14
+ * sums (zero where no sample was blended).
12
15
  *
13
- * - **Radiance**: the mean of the texel's resolved rays, a back face's being zero, blended by
14
- * α = max(1/(a+1), 1 − e^(−Δt·p/τ)). a is the texel's own count of the updates that reached it, held
15
- * in its alpha; p the updates between a texel's rays, n_r²/R below one ray a texel. Counting a texel
16
- * rather than the probe keeps α right where an update covers a subset: a texel's first ray is taken
17
- * whole whenever it comes. A texel no ray reached keeps its history.
18
- * - **Depth**: the moments (d, d²) of the rays landing in the texel, in spacings: a miss √3, a back
19
- * face 0.2·t (DDGI 2021's shortening), a hit t, every sample held to √3 (D9). Blended by the probe's
20
- * α = max(1/(n+1), 1 − e^(−Δt/τ)), n its updates. At most 64 rays a texel, which the settings hold
21
- * R to (R ≤ 64·n_d²).
16
+ * - **A texel's rays**: on a uniform update (`PROBE_UNIFORM_PERIOD`), `probe_clipmap_texel_ray`'s. On a
17
+ * guided one, the run that begins at its walk position in the probe's guide, at most
18
+ * `PROBE_TEXEL_RAYS` of them. A guided texel's rays are spread evenly over it however many it takes,
19
+ * so their mean needs no weight for the guide's choice.
20
+ * - **Radiance**: the mean of the texel's resolved rays, a back face's being zero, is a sample of the
21
+ * texel's multi-scale mean (`chunk_multiscale_mean`), its estimator in `probe_estimators` and its mean
22
+ * in the atlas.
23
+ * - Δt and τ are frames: Δt since the probe's last update, τ `response_frames`.
24
+ * - The short mean blends by β = max(1/(a+1), 1 − e^(−Δt·p/τ)), its variance by the same with 2τ. a is
25
+ * the texel's own count of the updates that reached it, held in its alpha; p the updates between a
26
+ * texel's rays: one over the share of updates that reach it, averaged over the uniform period
27
+ * (`probe_clipmap_guide_rate`), n_r²/R below one ray a texel when every update is uniform. A texel
28
+ * the guide passes over thus blends what it takes as fully as its rarity asks. Counting a texel
29
+ * rather than the probe keeps β right where an update covers a subset.
30
+ * - The mean blends by at least 1/(a+1) until the count reaches its limit: a young texel is its running
31
+ * mean, which the estimator's blend reduction, nothing at its seed, would otherwise hold back. Past it
32
+ * the estimator alone, down to 1/8192 an update on a noisy texel.
33
+ * - Samples are clipped once the variance's window has passed, when 1/(a+1) is no longer its blend:
34
+ * before that it holds no spread to clip to.
35
+ * - A texel's first sample seeds both means. A texel no ray reached keeps its history.
36
+ * - **Depth**: the moments (d, d²) of the rays landing in the texel, in spacings: a miss the limit, a
37
+ * back face 0.2·t (DDGI 2021's shortening), a hit t, every sample held to the limit, the farthest a
38
+ * cage tests a relocated probe, (1 + 0.45)·√3 (`PROBE_DEPTH_LIMIT`, D9). On a uniform update the
39
+ * sample is the plain mean, blended by the probe's α = max(1/(n+1), 1 − e^(−Δt/τ)), n its updates. At
40
+ * most 64 rays a texel, which the settings hold R to (R ≤ 64·n_d²).
41
+ * - On a guided update the sample is a mean of means: each radiance texel inside the depth texel gives
42
+ * its own mean, since the guide gives the brighter ones more rays, at most 64/f² of its rays,
43
+ * evenly strided. It is taken only when every one of them took rays. The guide gives a dark one,
44
+ * a back face's or a shadowed wall's, none, and the lit ones' depths are not the whole texel's: its
45
+ * depth comes from the uniform updates.
46
+ * - The time term's period is one over the share of updates that reach the depth texel, a uniform
47
+ * update counting as reaching every one, a guided one as often as its least reached radiance texel.
22
48
  * - **A new probe's history is another probe's**, its slot's last owner: on its first update a texel
23
49
  * no ray reached is cleared, radiance to nothing seen, depth to the moments of a miss.
24
50
  * - **Stored rounded stochastically** onto halves (`f16_round_stochastic`), with noise fresh for each
@@ -1 +1 @@
1
- {"version":3,"file":"shader_probe_clipmap_accumulate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js"],"names":[],"mappings":"AA+BA;;GAEG;AACH,wCAFU,YAAY,CAmBQ;AAgB9B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,8CAFU,aAAa,CAgMpB;6BAlR0B,sCAAsC;8BAHrC,kCAAkC"}
1
+ {"version":3,"file":"shader_probe_clipmap_accumulate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js"],"names":[],"mappings":"AA0CA;;GAEG;AACH,wCAFU,YAAY,CAqBQ;AAmB9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,8CAFU,aAAa,CAmVpB;6BA3c0B,sCAAsC;8BAHrC,kCAAkC"}
@@ -1,6 +1,10 @@
1
+ import { chunk_multiscale_mean } from "../../../shader/chunk/filter/chunk_multiscale_mean.js";
2
+ import { MULTISCALE_MEAN_STRUCT } from "../../../shader/chunk/filter/MULTISCALE_MEAN_STRUCT.js";
1
3
  import { chunk_folded_workgroup_index } from "../../../shader/chunk/grid/chunk_folded_workgroup_index.js";
2
4
  import { chunk_index_to_grid2d } from "../../../shader/chunk/grid/chunk_index_to_grid2d.js";
3
5
  import { chunk_f16_round_stochastic } from "../../../shader/chunk/math/chunk_f16_round_stochastic.js";
6
+ import { chunk_rgbe9995_decode } from "../../../shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.js";
7
+ import { F16_MAX_DEFINITION } from "../../../shader/chunk/math/F16_MAX_DEFINITION.js";
4
8
  import { chunk_hash_to_float01 } from "../../../shader/chunk/random/chunk_hash_to_float01.js";
5
9
  import { chunk_pcg3d } from "../../../shader/chunk/random/pcg/chunk_pcg3d.js";
6
10
  import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
@@ -11,12 +15,17 @@ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
11
15
  import { BRICK_TRACE_MISS, BRICK_TRACE_UNRESOLVED } from "../brick/BRICK_CLIPMAP.js";
12
16
  import {
13
17
  chunk_probe_clipmap,
18
+ chunk_probe_clipmap_guide,
19
+ chunk_probe_clipmap_ray_layout,
14
20
  chunk_probe_clipmap_ray_texel,
15
21
  PROBE_DEPTH_HISTORY_RESOURCE,
22
+ PROBE_ESTIMATORS_RESOURCE,
23
+ PROBE_GUIDE_READ_RESOURCE,
16
24
  PROBE_MAPS_WRITE_RESOURCE,
17
25
  PROBE_ORIGINS_READ_RESOURCE,
18
26
  PROBE_RADIANCE_HISTORY_RESOURCE,
19
27
  PROBE_RAY_STRUCT,
28
+ PROBE_RAY_SUMS_READ_RESOURCE,
20
29
  PROBE_RAYS_READ_RESOURCE,
21
30
  PROBE_RECORDS_READ_RESOURCE,
22
31
  PROBE_STATES_READ_RESOURCE,
@@ -24,7 +33,9 @@ import {
24
33
  } from "./chunk_probe_clipmap.js";
25
34
  import {
26
35
  PROBE_BACK_FACE_DEPTH,
36
+ PROBE_CHANGE_SIGNIFICANCE,
27
37
  PROBE_DEPTH_LIMIT,
38
+ PROBE_DEPTH_TEXEL_RAYS,
28
39
  PROBE_RADIANCE_SAMPLES_LIMIT,
29
40
  PROBE_THREAD_WORKGROUP_SIZE
30
41
  } from "./PROBE_CLIPMAP.js";
@@ -35,7 +46,7 @@ import {
35
46
  export const PROBE_ACCUMULATE_SETTINGS = WebGPUStruct.from({
36
47
  /** probes a frame updates at most: the trace list's bound */
37
48
  trace_capacity: u32,
38
- /** rays an update casts, R */
49
+ /** rays a uniform update casts, R; a guided update casts its probe's own (`probe_ray_sums`) */
39
50
  rays_per_probe: u32,
40
51
  /** octahedral radiance texels a side, n_r */
41
52
  radiance_resolution: u32,
@@ -45,10 +56,12 @@ export const PROBE_ACCUMULATE_SETTINGS = WebGPUStruct.from({
45
56
  radiance_tiles_per_row: u32,
46
57
  /** tiles a row of the depth atlas */
47
58
  depth_tiles_per_row: u32,
48
- /** the frame's time on the records' clock, seconds */
49
- time: f32,
50
- /** the blend's response time, τ, seconds */
51
- response_time: f32,
59
+ /** the frame, of the frames the clipmap has recorded */
60
+ frame: u32,
61
+ /** the short mean's response, τ, in frames; the depth's blend's */
62
+ response_frames: f32,
63
+ /** updates between a probe's uniform ones, `PROBE_UNIFORM_PERIOD` */
64
+ uniform_period: u32,
52
65
  }, "ProbeAccumulateSettings");
53
66
 
54
67
  const resources = new ShaderResourceSetDescriptor();
@@ -59,11 +72,14 @@ resources.createGroup()
59
72
  .add(PROBE_TRACE_READ_RESOURCE)
60
73
  .add(PROBE_ORIGINS_READ_RESOURCE)
61
74
  .add(PROBE_RAYS_READ_RESOURCE)
75
+ .add(PROBE_RAY_SUMS_READ_RESOURCE)
62
76
  .add(PROBE_STATES_READ_RESOURCE)
63
77
  .add(PROBE_RECORDS_READ_RESOURCE)
78
+ .add(PROBE_GUIDE_READ_RESOURCE)
64
79
  .add(PROBE_MAPS_WRITE_RESOURCE)
65
80
  .add(PROBE_RADIANCE_HISTORY_RESOURCE)
66
- .add(PROBE_DEPTH_HISTORY_RESOURCE);
81
+ .add(PROBE_DEPTH_HISTORY_RESOURCE)
82
+ .add(PROBE_ESTIMATORS_RESOURCE);
67
83
 
68
84
  /**
69
85
  * Accumulate (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.8): a thread a texel of each listed probe's maps,
@@ -71,17 +87,43 @@ resources.createGroup()
71
87
  * gathers its own rays and writes the texel, blended with its history, to the probe's maps in
72
88
  * `probe_maps` (`probe_clipmap_maps_words`): two words a radiance texel, rgba as half floats; then a
73
89
  * word a radiance texel, its rays this update, resolved in the low half and back faces in the high,
74
- * which classification sums; then a word a depth texel, its moments as half floats.
90
+ * which classification sums; then a word a depth texel, its moments as half floats; then a word a
91
+ * radiance texel, how far its sample fell from its mean in its own deviation, luminance, held to
92
+ * `PROBE_CHANGE_SIGNIFICANCE`, and one for its blending one, as half floats, which the probe's ray request
93
+ * sums (zero where no sample was blended).
75
94
  *
76
- * - **Radiance**: the mean of the texel's resolved rays, a back face's being zero, blended by
77
- * α = max(1/(a+1), 1 − e^(−Δt·p/τ)). a is the texel's own count of the updates that reached it, held
78
- * in its alpha; p the updates between a texel's rays, n_r²/R below one ray a texel. Counting a texel
79
- * rather than the probe keeps α right where an update covers a subset: a texel's first ray is taken
80
- * whole whenever it comes. A texel no ray reached keeps its history.
81
- * - **Depth**: the moments (d, d²) of the rays landing in the texel, in spacings: a miss √3, a back
82
- * face 0.2·t (DDGI 2021's shortening), a hit t, every sample held to √3 (D9). Blended by the probe's
83
- * α = max(1/(n+1), 1 − e^(−Δt/τ)), n its updates. At most 64 rays a texel, which the settings hold
84
- * R to (R ≤ 64·n_d²).
95
+ * - **A texel's rays**: on a uniform update (`PROBE_UNIFORM_PERIOD`), `probe_clipmap_texel_ray`'s. On a
96
+ * guided one, the run that begins at its walk position in the probe's guide, at most
97
+ * `PROBE_TEXEL_RAYS` of them. A guided texel's rays are spread evenly over it however many it takes,
98
+ * so their mean needs no weight for the guide's choice.
99
+ * - **Radiance**: the mean of the texel's resolved rays, a back face's being zero, is a sample of the
100
+ * texel's multi-scale mean (`chunk_multiscale_mean`), its estimator in `probe_estimators` and its mean
101
+ * in the atlas.
102
+ * - Δt and τ are frames: Δt since the probe's last update, τ `response_frames`.
103
+ * - The short mean blends by β = max(1/(a+1), 1 − e^(−Δt·p/τ)), its variance by the same with 2τ. a is
104
+ * the texel's own count of the updates that reached it, held in its alpha; p the updates between a
105
+ * texel's rays: one over the share of updates that reach it, averaged over the uniform period
106
+ * (`probe_clipmap_guide_rate`), n_r²/R below one ray a texel when every update is uniform. A texel
107
+ * the guide passes over thus blends what it takes as fully as its rarity asks. Counting a texel
108
+ * rather than the probe keeps β right where an update covers a subset.
109
+ * - The mean blends by at least 1/(a+1) until the count reaches its limit: a young texel is its running
110
+ * mean, which the estimator's blend reduction, nothing at its seed, would otherwise hold back. Past it
111
+ * the estimator alone, down to 1/8192 an update on a noisy texel.
112
+ * - Samples are clipped once the variance's window has passed, when 1/(a+1) is no longer its blend:
113
+ * before that it holds no spread to clip to.
114
+ * - A texel's first sample seeds both means. A texel no ray reached keeps its history.
115
+ * - **Depth**: the moments (d, d²) of the rays landing in the texel, in spacings: a miss the limit, a
116
+ * back face 0.2·t (DDGI 2021's shortening), a hit t, every sample held to the limit, the farthest a
117
+ * cage tests a relocated probe, (1 + 0.45)·√3 (`PROBE_DEPTH_LIMIT`, D9). On a uniform update the
118
+ * sample is the plain mean, blended by the probe's α = max(1/(n+1), 1 − e^(−Δt/τ)), n its updates. At
119
+ * most 64 rays a texel, which the settings hold R to (R ≤ 64·n_d²).
120
+ * - On a guided update the sample is a mean of means: each radiance texel inside the depth texel gives
121
+ * its own mean, since the guide gives the brighter ones more rays, at most 64/f² of its rays,
122
+ * evenly strided. It is taken only when every one of them took rays. The guide gives a dark one,
123
+ * a back face's or a shadowed wall's, none, and the lit ones' depths are not the whole texel's: its
124
+ * depth comes from the uniform updates.
125
+ * - The time term's period is one over the share of updates that reach the depth texel, a uniform
126
+ * update counting as reaching every one, a guided one as often as its least reached radiance texel.
85
127
  * - **A new probe's history is another probe's**, its slot's last owner: on its first update a texel
86
128
  * no ray reached is cleared, radiance to nothing seen, depth to the moments of a miss.
87
129
  * - **Stored rounded stochastically** onto halves (`f16_round_stochastic`), with noise fresh for each
@@ -98,7 +140,7 @@ export const shader_probe_clipmap_accumulate = ComputeShader.from({
98
140
  //language=WGSL
99
141
  `
100
142
  fn probe_accumulate_light(ray: ${PROBE_RAY_STRUCT.wgsl_ref}) -> vec3<f32> {
101
- return vec3<f32>(unpack2x16float(ray.light_rg), unpack2x16float(ray.light_b).x);
143
+ return rgbe9995_decode(ray.light);
102
144
  }
103
145
 
104
146
  // uniform noise in [0, 1) for a texel's store, fresh each update
@@ -108,6 +150,36 @@ fn probe_accumulate_store_noise(slot: u32, texel: u32, updates: u32) -> vec3<f32
108
150
  return vec3<f32>(hash_to_float01(hash.x), hash_to_float01(hash.y), hash_to_float01(hash.z));
109
151
  }
110
152
 
153
+ // a texel's estimator from its words, its mean the atlas's
154
+ fn probe_accumulate_estimator(mean: vec3<f32>, words: vec4<u32>) -> ${MULTISCALE_MEAN_STRUCT.wgsl_ref} {
155
+ let rg = unpack2x16float(words.x);
156
+ let b_r = unpack2x16float(words.y);
157
+ let deviation = vec3<f32>(b_r.y, unpack2x16float(words.z));
158
+ let tail = unpack2x16float(words.w);
159
+
160
+ return ${MULTISCALE_MEAN_STRUCT.make({
161
+ mean: 'mean',
162
+ short_mean: 'vec3<f32>(rg, b_r.x)',
163
+ variance: 'deviation * deviation',
164
+ reduction: 'tail.x',
165
+ inconsistency: 'tail.y',
166
+ })};
167
+ }
168
+
169
+ // a texel's estimator as its words: the means and the deviation rounded stochastically, as the maps are, by
170
+ // noise of their own after the texel's; the inconsistency held to a half
171
+ fn probe_accumulate_estimator_words(e: ${MULTISCALE_MEAN_STRUCT.wgsl_ref}, slot: u32, key: u32, updates: u32) -> vec4<u32> {
172
+ let short_mean = f16_round_stochastic(vec4<f32>(e.short_mean, 0.0), vec4<f32>(probe_accumulate_store_noise(slot, key, updates), 0.0));
173
+ let deviation = f16_round_stochastic(vec4<f32>(sqrt(e.variance), 0.0), vec4<f32>(probe_accumulate_store_noise(slot, key + 1u, updates), 0.0));
174
+
175
+ return vec4<u32>(
176
+ pack2x16float(short_mean.rg),
177
+ pack2x16float(vec2<f32>(short_mean.b, deviation.r)),
178
+ pack2x16float(deviation.gb),
179
+ pack2x16float(vec2<f32>(e.reduction, min(e.inconsistency, F16_MAX))),
180
+ );
181
+ }
182
+
111
183
  // a ray's depth sample, in spacings: past a miss's, as far as a sample goes
112
184
  fn probe_accumulate_depth(ray: ${PROBE_RAY_STRUCT.wgsl_ref}, spacing: f32) -> f32 {
113
185
  if ((ray.flags & PROBE_RAY_KIND_MASK) == ${BRICK_TRACE_MISS}u) {
@@ -119,6 +191,27 @@ fn probe_accumulate_depth(ray: ${PROBE_RAY_STRUCT.wgsl_ref}, spacing: f32) -> f3
119
191
  return min(select(t, ${PROBE_BACK_FACE_DEPTH} * t, (ray.flags & PROBE_RAY_BACK_FACE) != 0u), ${PROBE_DEPTH_LIMIT});
120
192
  }
121
193
 
194
+ // a guided update's rays of a radiance texel, for the probe whose guide starts at word base: the first
195
+ // one, and how many, at most PROBE_TEXEL_RAYS
196
+ fn probe_accumulate_guided_rays(base: u32, texel: u32, updates: u32, rays: u32, n: u32) -> vec2<u32> {
197
+ let texels = n * n;
198
+ let position = probe_clipmap_guide_texel(texel, updates, n);
199
+ let first = probe_guide[base + position];
200
+ let end = select(rays, probe_guide[base + position + 1u], position + 1u < texels);
201
+
202
+ return vec2<u32>(first, min(select(0u, end - first, end > first), PROBE_TEXEL_RAYS));
203
+ }
204
+
205
+ // the rays a guided update gives a radiance texel, R·(w + e)/W
206
+ fn probe_accumulate_expected_rays(base: u32, texel: u32, rays: u32, n: u32) -> f32 {
207
+ let texels = n * n;
208
+ let total = probe_guide[base + 2u * texels + 2u * n];
209
+ let share = probe_guide[base + 2u * texels + 2u * n + 1u];
210
+
211
+ // the guide passes always leave a total; a guide they never wrote gives nothing
212
+ return select(0.0, f32(rays) * f32(probe_guide[base + texels + texel] + share) / f32(total), total > 0u);
213
+ }
214
+
122
215
  @compute @workgroup_size(${PROBE_THREAD_WORKGROUP_SIZE})
123
216
  fn main(
124
217
  @builtin(workgroup_id) workgroup_id: vec3<u32>,
@@ -139,21 +232,28 @@ fn main(
139
232
  let i = thread % per_probe;
140
233
  let slot = probe_trace.elements[k];
141
234
 
142
- let rays = settings.rays_per_probe;
143
- let first_ray = k * rays;
235
+ // the update's rays: the probe's first among the frame's, and how many
236
+ let span = probe_clipmap_probe_rays(k);
237
+ let rays = span.y;
238
+ let first_ray = span.x;
144
239
  let updates = probe_state_updates(probe_states[slot].x);
145
- let elapsed = max(settings.time - probe_records[slot].traced_time, 0.0);
240
+ let elapsed = f32(settings.frame - probe_records[slot].traced_frame);
146
241
  let rounds = max(rays / texels, 1u);
147
242
 
148
243
  let maps = k * probe_clipmap_maps_words(n, m);
244
+ let guided = probe_clipmap_guided(probe_states[slot].x, settings.uniform_period, settings.rays_per_probe, texels);
245
+ let base = k * probe_clipmap_guide_words(n);
149
246
 
150
247
  if (i < texels) {
151
248
  var sum = vec3<f32>(0.0);
152
249
  var count = 0u;
153
250
  var back_faces = 0u;
154
251
 
155
- for (var round = 0u; round < rounds; round++) {
156
- let ray = probe_clipmap_texel_ray(i, round, updates, rays, texels);
252
+ let run = probe_accumulate_guided_rays(base, i, updates, rays, n);
253
+ let gathered = select(rounds, run.y, guided);
254
+
255
+ for (var round = 0u; round < gathered; round++) {
256
+ let ray = select(probe_clipmap_texel_ray(i, round, updates, rays, texels), run.x + round, guided);
157
257
 
158
258
  if (ray == PROBE_CLIPMAP_NONE) {
159
259
  continue;
@@ -174,12 +274,42 @@ fn main(
174
274
  let history = select(textureLoad(probe_radiance, tile + vec2<u32>(i % n, i / n), 0), vec4<f32>(0.0), updates == 0u);
175
275
 
176
276
  var texel = history;
277
+ // how far the sample fell from the texel's mean in its own deviation, luminance, and that it blended
278
+ // one: the probe's ray request reads their sums. A texel's part is held to PROBE_CHANGE_SIGNIFICANCE,
279
+ // so that one bright sample is one texel's at most
280
+ var change = vec2<f32>(0.0);
177
281
 
178
282
  if (count > 0u) {
179
- let period = max(1.0, f32(texels) / f32(rays));
180
- let alpha = max(1.0 / (history.a + 1.0), 1.0 - exp(-elapsed * period / settings.response_time));
283
+ let sample = sum / f32(count);
284
+ let estimator = slot * texels + i;
285
+ let rate = probe_clipmap_guide_rate(probe_accumulate_expected_rays(base, i, rays, n), settings.rays_per_probe, texels, settings.uniform_period);
286
+
287
+ var e = multiscale_mean_seed(sample);
288
+
289
+ if (history.a > 0.0) {
290
+ // the gap in response times, a texel's own: its period is one over its share of updates
291
+ let gap = elapsed / (rate * settings.response_frames);
292
+ let ramp = 1.0 / (history.a + 1.0);
293
+ let variance_time = 1.0 - exp(-0.5 * gap);
294
+ let before = probe_accumulate_estimator(history.rgb, probe_estimators[estimator]);
295
+ // the estimator's own floor on the variance
296
+ let deviation = rgb_to_luminance(sqrt(max(vec3<f32>(1e-5), before.variance)));
297
+
298
+ change = vec2<f32>(clamp(rgb_to_luminance(sample - history.rgb) / deviation, -${PROBE_CHANGE_SIGNIFICANCE}.0, ${PROBE_CHANGE_SIGNIFICANCE}.0), 1.0);
299
+
300
+ e = multiscale_mean_add(
301
+ before,
302
+ sample,
303
+ max(ramp, 1.0 - exp(-gap)),
304
+ max(ramp, variance_time),
305
+ select(0.0, ramp, history.a < ${PROBE_RADIANCE_SAMPLES_LIMIT}.0),
306
+ ramp <= variance_time,
307
+ );
308
+ }
309
+
310
+ texel = vec4<f32>(e.mean, min(history.a + 1.0, ${PROBE_RADIANCE_SAMPLES_LIMIT}.0));
181
311
 
182
- texel = vec4<f32>(mix(history.rgb, sum / f32(count), alpha), min(history.a + 1.0, ${PROBE_RADIANCE_SAMPLES_LIMIT}.0));
312
+ probe_estimators[estimator] = probe_accumulate_estimator_words(e, slot, per_probe + 2u * i, updates);
183
313
  }
184
314
 
185
315
  // the count is whole, which any noise keeps
@@ -188,6 +318,7 @@ fn main(
188
318
  probe_maps[maps + 2u * i] = pack2x16float(stored.rg);
189
319
  probe_maps[maps + 2u * i + 1u] = pack2x16float(stored.ba);
190
320
  probe_maps[maps + 2u * texels + i] = count | (back_faces << 16u);
321
+ probe_maps[maps + 3u * texels + m * m + i] = pack2x16float(change);
191
322
 
192
323
  return;
193
324
  }
@@ -198,8 +329,50 @@ fn main(
198
329
 
199
330
  var sum = vec2<f32>(0.0);
200
331
  var count = 0u;
332
+ // the share of guided updates that reach this texel: its least reached radiance texel's
333
+ var reach = 1.0;
334
+
335
+ if (n >= m && guided) {
336
+ // the radiance texels inside this one, each a mean of its own
337
+ let f = n / m;
338
+ let budget = max(${PROBE_DEPTH_TEXEL_RAYS}u / (f * f), 1u);
339
+
340
+ for (var v = 0u; v < f; v++) {
341
+ for (var u = 0u; u < f; u++) {
342
+ let texel = (at.y * f + v) * n + at.x * f + u;
343
+ let run = probe_accumulate_guided_rays(base, texel, updates, rays, n);
344
+ let stride = max((run.y + budget - 1u) / budget, 1u);
345
+
346
+ reach = min(reach, min(probe_accumulate_expected_rays(base, texel, rays, n), 1.0));
347
+
348
+ var texel_sum = vec2<f32>(0.0);
349
+ var texel_count = 0u;
350
+
351
+ for (var q = 0u; q < run.y; q += stride) {
352
+ let record = probe_rays[first_ray + run.x + q];
353
+
354
+ if ((record.flags & PROBE_RAY_KIND_MASK) == ${BRICK_TRACE_UNRESOLVED}u) {
355
+ continue;
356
+ }
357
+
358
+ let d = probe_accumulate_depth(record, spacing);
201
359
 
202
- if (n >= m) {
360
+ texel_sum += vec2<f32>(d, d * d);
361
+ texel_count++;
362
+ }
363
+
364
+ if (texel_count > 0u) {
365
+ sum += texel_sum / f32(texel_count);
366
+ count++;
367
+ }
368
+ }
369
+ }
370
+
371
+ // a radiance texel the guide gave no ray, a dark one: the lit ones' depths are not the whole texel's
372
+ if (count < f * f) {
373
+ count = 0u;
374
+ }
375
+ } else if (n >= m) {
203
376
  // the radiance texels inside this one: their rays land in it
204
377
  let f = n / m;
205
378
 
@@ -207,6 +380,8 @@ fn main(
207
380
  for (var u = 0u; u < f; u++) {
208
381
  let texel = (at.y * f + v) * n + at.x * f + u;
209
382
 
383
+ reach = min(reach, min(probe_accumulate_expected_rays(base, texel, rays, n), 1.0));
384
+
210
385
  for (var round = 0u; round < rounds; round++) {
211
386
  let ray = probe_clipmap_texel_ray(texel, round, updates, rays, texels);
212
387
 
@@ -231,9 +406,14 @@ fn main(
231
406
  // the radiance texel this one is inside: those of its rays whose direction lands here
232
407
  let f = m / n;
233
408
  let texel = (at.y / f) * n + at.x / f;
409
+ let run = probe_accumulate_guided_rays(base, texel, updates, rays, n);
410
+ let gathered = select(rounds, run.y, guided);
411
+
412
+ // of the radiance texel's rays, the share whose direction lands here
413
+ reach = min(probe_accumulate_expected_rays(base, texel, rays, n) / f32(f * f), 1.0);
234
414
 
235
- for (var round = 0u; round < rounds; round++) {
236
- let ray = probe_clipmap_texel_ray(texel, round, updates, rays, texels);
415
+ for (var round = 0u; round < gathered; round++) {
416
+ let ray = select(probe_clipmap_texel_ray(texel, round, updates, rays, texels), run.x + round, guided);
237
417
 
238
418
  if (ray == PROBE_CLIPMAP_NONE) {
239
419
  continue;
@@ -259,7 +439,10 @@ fn main(
259
439
  var moments = textureLoad(probe_depth, tile + at, 0).rg;
260
440
 
261
441
  if (count > 0u) {
262
- let alpha = max(1.0 / f32(updates + 1u), 1.0 - exp(-elapsed / settings.response_time));
442
+ // a uniform update reaches every depth texel, a guided one those its rays land in
443
+ let period = f32(settings.uniform_period);
444
+ let rate = (1.0 + (period - 1.0) * reach) / period;
445
+ let alpha = max(1.0 / f32(updates + 1u), 1.0 - exp(-elapsed / (rate * settings.response_frames)));
263
446
 
264
447
  moments = mix(moments, sum / f32(count), alpha);
265
448
  } else if (updates == 0u) {
@@ -273,12 +456,18 @@ fn main(
273
456
  }
274
457
  `, [
275
458
  chunk_probe_clipmap,
459
+ chunk_probe_clipmap_ray_layout,
276
460
  chunk_probe_clipmap_ray_texel,
461
+ chunk_probe_clipmap_guide,
277
462
  chunk_folded_workgroup_index,
278
463
  chunk_index_to_grid2d,
279
464
  chunk_f16_round_stochastic,
280
465
  chunk_pcg3d,
281
466
  chunk_hash_to_float01,
467
+ chunk_multiscale_mean,
468
+ F16_MAX_DEFINITION,
469
+ chunk_rgbe9995_decode,
282
470
  PROBE_RAY_STRUCT.declaration_chunk,
471
+ MULTISCALE_MEAN_STRUCT.declaration_chunk,
283
472
  ]),
284
473
  });
@@ -17,7 +17,7 @@ export const PROBE_ADMIT_SETTINGS: WebGPUStruct;
17
17
  * Admit (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a point wanted this frame, dispatched
18
18
  * through `PROBE_DISPATCH_ADMIT`.
19
19
  *
20
- * A point that has a probe has its wanted time brought to the frame's. One that has none pops a slot:
20
+ * A point that has a probe has its wanted frame brought to this one. One that has none pops a slot:
21
21
  * the slot becomes a NEW probe at the point the cascade's window holds in that storage cell, with
22
22
  * nothing traced, its indirection entry names it, and it goes on the frame's active list. A pop the
23
23
  * free list cannot serve is counted, and the host grows the capacity on it (§7.10's pattern); the
@@ -26,6 +26,10 @@ export const PROBE_ADMIT_SETTINGS: WebGPUStruct;
26
26
  * Either way the probe is marked the screen's when its entry carries `PROBE_WANTED_SCREEN`, and the
27
27
  * hits' when it does not, which decides whether its hits want in turn.
28
28
  *
29
+ * A probe this frame's want leaves waiting for an update, that was not before, is counted into
30
+ * `PROBE_COUNTER_WAITING` beside retire's: one an update served since it was last wanted, and a NEW one.
31
+ * A probe that already waited, NEW or wanted since its last update, retire counted.
32
+ *
29
33
  * Retire ran first, so an entry that names a slot names the probe of this very point: the window holds
30
34
  * one point a storage cell, and a probe whose point left was freed.
31
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"shader_probe_clipmap_admit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js"],"names":[],"mappings":"AAuBA;;GAEG;AACH,2CAFU,YAAY,CAKU;AAUhC;;;;;GAKG;AACH,iDAFU,aAAa,CAqBpB;AAEH;;GAEG;AACH,mCAFU,YAAY,CAWG;AAgBzB;;;;;;;;;;;;;;;;;GAiBG;AACH,yCAFU,aAAa,CAiEpB;6BAvK0B,sCAAsC;8BAHrC,kCAAkC"}
1
+ {"version":3,"file":"shader_probe_clipmap_admit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js"],"names":[],"mappings":"AAwBA;;GAEG;AACH,2CAFU,YAAY,CAKU;AAUhC;;;;;GAKG;AACH,iDAFU,aAAa,CAqBpB;AAEH;;GAEG;AACH,mCAFU,YAAY,CAWG;AAgBzB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,yCAFU,aAAa,CAsEpB;6BAhL0B,sCAAsC;8BAHrC,kCAAkC"}
@@ -2,10 +2,11 @@ import { chunk_collection_u32_append } from "../../../gpu_primitive/chunk_collec
2
2
  import { chunk_folded_dispatch } from "../../../gpu_primitive/indirect/chunk_folded_dispatch.js";
3
3
  import { chunk_slot_stack } from "../../../gpu_primitive/slot_stack/chunk_slot_stack.js";
4
4
  import { chunk_folded_workgroup_index } from "../../../shader/chunk/grid/chunk_folded_workgroup_index.js";
5
+ import { chunk_subgroup_atomic_add } from "../../../shader/chunk/subgroup/chunk_subgroup_atomic_add.js";
5
6
  import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
6
7
  import { ComputeShader } from "../../../shader/ComputeShader.js";
7
8
  import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
8
- import { f32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
9
+ import { u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
9
10
  import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
10
11
  import {
11
12
  chunk_probe_clipmap,
@@ -74,8 +75,8 @@ export const PROBE_ADMIT_SETTINGS = WebGPUStruct.from({
74
75
  resolution: u32,
75
76
  /** keys over every cascade: what the wanted list holds at most */
76
77
  key_count: u32,
77
- /** the frame's time, seconds since the clipmap was made */
78
- time: f32,
78
+ /** the frame, of the frames the clipmap has recorded */
79
+ frame: u32,
79
80
  }, "ProbeAdmitSettings");
80
81
 
81
82
  const resources = new ShaderResourceSetDescriptor();
@@ -96,7 +97,7 @@ resources.createGroup()
96
97
  * Admit (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): a thread a point wanted this frame, dispatched
97
98
  * through `PROBE_DISPATCH_ADMIT`.
98
99
  *
99
- * A point that has a probe has its wanted time brought to the frame's. One that has none pops a slot:
100
+ * A point that has a probe has its wanted frame brought to this one. One that has none pops a slot:
100
101
  * the slot becomes a NEW probe at the point the cascade's window holds in that storage cell, with
101
102
  * nothing traced, its indirection entry names it, and it goes on the frame's active list. A pop the
102
103
  * free list cannot serve is counted, and the host grows the capacity on it (§7.10's pattern); the
@@ -105,6 +106,10 @@ resources.createGroup()
105
106
  * Either way the probe is marked the screen's when its entry carries `PROBE_WANTED_SCREEN`, and the
106
107
  * hits' when it does not, which decides whether its hits want in turn.
107
108
  *
109
+ * A probe this frame's want leaves waiting for an update, that was not before, is counted into
110
+ * `PROBE_COUNTER_WAITING` beside retire's: one an update served since it was last wanted, and a NEW one.
111
+ * A probe that already waited, NEW or wanted since its last update, retire counted.
112
+ *
108
113
  * Retire ran first, so an entry that names a slot names the probe of this very point: the window holds
109
114
  * one point a storage cell, and a probe whose point left was freed.
110
115
  *
@@ -125,20 +130,25 @@ fn main(
125
130
 
126
131
  var slot = 0u;
127
132
  var admitted = false;
133
+ var waits = false;
128
134
 
129
135
  if (index < min(probe_wanted.count, settings.key_count)) {
130
136
  let resolution = settings.resolution;
131
137
  let wanted = probe_wanted.elements[index];
132
138
  let key = wanted & ~PROBE_WANTED_SCREEN;
133
- let screen = select(0u, 1u, (wanted & PROBE_WANTED_SCREEN) != 0u);
139
+ let screen = (wanted & PROBE_WANTED_SCREEN) != 0u;
134
140
  let cascade = probe_clipmap_key_cascade(key, resolution);
135
141
  let storage = probe_clipmap_key_storage(key, resolution);
136
142
  let texel = probe_clipmap_indirection_texel(cascade, storage, resolution);
137
143
  let entry = textureLoad(probe_indirection, texel).x;
138
144
 
139
145
  if (entry != PROBE_CLIPMAP_NONE) {
140
- probe_records[entry].wanted_time = settings.time;
141
- probe_records[entry].screen = screen;
146
+ let waited = probe_state_kind(probe_states[entry].x) == PROBE_STATE_NEW || probe_records[entry].wanted_frame > probe_records[entry].traced_frame;
147
+
148
+ probe_records[entry].wanted_frame = settings.frame;
149
+ probe_records[entry].flags = (probe_records[entry].flags & ~PROBE_RECORD_SCREEN) | select(0u, PROBE_RECORD_SCREEN, screen);
150
+
151
+ waits = !waited;
142
152
  } else {
143
153
  slot = slot_stack_pop(&probe_counters[PROBE_COUNTER_FREE], &probe_free, settings.capacity);
144
154
 
@@ -147,13 +157,10 @@ fn main(
147
157
  } else {
148
158
  // field by field: nothing of the slot's last probe stays
149
159
  probe_records[slot].cell = probe_clipmap_window_point(storage, probe_levels[cascade].corner, resolution);
150
- probe_records[slot].cascade = cascade;
151
- probe_records[slot].wanted_time = settings.time;
152
- probe_records[slot].traced_time = settings.time;
153
- probe_records[slot].back_face = 0.0;
154
- probe_records[slot].screen = screen;
155
- probe_records[slot].sh.CoCg = vec2<f32>(0.0);
156
- probe_records[slot].sh.Y = vec4<f32>(0.0);
160
+ probe_records[slot].flags = probe_record_flags(0.0, screen, cascade);
161
+ probe_records[slot].wanted_frame = settings.frame;
162
+ probe_records[slot].traced_frame = settings.frame;
163
+ probe_records[slot].sh = vec3<u32>(0u);
157
164
 
158
165
  // at its lattice point until its first update relocates it
159
166
  probe_states[slot] = vec2<u32>(probe_state(PROBE_STATE_NEW, 0u), 0u);
@@ -161,10 +168,12 @@ fn main(
161
168
  textureStore(probe_indirection, texel, vec4<u32>(slot, 0u, 0u, 0u));
162
169
 
163
170
  admitted = true;
171
+ waits = true;
164
172
  }
165
173
  }
166
174
  }
167
175
 
176
+ subgroup_atomic_add_u32(&probe_counters[PROBE_COUNTER_WAITING], select(0u, 1u, waits));
168
177
  collection_u32_append(&probe_active_write, admitted, slot, settings.capacity);
169
178
  }
170
179
  `, [
@@ -172,5 +181,6 @@ fn main(
172
181
  chunk_folded_workgroup_index,
173
182
  chunk_slot_stack,
174
183
  chunk_collection_u32_append,
184
+ chunk_subgroup_atomic_add,
175
185
  ]),
176
186
  });
@@ -5,14 +5,23 @@ export const PROBE_DUE_SETTINGS: WebGPUStruct;
5
5
  /**
6
6
  * Due (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.5): a thread an entry of the frame's active list,
7
7
  * dispatched twice through `PROBE_DISPATCH_ACTIVE` after schedule has set the period T. A probe is due
8
- * when a pixel or a hit wanted it this frame, its point's bit set, and:
9
- * - it is NEW, in the first pass, which lists them first;
10
- * - in the second pass, it is ALIVE and `(frame + h(slot)) mod T` is 0, or DEAD and
11
- * `(frame + h(slot)) mod 8T` is 0, so that a probe inside a solid notices when the scene changes.
8
+ * when a want waits on it:
9
+ * - it is NEW, in the first pass, which lists them first: it has had no update;
10
+ * - in the second pass, it is ALIVE or DEAD, a pixel or a hit wanted it since its last update, its
11
+ * wanted time past its traced time, and `(frame + h(slot)) mod T` is 0. A DEAD probe's update casts
12
+ * the fewest rays (`PROBE_RAYS_PER_TEXEL_MIN`), every period rather than every eighth at R, so that a
13
+ * probe inside a solid notices when the scene changes sooner, for fewer rays (Enshrouded's dead probes
14
+ * trace 16 a frame).
15
+ *
16
+ * Wanted since its last update, not this frame: a hit wants a probe the frame after its own probe's
17
+ * update, so a probe that only hits keep is wanted on few of its turns. Measured on Sponza with the
18
+ * point's bit as the test, the hits' probes were updated 0.8 times a second at p10 against the screen's
19
+ * 6.6 at the least, and 6 s had passed since the last update at p99 (§8.3). A want an update served
20
+ * waits on nothing: the update comes after admit in its frame, so its traced time is the want's or later.
12
21
  *
13
22
  * The due go on the trace list, which holds the frame's updates, at most U: past it the count still
14
- * rises and nothing is written, and a probe not listed waits its next turn. With T = ⌈P_w / U⌉ the
15
- * expected count a frame is under U, so only NEW probes past U, a camera cut, wait.
23
+ * rises and nothing is written, and a probe not listed waits its next turn. With T = ⌈P_w / U⌉ over the
24
+ * probes waiting, the expected count a frame is under U, so only NEW probes past U, a camera cut, wait.
16
25
  *
17
26
  * @type {ComputeShader}
18
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"shader_probe_clipmap_due.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js"],"names":[],"mappings":"AAmBA;;GAEG;AACH,iCAFU,YAAY,CAaC;AAcvB;;;;;;;;;;;;;GAaG;AACH,uCAFU,aAAa,CAkDpB;6BAtG0B,sCAAsC;8BAHrC,kCAAkC"}
1
+ {"version":3,"file":"shader_probe_clipmap_due.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js"],"names":[],"mappings":"AAkBA;;GAEG;AACH,iCAFU,YAAY,CAWC;AAavB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,uCAFU,aAAa,CA4CpB;6BArG0B,sCAAsC;8BAHrC,kCAAkC"}