@woosh/meep-engine 3.39.0 → 3.40.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 (367) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/engine/EngineHarness.d.ts.map +1 -1
  4. package/src/engine/EngineHarness.js +17 -4
  5. package/src/engine/asset/loaders/image/avif/threaded_image_encoder.js +1 -1
  6. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  7. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
  8. package/src/engine/graphics/ecs/water/Water.d.ts +14 -17
  9. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  10. package/src/engine/graphics/ecs/water/Water.js +100 -110
  11. package/src/engine/graphics/ecs/water/WaterSerializationAdapter.d.ts.map +1 -1
  12. package/src/engine/graphics/ecs/water/WaterSerializationAdapter.js +36 -38
  13. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts +6 -0
  14. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts.map +1 -0
  15. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.js +10 -0
  16. package/src/engine/graphics/ecs/water/WaterWaves.d.ts +3 -3
  17. package/src/engine/graphics/ecs/water/WaterWaves.js +46 -46
  18. package/src/engine/graphics/texture/sampler/sampler2d_to_avif.d.ts.map +1 -1
  19. package/src/engine/graphics/texture/sampler/sampler2d_to_avif.js +8 -5
  20. package/src/engine/graphics3/WaterSystem.d.ts +21 -74
  21. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  22. package/src/engine/graphics3/WaterSystem.js +174 -367
  23. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  24. package/src/format/image/avif/api/convert_to_rgba.d.ts +2 -2
  25. package/src/format/image/avif/api/convert_to_rgba.d.ts.map +1 -1
  26. package/src/format/image/avif/api/convert_to_rgba.js +10 -9
  27. package/src/format/image/avif/api/decode_avif.d.ts +2 -2
  28. package/src/format/image/avif/api/decode_avif.d.ts.map +1 -1
  29. package/src/format/image/avif/api/decode_avif.js +1 -1
  30. package/src/shade/playground/ssr_reprojection/README.md +111 -103
  31. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +68 -68
  32. package/src/shade/playground/ssr_reprojection/index.html +80 -79
  33. package/src/shade/playground/ssr_reprojection/main.js +256 -247
  34. package/src/shade/playground/ssr_variance/capture.js +96 -96
  35. package/src/shade/playground/ssr_variance/reference.js +78 -78
  36. package/src/shade/playground/vsm/README.md +96 -0
  37. package/src/shade/playground/vsm/VSMDebugOverlay.d.ts +49 -0
  38. package/src/shade/playground/vsm/VSMDebugOverlay.d.ts.map +1 -0
  39. package/src/shade/playground/vsm/VSMDebugOverlay.js +351 -0
  40. package/src/shade/playground/vsm/clipmap_panel.d.ts +8 -0
  41. package/src/shade/playground/vsm/clipmap_panel.d.ts.map +1 -0
  42. package/src/shade/playground/vsm/clipmap_panel.js +138 -0
  43. package/src/shade/playground/vsm/index.html +170 -0
  44. package/src/shade/playground/vsm/main.d.ts +2 -0
  45. package/src/shade/playground/vsm/main.d.ts.map +1 -0
  46. package/src/shade/playground/vsm/main.js +389 -0
  47. package/src/shade/playground/vsm/scenes.d.ts +52 -0
  48. package/src/shade/playground/vsm/scenes.d.ts.map +1 -0
  49. package/src/shade/playground/vsm/scenes.js +320 -0
  50. package/src/shade/playground/vsm/verify_vsm.d.ts +38 -0
  51. package/src/shade/playground/vsm/verify_vsm.d.ts.map +1 -0
  52. package/src/shade/playground/vsm/verify_vsm.js +305 -0
  53. package/src/shade/playground/water_refraction/README.md +57 -9
  54. package/src/shade/playground/water_refraction/main.js +12 -3
  55. package/src/shade/playground/water_refraction/world.d.ts +1 -0
  56. package/src/shade/playground/water_refraction/world.d.ts.map +1 -1
  57. package/src/shade/playground/water_refraction/world.js +15 -5
  58. package/src/shade/renderer/Renderer.d.ts +19 -0
  59. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  60. package/src/shade/renderer/Renderer.js +72 -1
  61. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +8 -0
  62. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  63. package/src/shade/renderer/animation/GPUAnimationManager.js +18 -0
  64. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +7 -0
  65. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  66. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -0
  67. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts +3 -1
  68. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts.map +1 -1
  69. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +10 -1
  70. package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.d.ts.map +1 -1
  71. package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.js +28 -0
  72. package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.d.ts.map +1 -1
  73. package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.js +31 -1
  74. package/src/shade/renderer/geometry/MeshletGeometry.d.ts +3 -0
  75. package/src/shade/renderer/geometry/MeshletGeometry.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/MeshletGeometry.js +1 -0
  77. package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.d.ts.map +1 -1
  78. package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.js +62 -4
  79. package/src/shade/renderer/light/environment/rgbe/parse_rgbe.d.ts +1 -1
  80. package/src/shade/renderer/light/environment/rgbe/parse_rgbe.js +2 -2
  81. package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts +2 -2
  82. package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts.map +1 -1
  83. package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.js +6 -14
  84. package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.d.ts.map +1 -1
  85. package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.js +5 -1
  86. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  87. package/src/shade/renderer/medium/ParticipatingMedium.d.ts +3 -0
  88. package/src/shade/renderer/medium/ParticipatingMedium.d.ts.map +1 -1
  89. package/src/shade/renderer/medium/ParticipatingMedium.js +7 -0
  90. package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.d.ts.map +1 -1
  91. package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.js +5 -35
  92. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  93. package/src/shade/renderer/postprocess/ssr/SSR.d.ts +12 -4
  94. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  95. package/src/shade/renderer/postprocess/ssr/SSR.js +36 -8
  96. package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts +3 -0
  97. package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts.map +1 -0
  98. package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.js +2 -0
  99. package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts +8 -0
  100. package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts.map +1 -0
  101. package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.js +40 -0
  102. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
  103. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +150 -137
  104. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts +3 -0
  105. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts.map +1 -0
  106. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.js +44 -0
  107. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts +5 -0
  108. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts.map +1 -0
  109. package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.js +35 -0
  110. package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts +26 -0
  111. package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts.map +1 -0
  112. package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.js +42 -0
  113. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +1 -0
  114. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
  115. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +113 -105
  116. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts +2 -0
  117. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  118. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +177 -167
  119. package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.d.ts.map +1 -1
  120. package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.js +10 -0
  121. package/src/shade/renderer/rasterize/RasterizationJob.d.ts +1 -2
  122. package/src/shade/renderer/rasterize/RasterizationJob.d.ts.map +1 -1
  123. package/src/shade/renderer/rasterize/RasterizationJob.js +1 -2
  124. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +5 -6
  125. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
  126. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +5 -6
  127. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +2 -2
  128. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  129. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +1 -1
  130. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  131. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +11 -0
  132. package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.d.ts.map +1 -1
  133. package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.js +4 -5
  134. package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.d.ts.map +1 -1
  135. package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.js +1 -5
  136. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts +30 -0
  137. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts.map +1 -0
  138. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.js +54 -0
  139. package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.d.ts.map +1 -1
  140. package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.js +3 -2
  141. package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts +19 -0
  142. package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts.map +1 -0
  143. package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.js +27 -0
  144. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts +1 -0
  145. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts.map +1 -1
  146. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +4 -0
  147. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +54 -0
  148. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  149. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +502 -10
  150. package/src/shade/renderer/shadow/map/Shadowmap.d.ts +3 -2
  151. package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
  152. package/src/shade/renderer/shadow/map/Shadowmap.js +3 -2
  153. package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts +8 -0
  154. package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts.map +1 -1
  155. package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.js +34 -3
  156. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +3 -2
  157. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
  158. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +17 -2
  159. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
  160. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +137 -133
  161. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts +15 -0
  162. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts.map +1 -0
  163. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.js +14 -0
  164. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts +16 -0
  165. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts.map +1 -0
  166. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.js +15 -0
  167. package/src/shade/renderer/shadow/vsm/PLAN.md +440 -0
  168. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +43 -0
  169. package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts +42 -0
  170. package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts.map +1 -0
  171. package/src/shade/renderer/shadow/vsm/VSMMoverTracker.js +153 -0
  172. package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts +327 -0
  173. package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts.map +1 -0
  174. package/src/shade/renderer/shadow/vsm/VSMPageManager.js +1408 -0
  175. package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts +14 -0
  176. package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts.map +1 -0
  177. package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.js +13 -0
  178. package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts +63 -0
  179. package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts.map +1 -0
  180. package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.js +70 -0
  181. package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts +11 -0
  182. package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts.map +1 -0
  183. package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.js +10 -0
  184. package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts +54 -0
  185. package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts.map +1 -0
  186. package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.js +75 -0
  187. package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts +23 -0
  188. package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts.map +1 -0
  189. package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.js +85 -0
  190. package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts +16 -0
  191. package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts.map +1 -0
  192. package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.js +29 -0
  193. package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts +136 -25
  194. package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts.map +1 -1
  195. package/src/shade/renderer/shadow/vsm/VirtualShadowMap.js +282 -116
  196. package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts +39 -0
  197. package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts.map +1 -0
  198. package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.js +289 -0
  199. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts +18 -0
  200. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts.map +1 -0
  201. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.js +65 -0
  202. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts +17 -0
  203. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts.map +1 -0
  204. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.js +75 -0
  205. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts +14 -0
  206. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts.map +1 -0
  207. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.js +45 -0
  208. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts +17 -0
  209. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts.map +1 -0
  210. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.js +100 -0
  211. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts +15 -0
  212. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts.map +1 -0
  213. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.js +47 -0
  214. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts +26 -0
  215. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts.map +1 -0
  216. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.js +156 -0
  217. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts +13 -0
  218. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts.map +1 -0
  219. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.js +65 -0
  220. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts +30 -0
  221. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts.map +1 -0
  222. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.js +184 -0
  223. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts +23 -0
  224. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts.map +1 -0
  225. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.js +109 -0
  226. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts +56 -0
  227. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts.map +1 -0
  228. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.js +211 -0
  229. package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts +1 -1
  230. package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts.map +1 -1
  231. package/src/shade/renderer/texture/format/decode_typed_gpu_data.js +3 -13
  232. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -1
  233. package/src/shade/renderer/texture/format/infer_format_from_parameters.js +2 -3
  234. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
  235. package/src/shade/renderer/texture/texture_write_to_gpu.js +16 -16
  236. package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts +4 -90
  237. package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts.map +1 -1
  238. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +6 -210
  239. package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts +119 -0
  240. package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts.map +1 -0
  241. package/src/shade/renderer/texture/virtual/VTPhysicalSlots.js +245 -0
  242. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts +1 -1
  243. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts.map +1 -1
  244. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +3 -19
  245. package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts +13 -0
  246. package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts.map +1 -0
  247. package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.js +34 -0
  248. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +7 -2
  249. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  250. package/src/shade/renderer/water/GPUWaterRenderer.js +49 -49
  251. package/src/shade/renderer/water/chunk_water_transport.js +3 -3
  252. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +11 -25
  253. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  254. package/src/shade/renderer/water/medium/GPUWaterBodies.js +64 -116
  255. package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts +1 -20
  256. package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts.map +1 -1
  257. package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.js +10 -42
  258. package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts +3 -0
  259. package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts.map +1 -0
  260. package/src/shade/renderer/water/medium/chunk_water_bodies.js +3 -0
  261. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts +1 -5
  262. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts.map +1 -1
  263. package/src/shade/renderer/water/medium/shader_water_bodies_derive.js +32 -30
  264. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts +4 -0
  265. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts.map +1 -0
  266. package/src/shade/renderer/water/medium/shader_water_meshlets.js +69 -0
  267. package/src/shade/renderer/water/optics/chunk_water_inscatter.d.ts.map +1 -1
  268. package/src/shade/renderer/water/optics/chunk_water_inscatter.js +124 -123
  269. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
  270. package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +75 -74
  271. package/src/shade/renderer/water/shader_water.d.ts +1 -1
  272. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  273. package/src/shade/renderer/water/shader_water.js +490 -406
  274. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts +12 -85
  275. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts.map +1 -1
  276. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.js +128 -408
  277. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts +6 -0
  278. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts.map +1 -0
  279. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.js +23 -0
  280. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts +9 -0
  281. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts.map +1 -0
  282. package/src/shade/renderer/water/surface/chunk_water_tessellation.js +144 -0
  283. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts +3 -5
  284. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts.map +1 -1
  285. package/src/shade/renderer/water/surface/chunk_water_wave.js +40 -48
  286. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +14 -0
  287. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -0
  288. package/src/shade/renderer/water/surface/graph_water_tessellation.js +34 -0
  289. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts +4 -0
  290. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts.map +1 -0
  291. package/src/shade/renderer/water/surface/shader_water_tiles.js +123 -0
  292. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts +6 -0
  293. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts.map +1 -0
  294. package/src/shade/renderer/water/surface/shader_water_wave_batch.js +85 -0
  295. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts +6 -0
  296. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts.map +1 -0
  297. package/src/shade/renderer/water/surface/shader_water_wave_domain.js +83 -0
  298. package/src/shade/renderer/water/water_height_texture_from_sampler.d.ts.map +1 -1
  299. package/src/shade/renderer/water/water_height_texture_from_sampler.js +4 -3
  300. package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts +0 -2
  301. package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts.map +0 -1
  302. package/src/engine/graphics/ecs/water/WATER_SIZE.js +0 -1
  303. package/src/shade/renderer/light/GPUViewLightContext.d.ts +0 -22
  304. package/src/shade/renderer/light/GPUViewLightContext.d.ts.map +0 -1
  305. package/src/shade/renderer/light/GPUViewLightContext.js +0 -62
  306. package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts +0 -14
  307. package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts.map +0 -1
  308. package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.js +0 -20
  309. package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts +0 -27
  310. package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts.map +0 -1
  311. package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.js +0 -147
  312. package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts +0 -7
  313. package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts.map +0 -1
  314. package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.js +0 -10
  315. package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts +0 -2
  316. package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts.map +0 -1
  317. package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.js +0 -1
  318. package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts +0 -3
  319. package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts.map +0 -1
  320. package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.js +0 -8
  321. package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts +0 -27
  322. package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts.map +0 -1
  323. package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.js +0 -102
  324. package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts +0 -8
  325. package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts.map +0 -1
  326. package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.js +0 -34
  327. package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts +0 -10
  328. package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts.map +0 -1
  329. package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.js +0 -64
  330. package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts +0 -11
  331. package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts.map +0 -1
  332. package/src/shade/renderer/shadow/vsm/decode_tile_address.js +0 -26
  333. package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts +0 -2
  334. package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts.map +0 -1
  335. package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.js +0 -11
  336. package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts +0 -20
  337. package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts.map +0 -1
  338. package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.js +0 -184
  339. package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts +0 -25
  340. package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts.map +0 -1
  341. package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.js +0 -230
  342. package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts +0 -19
  343. package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts.map +0 -1
  344. package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.js +0 -127
  345. package/src/shade/renderer/texture/encode/ENCODE_NOTES_2026_09_02.md +0 -462
  346. package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts +0 -23
  347. package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts.map +0 -1
  348. package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts +0 -18
  349. package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts.map +0 -1
  350. package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts +0 -12
  351. package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts.map +0 -1
  352. package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.js +0 -27
  353. package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts +0 -14
  354. package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts.map +0 -1
  355. package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.js +0 -49
  356. package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts +0 -9
  357. package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts.map +0 -1
  358. package/src/shade/renderer/water/surface/chunk_water_wave_grid.js +0 -47
  359. package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts +0 -10
  360. package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts.map +0 -1
  361. package/src/shade/renderer/water/surface/shader_water_surface_write.js +0 -51
  362. package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts +0 -12
  363. package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts.map +0 -1
  364. package/src/shade/renderer/water/surface/shader_water_wave_step.js +0 -54
  365. package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts +0 -13
  366. package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts.map +0 -1
  367. package/src/shade/renderer/water/surface/water_surface_grid_indices.js +0 -39
@@ -0,0 +1,100 @@
1
+ import { chunk_vt_page_table_entry } from "../../../texture/virtual/chunk_vt_page_table_entry.js";
2
+ import { LIGHT_DATABASE_SPEC } from "../../../light/LIGHT_DATABASE_SPEC.js";
3
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
4
+ import { VSM_LEVEL_LIMIT } from "../VSM_LEVEL_LIMIT.js";
5
+ import { VSM_RECORD_STRUCT } from "../VSM_RECORD_STRUCT.js";
6
+ import { chunk_vsm_addressing } from "./chunk_vsm_addressing.js";
7
+
8
+ const PAGE_TABLE = LIGHT_DATABASE_SPEC.get('shadow_virtual_page');
9
+
10
+ /**
11
+ * Which page of a virtual shadow map a world point asks for, and which resident page shadows it.
12
+ *
13
+ * - `vsm_request_page(database, record, p)` — the first level at or above the point's desired level
14
+ * whose window holds it, and the world page there. The demand pass asks for exactly this page.
15
+ * - `vsm_find_resident_page(database, record, p)` — the same walk, carried on up the levels until a
16
+ * resident page is found: the requested page itself, or the nearest coarser one standing in for
17
+ * it. A sampler reads this one.
18
+ *
19
+ * Both walks are bounded by {@link VSM_LEVEL_LIMIT} and stop at the map's level count; a point no
20
+ * level holds, or no resident page covers, answers with level {@link VSM_LEVEL_NONE}.
21
+ *
22
+ * @type {CodeChunk}
23
+ */
24
+ export const chunk_vsm_find_page = CodeChunk.from(
25
+ //language=WGSL
26
+ `
27
+ const VSM_LEVEL_NONE: u32 = 0xFFFFFFFFu;
28
+
29
+ struct VSMPageAddress {
30
+ // the level, or VSM_LEVEL_NONE
31
+ level: u32,
32
+ // world page coordinates at that level
33
+ page: vec2i,
34
+ // the pool slot holding it, for a resident page
35
+ phys: vec2u,
36
+ }
37
+
38
+ fn vsm_request_page(
39
+ database: ptr<storage, array<u32>>,
40
+ record: ${VSM_RECORD_STRUCT.wgsl_ref},
41
+ position_ws: vec3f,
42
+ ) -> VSMPageAddress {
43
+ let light_space = vsm_light_space(record, position_ws);
44
+
45
+ var level = vsm_desired_level(record, position_ws);
46
+
47
+ for (var step = 0u; step < ${VSM_LEVEL_LIMIT}u; step++) {
48
+ if (level >= record.level_count) {
49
+ break;
50
+ }
51
+
52
+ let page = vsm_world_page(record, light_space.xy, level);
53
+
54
+ if (vsm_window_contains(database, record, page, level)) {
55
+ return VSMPageAddress(level, page, vec2u(0u));
56
+ }
57
+
58
+ level += 1u;
59
+ }
60
+
61
+ return VSMPageAddress(VSM_LEVEL_NONE, vec2i(0), vec2u(0u));
62
+ }
63
+
64
+ fn vsm_find_resident_page(
65
+ database: ptr<storage, array<u32>>,
66
+ record: ${VSM_RECORD_STRUCT.wgsl_ref},
67
+ position_ws: vec3f,
68
+ ) -> VSMPageAddress {
69
+ let light_space = vsm_light_space(record, position_ws);
70
+
71
+ var level = vsm_desired_level(record, position_ws);
72
+
73
+ for (var step = 0u; step < ${VSM_LEVEL_LIMIT}u; step++) {
74
+ if (level >= record.level_count) {
75
+ break;
76
+ }
77
+
78
+ let page = vsm_world_page(record, light_space.xy, level);
79
+
80
+ if (vsm_window_contains(database, record, page, level)) {
81
+ let word = ${PAGE_TABLE.marshalling_method_read}(database, record.first_page + vsm_cell_index(record, page, level));
82
+ let entry = vt_entry_unpack(word);
83
+
84
+ if (entry.valid) {
85
+ return VSMPageAddress(level, page, entry.phys);
86
+ }
87
+ }
88
+
89
+ level += 1u;
90
+ }
91
+
92
+ return VSMPageAddress(VSM_LEVEL_NONE, vec2i(0), vec2u(0u));
93
+ }
94
+ `, [
95
+ VSM_RECORD_STRUCT.declaration_chunk,
96
+ PAGE_TABLE.chunk_read,
97
+ chunk_vt_page_table_entry,
98
+ chunk_vsm_addressing,
99
+ ]
100
+ );
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The view-projection a page of a virtual shadow map was drawn with: the light view, then the
3
+ * orthographic projection of the page's square widened by its border on every side — the slot the
4
+ * page fills, so the matrix maps the slot onto clip space and a sampler handed it with the slot's
5
+ * atlas rect reads exactly what the page's draw wrote.
6
+ *
7
+ * Built the way the CPU builds the page camera's: `OrthographicCamera.update_projection`'s
8
+ * reverse-Z orthographic matrix, times the light view. The two have to agree to a fraction of a
9
+ * texel, and the border is what absorbs the f32-against-f64 difference.
10
+ *
11
+ * @type {CodeChunk}
12
+ */
13
+ export const chunk_vsm_page_view_projection: CodeChunk;
14
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
15
+ //# sourceMappingURL=chunk_vsm_page_view_projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_vsm_page_view_projection.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,6CAFU,SAAS,CAgCjB;0BA9CwB,uCAAuC"}
@@ -0,0 +1,47 @@
1
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
2
+ import { VSM_RECORD_STRUCT } from "../VSM_RECORD_STRUCT.js";
3
+ import { chunk_vsm_addressing } from "./chunk_vsm_addressing.js";
4
+
5
+ /**
6
+ * The view-projection a page of a virtual shadow map was drawn with: the light view, then the
7
+ * orthographic projection of the page's square widened by its border on every side — the slot the
8
+ * page fills, so the matrix maps the slot onto clip space and a sampler handed it with the slot's
9
+ * atlas rect reads exactly what the page's draw wrote.
10
+ *
11
+ * Built the way the CPU builds the page camera's: `OrthographicCamera.update_projection`'s
12
+ * reverse-Z orthographic matrix, times the light view. The two have to agree to a fraction of a
13
+ * texel, and the border is what absorbs the f32-against-f64 difference.
14
+ *
15
+ * @type {CodeChunk}
16
+ */
17
+ export const chunk_vsm_page_view_projection = CodeChunk.from(
18
+ //language=WGSL
19
+ `
20
+ fn vsm_page_view_projection(record: ${VSM_RECORD_STRUCT.wgsl_ref}, level: u32, page: vec2i) -> mat4x4f {
21
+ let size = vsm_page_world_size(record, level);
22
+ let border = size * f32(record.border) / f32(record.page_size);
23
+
24
+ let left = f32(page.x) * size - border;
25
+ let right = f32(page.x + 1) * size + border;
26
+ let bottom = f32(page.y) * size - border;
27
+ let top = f32(page.y + 1) * size + border;
28
+
29
+ // ortho_reverse_z: near maps to 1, far to 0
30
+ let lr = 1.0 / (left - right);
31
+ let bt = 1.0 / (bottom - top);
32
+ let nf = 1.0 / (record.far - record.near);
33
+
34
+ let projection = mat4x4f(
35
+ vec4f(-2.0 * lr, 0.0, 0.0, 0.0),
36
+ vec4f(0.0, -2.0 * bt, 0.0, 0.0),
37
+ vec4f(0.0, 0.0, nf, 0.0),
38
+ vec4f((left + right) * lr, (top + bottom) * bt, record.far * nf, 1.0),
39
+ );
40
+
41
+ return projection * record.view;
42
+ }
43
+ `, [
44
+ VSM_RECORD_STRUCT.declaration_chunk,
45
+ chunk_vsm_addressing,
46
+ ]
47
+ );
@@ -0,0 +1,26 @@
1
+ export const VSM_DEMAND_WORKGROUP_SIZE: 8;
2
+ /**
3
+ * @type {WebGPUStruct}
4
+ */
5
+ export const VSM_DEMAND_SETTINGS_STRUCT: WebGPUStruct;
6
+ /**
7
+ * Ask for the pages the main view's pixels will sample: one thread per pixel of its depth, the
8
+ * point's world position back from the depth, and the page {@link chunk_vsm_find_page} requests for
9
+ * it — the same page every sampler starts its walk from.
10
+ *
11
+ * Each page-table cell has a counter of the importance of the pixels asking for it: a pixel adds
12
+ * its weight under the screen importance mask ({@link chunk_screen_importance}, the automatic
13
+ * exposure's metering mask), so a page wanted in the middle of the screen outweighs one wanted by as
14
+ * many pixels at its edge. The pixel whose add finds the counter at zero lists the page in the
15
+ * feedback buffer, so the list holds each page once without a compaction pass.
16
+ * {@link shader_vsm_gather_counts} writes the final sums into it afterwards.
17
+ *
18
+ * Dispatch over the depth texture at {@link VSM_DEMAND_WORKGROUP_SIZE}² with `counts` and the
19
+ * feedback buffer zeroed.
20
+ *
21
+ * @type {ComputeShader}
22
+ */
23
+ export const shader_vsm_demand: ComputeShader;
24
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
25
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
26
+ //# sourceMappingURL=shader_vsm_demand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_vsm_demand.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.js"],"names":[],"mappings":"AAeA,0CAA2C;AAE3C;;GAEG;AACH,yCAFU,YAAY,CAOE;AA6GxB;;;;;;;;;;;;;;;;GAgBG;AACH,gCAFU,aAAa,CAMpB;6BAhJ0B,sCAAsC;8BAJrC,kCAAkC"}
@@ -0,0 +1,156 @@
1
+ import { WebGPUExtensionType } from "../../../../descriptor/WebGPUExtensionType.js";
2
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
3
+ import { DEPTH_BACKGROUND_VALUE } from "../../../depth/DEPTH_BACKGROUND_VALUE.js";
4
+ import { LIGHT_DATABASE_SPEC } from "../../../light/LIGHT_DATABASE_SPEC.js";
5
+ import { chunk_project_position_from_depth } from "../../../shader/chunk/camera/chunk_project_position_from_depth.js";
6
+ import { chunk_screen_importance } from "../../../shader/chunk/screen_space/chunk_screen_importance.js";
7
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
8
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
9
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
10
+ import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
11
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
12
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
13
+ import { VSM_FEEDBACK_LAYOUT } from "../VSM_FEEDBACK_LAYOUT.js";
14
+ import { chunk_vsm_find_page } from "./chunk_vsm_find_page.js";
15
+
16
+ export const VSM_DEMAND_WORKGROUP_SIZE = 8;
17
+
18
+ /**
19
+ * @type {WebGPUStruct}
20
+ */
21
+ export const VSM_DEMAND_SETTINGS_STRUCT = WebGPUStruct.from({
22
+ /** the map's row of `shadow_virtual` */
23
+ record_row: u32,
24
+ /** requests the feedback buffer holds */
25
+ request_capacity: u32,
26
+ }, "VSMDemandSettings");
27
+
28
+ const RECORD_TABLE = LIGHT_DATABASE_SPEC.get('shadow_virtual');
29
+ const L = VSM_FEEDBACK_LAYOUT;
30
+
31
+ const resources = new ShaderResourceSetDescriptor();
32
+
33
+ resources.setImmediate('settings', VSM_DEMAND_SETTINGS_STRUCT);
34
+
35
+ resources.createGroup()
36
+ .addTexture('depth', 'depth')
37
+ .addUniform('camera', CAMERA_UNIFORM_STRUCT)
38
+ .addStorageBuffer('light_database', WebGPUArray.from(u32), false)
39
+ // one counter per page-table cell: the importance of the pixels that asked for its page this frame
40
+ .addStorageBuffer('counts', WebGPUArray.from(atomic_u32), true)
41
+ .addStorageBuffer('feedback', WebGPUArray.from(atomic_u32), true);
42
+
43
+ const body = CodeChunk.from(
44
+ //language=WGSL
45
+ `
46
+ const CELL_NONE: u32 = 0xFFFFFFFFu;
47
+
48
+ @compute @workgroup_size(${VSM_DEMAND_WORKGROUP_SIZE}, ${VSM_DEMAND_WORKGROUP_SIZE}, 1)
49
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
50
+ let size = textureDimensions(depth);
51
+
52
+ // a lane past the edge does not return: the whole subgroup has to reach the counting below
53
+ let inside = global_id.x < size.x && global_id.y < size.y;
54
+ let pixel = min(global_id.xy, size - 1u);
55
+
56
+ let z = textureLoad(depth, pixel, 0);
57
+
58
+ let record = ${RECORD_TABLE.marshalling_method_read}(&light_database, settings.record_row);
59
+
60
+ var cell = CELL_NONE;
61
+ var level = 0u;
62
+ var page = vec2i(0);
63
+ var light_depth = 0.0;
64
+
65
+ let uv = (vec2f(pixel) + 0.5) / vec2f(size);
66
+
67
+ // the view clears to the background depth: no surface there to shadow
68
+ if (inside && z != ${DEPTH_BACKGROUND_VALUE}) {
69
+ let position = project_position_from_depth(uv, z, camera.view_projection_matrix_inverse);
70
+
71
+ let wanted = vsm_request_page(&light_database, record, position);
72
+
73
+ if (wanted.level != VSM_LEVEL_NONE) {
74
+ level = wanted.level;
75
+ page = wanted.page;
76
+ cell = vsm_cell_index(record, page, level);
77
+ light_depth = vsm_light_space(record, position).z;
78
+ }
79
+ }
80
+
81
+ // a pixel counts by where it is on screen: the exposure's metering mask, the edges counting for
82
+ // less but never for nothing
83
+ let weight = select(0u, screen_importance_weight(uv, f32(size.y) / f32(size.x)), cell != CELL_NONE);
84
+
85
+ // neighbouring pixels mostly want the same page: a subgroup that agrees adds once — agreement
86
+ // being its lowest and highest cell the same, a lane asking for nothing included
87
+ let agreed = subgroupMin(cell) == subgroupMax(cell);
88
+ let asking = subgroupAdd(weight);
89
+ let elected = subgroupElect();
90
+
91
+ var add = 0u;
92
+
93
+ if (agreed) {
94
+ if (elected) {
95
+ add = asking;
96
+ }
97
+ } else {
98
+ add = weight;
99
+ }
100
+
101
+ if (add == 0u) {
102
+ return;
103
+ }
104
+
105
+ let before = atomicAdd(&counts[cell], add);
106
+
107
+ // the first to ask lists the page, with the depth of a receiver it shadows
108
+ if (before != 0u) {
109
+ return;
110
+ }
111
+
112
+ let index = atomicAdd(&feedback[${L.REQUEST_COUNT}u], 1u);
113
+
114
+ if (index >= settings.request_capacity) {
115
+ return;
116
+ }
117
+
118
+ let base = ${L.HEADER_WORDS}u + index * ${L.REQUEST_WORDS}u;
119
+
120
+ atomicStore(&feedback[base + ${L.REQUEST_LEVEL}u], level);
121
+ atomicStore(&feedback[base + ${L.REQUEST_X}u], u32(page.x));
122
+ atomicStore(&feedback[base + ${L.REQUEST_Y}u], u32(page.y));
123
+ atomicStore(&feedback[base + ${L.REQUEST_DEPTH}u], bitcast<u32>(light_depth));
124
+ }
125
+ `, [
126
+ CAMERA_UNIFORM_STRUCT.declaration_chunk,
127
+ RECORD_TABLE.chunk_read,
128
+ chunk_project_position_from_depth,
129
+ chunk_screen_importance,
130
+ chunk_vsm_find_page,
131
+ ]);
132
+
133
+ body.addExtension(WebGPUExtensionType.Subgroups);
134
+
135
+ /**
136
+ * Ask for the pages the main view's pixels will sample: one thread per pixel of its depth, the
137
+ * point's world position back from the depth, and the page {@link chunk_vsm_find_page} requests for
138
+ * it — the same page every sampler starts its walk from.
139
+ *
140
+ * Each page-table cell has a counter of the importance of the pixels asking for it: a pixel adds
141
+ * its weight under the screen importance mask ({@link chunk_screen_importance}, the automatic
142
+ * exposure's metering mask), so a page wanted in the middle of the screen outweighs one wanted by as
143
+ * many pixels at its edge. The pixel whose add finds the counter at zero lists the page in the
144
+ * feedback buffer, so the list holds each page once without a compaction pass.
145
+ * {@link shader_vsm_gather_counts} writes the final sums into it afterwards.
146
+ *
147
+ * Dispatch over the depth texture at {@link VSM_DEMAND_WORKGROUP_SIZE}² with `counts` and the
148
+ * feedback buffer zeroed.
149
+ *
150
+ * @type {ComputeShader}
151
+ */
152
+ export const shader_vsm_demand = ComputeShader.from({
153
+ label: "VSM/Demand",
154
+ body,
155
+ resources,
156
+ });
@@ -0,0 +1,13 @@
1
+ export const VSM_GATHER_WORKGROUP_SIZE: 64;
2
+ /**
3
+ * Write the pixels that asked for each listed page into its request, once {@link shader_vsm_demand}
4
+ * has run over every pixel: the counter of the page's cell, as it ended.
5
+ *
6
+ * One thread per request the feedback buffer can hold — a fixed dispatch of
7
+ * `ceil(request_capacity / 64)` workgroups, the listed ones doing the work.
8
+ *
9
+ * @type {ComputeShader}
10
+ */
11
+ export const shader_vsm_gather_counts: ComputeShader;
12
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
13
+ //# sourceMappingURL=shader_vsm_gather_counts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_vsm_gather_counts.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.js"],"names":[],"mappings":"AAUA,2CAA4C;AAc5C;;;;;;;;GAQG;AACH,uCAFU,aAAa,CAiCpB;8BA9D2B,kCAAkC"}
@@ -0,0 +1,65 @@
1
+ import { LIGHT_DATABASE_SPEC } from "../../../light/LIGHT_DATABASE_SPEC.js";
2
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
3
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
4
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
5
+ import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
6
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
7
+ import { VSM_FEEDBACK_LAYOUT } from "../VSM_FEEDBACK_LAYOUT.js";
8
+ import { chunk_vsm_addressing } from "./chunk_vsm_addressing.js";
9
+ import { VSM_DEMAND_SETTINGS_STRUCT } from "./shader_vsm_demand.js";
10
+
11
+ export const VSM_GATHER_WORKGROUP_SIZE = 64;
12
+
13
+ const RECORD_TABLE = LIGHT_DATABASE_SPEC.get('shadow_virtual');
14
+ const L = VSM_FEEDBACK_LAYOUT;
15
+
16
+ const resources = new ShaderResourceSetDescriptor();
17
+
18
+ resources.setImmediate('settings', VSM_DEMAND_SETTINGS_STRUCT);
19
+
20
+ resources.createGroup()
21
+ .addStorageBuffer('light_database', WebGPUArray.from(u32), false)
22
+ .addStorageBuffer('counts', WebGPUArray.from(u32), false)
23
+ .addStorageBuffer('feedback', WebGPUArray.from(atomic_u32), true);
24
+
25
+ /**
26
+ * Write the pixels that asked for each listed page into its request, once {@link shader_vsm_demand}
27
+ * has run over every pixel: the counter of the page's cell, as it ended.
28
+ *
29
+ * One thread per request the feedback buffer can hold — a fixed dispatch of
30
+ * `ceil(request_capacity / 64)` workgroups, the listed ones doing the work.
31
+ *
32
+ * @type {ComputeShader}
33
+ */
34
+ export const shader_vsm_gather_counts = ComputeShader.from({
35
+ label: "VSM/GatherCounts",
36
+ body: CodeChunk.from(
37
+ //language=WGSL
38
+ `
39
+ @compute @workgroup_size(${VSM_GATHER_WORKGROUP_SIZE}, 1, 1)
40
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
41
+ let index = global_id.x;
42
+ let listed = min(atomicLoad(&feedback[${L.REQUEST_COUNT}u]), settings.request_capacity);
43
+
44
+ if (index >= listed) {
45
+ return;
46
+ }
47
+
48
+ let base = ${L.HEADER_WORDS}u + index * ${L.REQUEST_WORDS}u;
49
+
50
+ let level = atomicLoad(&feedback[base + ${L.REQUEST_LEVEL}u]);
51
+ let page = vec2i(
52
+ i32(atomicLoad(&feedback[base + ${L.REQUEST_X}u])),
53
+ i32(atomicLoad(&feedback[base + ${L.REQUEST_Y}u])),
54
+ );
55
+
56
+ let record = ${RECORD_TABLE.marshalling_method_read}(&light_database, settings.record_row);
57
+
58
+ atomicStore(&feedback[base + ${L.REQUEST_IMPORTANCE}u], counts[vsm_cell_index(record, page, level)]);
59
+ }
60
+ `, [
61
+ RECORD_TABLE.chunk_read,
62
+ chunk_vsm_addressing,
63
+ ]),
64
+ resources,
65
+ });
@@ -0,0 +1,30 @@
1
+ export const VSM_MOVERS_WORKGROUP_SIZE: number;
2
+ /**
3
+ * What the mover pass runs with: how many rows the "last seen" buffer covers, how many movers the
4
+ * list holds, and the dispatch's shape — `group_count` workgroups folded into rows of `groups_x`,
5
+ * since a table's pages can take more than one dimension of a dispatch holds.
6
+ *
7
+ * @type {WebGPUStruct}
8
+ */
9
+ export const VSM_MOVERS_SETTINGS_STRUCT: WebGPUStruct;
10
+ /**
11
+ * List the casters that moved since the last frame, for every virtual shadow map's stale pass.
12
+ *
13
+ * One thread per slot of the `meshes` table, freed pages included, against a buffer of what each
14
+ * row was when the pass last saw it ({@link VSM_LAST_SEEN_WORDS}). A row moved when its world matrix
15
+ * differs from the one the hierarchy pass kept from last frame, or when its world box, geometry or
16
+ * material differs from the one the pass saw — which is also how a row that appeared or left shows.
17
+ * A change to a material's parameters, the same material, is not seen. Nothing about a row is
18
+ * declared; what changed is observed. A mover is listed with the union of its box now and then:
19
+ * every page either one covers may hold its old shadow, or lack its new one.
20
+ *
21
+ * Dispatch with as many workgroups as the "last seen" buffer's rows need at
22
+ * {@link VSM_MOVERS_WORKGROUP_SIZE} — the table's pages, times its groups per page — folded into rows
23
+ * of at most a dispatch dimension's limit, and once per frame, before the stale passes.
24
+ *
25
+ * @type {ComputeShader}
26
+ */
27
+ export const shader_vsm_movers: ComputeShader;
28
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
29
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
30
+ //# sourceMappingURL=shader_vsm_movers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_vsm_movers.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.js"],"names":[],"mappings":"AAmBA,+CAA2E;AAE3E;;;;;;GAMG;AACH,yCAFU,YAAY,CAOE;AAiIxB;;;;;;;;;;;;;;;;GAgBG;AACH,gCAFU,aAAa,CAMpB;6BA9K0B,sCAAsC;8BALrC,kCAAkC"}
@@ -0,0 +1,184 @@
1
+ import { WebGPUExtensionType } from "../../../../descriptor/WebGPUExtensionType.js";
2
+ import { chunk_scene_database_access, MESHES_TABLE } from "../../../scene/chunk_scene_database_access.js";
3
+ import { COMPUTE_SHADER_DEFAULT_GROUP_SIZE } from "../../../shader/COMPUTE_SHADER_DEFAULT_GROUP_SIZE.js";
4
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { GPU_DATABASE_NULL } from "../../../buffer/table/GPU_DATABASE_NULL.js";
8
+ import { u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
9
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
10
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
11
+ import {
12
+ VSM_EMPTY_BOUND,
13
+ VSM_LAST_SEEN_GEOMETRY,
14
+ VSM_LAST_SEEN_MATERIAL,
15
+ VSM_LAST_SEEN_WORDS,
16
+ VSM_MOVERS_STRUCT
17
+ } from "../VSM_MOVER_LAYOUT.js";
18
+ import { chunk_vsm_append_mover } from "./chunk_vsm_append_mover.js";
19
+
20
+ export const VSM_MOVERS_WORKGROUP_SIZE = COMPUTE_SHADER_DEFAULT_GROUP_SIZE;
21
+
22
+ /**
23
+ * What the mover pass runs with: how many rows the "last seen" buffer covers, how many movers the
24
+ * list holds, and the dispatch's shape — `group_count` workgroups folded into rows of `groups_x`,
25
+ * since a table's pages can take more than one dimension of a dispatch holds.
26
+ *
27
+ * @type {WebGPUStruct}
28
+ */
29
+ export const VSM_MOVERS_SETTINGS_STRUCT = WebGPUStruct.from({
30
+ row_count: u32,
31
+ capacity: u32,
32
+ groups_x: u32,
33
+ group_count: u32,
34
+ }, "VSMMoversSettings");
35
+
36
+ const WG = VSM_MOVERS_WORKGROUP_SIZE;
37
+ const PG = MESHES_TABLE.page_iterator_symbol_prefix(WG);
38
+
39
+ const resources = new ShaderResourceSetDescriptor();
40
+
41
+ resources.setImmediate('settings', VSM_MOVERS_SETTINGS_STRUCT);
42
+
43
+ resources.createGroup()
44
+ .addStorageBuffer('scene_database', WebGPUArray.from(u32), false)
45
+ // per mesh row, what the pass saw it as last frame: its world box by the bits of its floats,
46
+ // then its geometry and material — empty and NULL for a row that held nothing
47
+ .addStorageBuffer('last_seen', WebGPUArray.from(u32), true)
48
+ .addStorageBuffer('movers', VSM_MOVERS_STRUCT, true);
49
+
50
+ const body = CodeChunk.from(
51
+ //language=WGSL
52
+ `
53
+ const EMPTY = ${VSM_EMPTY_BOUND};
54
+ const NO_MESH = ${GPU_DATABASE_NULL}u;
55
+ const WORDS = ${VSM_LAST_SEEN_WORDS}u;
56
+
57
+ @compute @workgroup_size(${WG},1,1)
58
+ fn main(
59
+ @builtin(workgroup_id) wg_id: vec3<u32>,
60
+ @builtin(local_invocation_index) local_id: u32,
61
+ ) {
62
+ // the dispatch's workgroups, folded into rows; the last row's tail past the count has nothing to
63
+ // walk, and leaves whole
64
+ let group_index = wg_id.x + wg_id.y * settings.groups_x;
65
+
66
+ if (group_index >= settings.group_count) {
67
+ return;
68
+ }
69
+
70
+ // the page iterator's own arithmetic, done here too: a page that has been freed is still walked,
71
+ // since the rows it held may have been casters a moment ago
72
+ let page_index = group_index / ${PG}_GROUPS_PER_PAGE;
73
+ let page_group = group_index % ${PG}_GROUPS_PER_PAGE;
74
+ let slot = page_group * ${WG}u + local_id;
75
+ let row = page_index * ${PG}_ELEMENTS_PER_PAGE + slot;
76
+
77
+ let tracked = slot < ${PG}_ELEMENTS_PER_PAGE && row < settings.row_count;
78
+
79
+ // the page address is uniform across the workgroup, so this is too
80
+ let allocated = ${PG}_setup(&scene_database, group_index, local_id);
81
+
82
+ var occupied = false;
83
+
84
+ if (allocated && slot < ${PG}_ELEMENTS_PER_PAGE) {
85
+ occupied = ${PG}_is_occupied(slot);
86
+ }
87
+
88
+ var now_min = vec3f(EMPTY);
89
+ var now_max = vec3f(-EMPTY);
90
+ var now_geometry = NO_MESH;
91
+ var now_material = NO_MESH;
92
+ var turned = false;
93
+
94
+ if (occupied) {
95
+ let mesh = ${PG}_read(&scene_database, slot);
96
+
97
+ now_geometry = mesh.geometry;
98
+ now_material = mesh.material;
99
+
100
+ now_min = vec3f(mesh.bounding_box[0], mesh.bounding_box[1], mesh.bounding_box[2]);
101
+ now_max = vec3f(mesh.bounding_box[3], mesh.bounding_box[4], mesh.bounding_box[5]);
102
+
103
+ // the hierarchy pass keeps last frame's world matrix beside this frame's: any change of the
104
+ // transform, including a turn that leaves the box where it was
105
+ let node = scene_read_node(&scene_database, mesh.node);
106
+
107
+ turned = any(node.global[0] != node.prev_global[0])
108
+ || any(node.global[1] != node.prev_global[1])
109
+ || any(node.global[2] != node.prev_global[2])
110
+ || any(node.global[3] != node.prev_global[3]);
111
+ }
112
+
113
+ var is_mover = false;
114
+ var box_min = now_min;
115
+ var box_max = now_max;
116
+
117
+ if (tracked) {
118
+ let base = row * WORDS;
119
+
120
+ let then_min = vec3f(
121
+ bitcast<f32>(last_seen[base]),
122
+ bitcast<f32>(last_seen[base + 1u]),
123
+ bitcast<f32>(last_seen[base + 2u]),
124
+ );
125
+ let then_max = vec3f(
126
+ bitcast<f32>(last_seen[base + 3u]),
127
+ bitcast<f32>(last_seen[base + 4u]),
128
+ bitcast<f32>(last_seen[base + 5u]),
129
+ );
130
+
131
+ // a row that appeared, left or changed shape has a box it did not have before; one given
132
+ // another mesh may keep its box, but not its geometry or material
133
+ let changed = any(now_min != then_min) || any(now_max != then_max)
134
+ || now_geometry != last_seen[base + ${VSM_LAST_SEEN_GEOMETRY}u]
135
+ || now_material != last_seen[base + ${VSM_LAST_SEEN_MATERIAL}u];
136
+
137
+ // where it is and where it was; an empty box is the identity of both
138
+ box_min = min(now_min, then_min);
139
+ box_max = max(now_max, then_max);
140
+
141
+ is_mover = (changed || turned) && all(box_min <= box_max);
142
+
143
+ last_seen[base] = bitcast<u32>(now_min.x);
144
+ last_seen[base + 1u] = bitcast<u32>(now_min.y);
145
+ last_seen[base + 2u] = bitcast<u32>(now_min.z);
146
+ last_seen[base + 3u] = bitcast<u32>(now_max.x);
147
+ last_seen[base + 4u] = bitcast<u32>(now_max.y);
148
+ last_seen[base + 5u] = bitcast<u32>(now_max.z);
149
+ last_seen[base + ${VSM_LAST_SEEN_GEOMETRY}u] = now_geometry;
150
+ last_seen[base + ${VSM_LAST_SEEN_MATERIAL}u] = now_material;
151
+ }
152
+
153
+ vsm_append_mover(is_mover, box_min, box_max, settings.capacity);
154
+ }
155
+ `, [
156
+ MESHES_TABLE.chunk_iterate(WG),
157
+ chunk_scene_database_access,
158
+ chunk_vsm_append_mover,
159
+ ]);
160
+
161
+ body.addExtension(WebGPUExtensionType.Subgroups);
162
+
163
+ /**
164
+ * List the casters that moved since the last frame, for every virtual shadow map's stale pass.
165
+ *
166
+ * One thread per slot of the `meshes` table, freed pages included, against a buffer of what each
167
+ * row was when the pass last saw it ({@link VSM_LAST_SEEN_WORDS}). A row moved when its world matrix
168
+ * differs from the one the hierarchy pass kept from last frame, or when its world box, geometry or
169
+ * material differs from the one the pass saw — which is also how a row that appeared or left shows.
170
+ * A change to a material's parameters, the same material, is not seen. Nothing about a row is
171
+ * declared; what changed is observed. A mover is listed with the union of its box now and then:
172
+ * every page either one covers may hold its old shadow, or lack its new one.
173
+ *
174
+ * Dispatch with as many workgroups as the "last seen" buffer's rows need at
175
+ * {@link VSM_MOVERS_WORKGROUP_SIZE} — the table's pages, times its groups per page — folded into rows
176
+ * of at most a dispatch dimension's limit, and once per frame, before the stale passes.
177
+ *
178
+ * @type {ComputeShader}
179
+ */
180
+ export const shader_vsm_movers = ComputeShader.from({
181
+ label: "VSM/Movers",
182
+ body,
183
+ resources,
184
+ });