@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,351 @@
1
+ import { CAMERA_UNIFORM_STRUCT } from "../../renderer/camera/CAMERA_UNIFORM_STRUCT.js";
2
+ import { DEPTH_BACKGROUND_VALUE } from "../../renderer/depth/DEPTH_BACKGROUND_VALUE.js";
3
+ import { FramePhase } from "../../renderer/extension/FramePhase.js";
4
+ import { RenderExtension } from "../../renderer/extension/RenderExtension.js";
5
+ import { SceneColor } from "../../renderer/extension/SceneColor.js";
6
+ import { ViewTextures } from "../../renderer/extension/ViewTextures.js";
7
+ import { LIGHT_DATABASE_SPEC } from "../../renderer/light/LIGHT_DATABASE_SPEC.js";
8
+ import { chunk_project_position_from_depth } from "../../renderer/shader/chunk/camera/chunk_project_position_from_depth.js";
9
+ import { chunk_u32_to_hash_color } from "../../renderer/shader/chunk/color/chunk_u32_to_hash_color.js";
10
+ import { chunk_lut_turbo } from "../../renderer/shader/chunk/color/lut/chunk_lut_turbo.js";
11
+ import { CodeChunk } from "../../renderer/shader/compiler/CodeChunk.js";
12
+ import { graph_image_pass } from "../../renderer/shader/graph/graph_image_pass.js";
13
+ import { graph_import_texture } from "../../renderer/shader/graph/graph_import_texture.js";
14
+ import { ImageShader } from "../../renderer/shader/ImageShader.js";
15
+ import { ShaderResourceSetDescriptor } from "../../renderer/shader/resource/ShaderResourceSetDescriptor.js";
16
+ import { ShaderDescriptor } from "../../renderer/shader/ShaderDescriptor.js";
17
+ import { u32 } from "../../renderer/shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
18
+ import { WebGPUArray } from "../../renderer/shader/type/WebGPUArray.js";
19
+ import { WebGPUStruct } from "../../renderer/shader/type/WebGPUStruct.js";
20
+ import { chunk_vsm_find_page } from "../../renderer/shadow/vsm/shader/chunk_vsm_find_page.js";
21
+ import { VSM_RECORD_STRUCT } from "../../renderer/shadow/vsm/VSM_RECORD_STRUCT.js";
22
+ import { VSM_SLOT_EMPTY } from "../../renderer/shadow/vsm/VSM_SLOT_STRUCT.js";
23
+
24
+ /**
25
+ * What the overlay shows over the picture.
26
+ * @enum {number}
27
+ */
28
+ export const VSMDebugView = {
29
+ None: 0,
30
+ /** the level of the page each pixel is shadowed by */
31
+ ServingLevel: 1,
32
+ /** how many levels coarser than it asked for the page a pixel is shadowed by is */
33
+ Deficit: 2,
34
+ /** the page each pixel is shadowed by, a colour per page, its edges drawn */
35
+ Pages: 3,
36
+ };
37
+
38
+ const RECORD_TABLE = LIGHT_DATABASE_SPEC.get('shadow_virtual');
39
+ const SLOT_TABLE = LIGHT_DATABASE_SPEC.get('shadow_virtual_slot');
40
+
41
+ const SETTINGS = WebGPUStruct.from({
42
+ record_row: u32,
43
+ mode: u32,
44
+ inset: u32,
45
+ output_width: u32,
46
+ output_height: u32,
47
+ }, "VSMDebugSettings");
48
+
49
+ const resources = new ShaderResourceSetDescriptor();
50
+
51
+ resources.setImmediate('settings', SETTINGS);
52
+
53
+ resources.createGroup()
54
+ .addTexture('tScene', 'unfilterable-float')
55
+ .addTexture('tDepth', 'depth')
56
+ .addTexture('tAtlas', 'depth')
57
+ .addUniform('camera', CAMERA_UNIFORM_STRUCT)
58
+ .addStorageBuffer('light_database', WebGPUArray.from(u32), false)
59
+ .addStorageBuffer('slot_stale', WebGPUArray.from(u32), false);
60
+
61
+ const shader_vsm_debug = new ImageShader({
62
+ descriptor: ShaderDescriptor.from({
63
+ label: "playground/vsm debug overlay",
64
+ resources,
65
+ body: CodeChunk.from(
66
+ //language=WGSL
67
+ `
68
+ fn vsm_debug_level_color(level: u32) -> vec3f {
69
+ // the finest level red, coarser through the spectrum to violet
70
+ return turbo(1.0 - f32(level) / 11.0);
71
+ }
72
+
73
+ fn vsm_debug_inset(coord: vec2f, record: ${VSM_RECORD_STRUCT.wgsl_ref}) -> vec4f {
74
+ let output_size = vec2f(f32(settings.output_width), f32(settings.output_height));
75
+ let side = floor(output_size.y * 0.42);
76
+ // bottom left, clear of the page's side panel
77
+ let origin = vec2f(12.0, output_size.y - side - 12.0);
78
+
79
+ let local = coord - origin;
80
+
81
+ if (any(local < vec2f(0.0)) || any(local >= vec2f(side))) {
82
+ return vec4f(-1.0);
83
+ }
84
+
85
+ let slot_size = f32(record.page_size + 2u * record.border);
86
+ let pool_size = f32(record.slots_per_axis) * slot_size;
87
+
88
+ let pool_texel = local / side * pool_size;
89
+ let slot_xy = vec2u(pool_texel / slot_size);
90
+ let slot = slot_xy.y * record.slots_per_axis + slot_xy.x;
91
+
92
+ let depth = textureLoad(tAtlas, vec2u(pool_texel) + record.pool_origin, 0);
93
+
94
+ // the depth range is wide, so the stored depth barely varies across a page: band the depth along
95
+ // the light in metres instead, a band every two
96
+ let metres = record.far - depth * (record.far - record.near);
97
+ var colour = select(vec3f(0.02), turbo(fract(metres * 0.5)) * 0.8, depth > 0.0);
98
+
99
+ // a stale slot washed red all over, so it reads apart from the finest level's dark red edge
100
+ let stale = slot_stale[slot] != 0u;
101
+
102
+ if (stale) {
103
+ colour = mix(colour, vec3f(1.0, 0.1, 0.1), 0.65);
104
+ }
105
+
106
+ // the slot grid, an inset pixel and a half wide, tinted by what the slot holds
107
+ let in_slot = pool_texel - vec2f(slot_xy) * slot_size;
108
+ let edge = min(min(in_slot.x, in_slot.y), min(slot_size - in_slot.x, slot_size - in_slot.y));
109
+
110
+ if (edge < pool_size / side * 1.5) {
111
+ let held = ${SLOT_TABLE.marshalling_method_read}(&light_database, record.first_slot + slot);
112
+
113
+ if (held.level == ${VSM_SLOT_EMPTY}u) {
114
+ colour = vec3f(0.12);
115
+ } else if (stale) {
116
+ colour = vec3f(1.0, 0.1, 0.1);
117
+ } else {
118
+ colour = vsm_debug_level_color(held.level);
119
+ }
120
+ }
121
+
122
+ return vec4f(colour, 1.0);
123
+ }
124
+
125
+ @fragment
126
+ fn main(@builtin(position) coord: vec4f) -> @location(0) vec4f {
127
+ let pixel = vec2u(coord.xy);
128
+ let scene = textureLoad(tScene, pixel, 0);
129
+
130
+ let record = ${RECORD_TABLE.marshalling_method_read}(&light_database, settings.record_row);
131
+
132
+ if (settings.inset != 0u) {
133
+ let inset = vsm_debug_inset(coord.xy, record);
134
+
135
+ if (inset.a > 0.0) {
136
+ return inset;
137
+ }
138
+ }
139
+
140
+ if (settings.mode == 0u) {
141
+ return scene;
142
+ }
143
+
144
+ let output_size = vec2f(f32(settings.output_width), f32(settings.output_height));
145
+ let uv = coord.xy / output_size;
146
+
147
+ let depth_size = textureDimensions(tDepth);
148
+ let depth_pixel = min(vec2u(uv * vec2f(depth_size)), depth_size - 1u);
149
+ let z = textureLoad(tDepth, depth_pixel, 0);
150
+
151
+ if (z == ${DEPTH_BACKGROUND_VALUE}) {
152
+ return scene;
153
+ }
154
+
155
+ let position = project_position_from_depth(uv, z, camera.view_projection_matrix_inverse);
156
+
157
+ let wanted = vsm_request_page(&light_database, record, position);
158
+ let found = vsm_find_resident_page(&light_database, record, position);
159
+
160
+ // nothing stands in at all: magenta
161
+ var tint = vec3f(1.0, 0.0, 1.0);
162
+
163
+ if (found.level != VSM_LEVEL_NONE) {
164
+ if (settings.mode == ${VSMDebugView.ServingLevel}u) {
165
+ tint = vsm_debug_level_color(found.level);
166
+ } else if (settings.mode == ${VSMDebugView.Deficit}u) {
167
+ let deficit = found.level - min(found.level, wanted.level);
168
+
169
+ tint = select(
170
+ select(select(vec3f(1.0, 0.1, 0.05), vec3f(1.0, 0.5, 0.0), deficit < 3u), vec3f(1.0, 0.95, 0.1), deficit < 2u),
171
+ vec3f(0.1, 0.9, 0.2),
172
+ deficit == 0u
173
+ );
174
+ } else {
175
+ tint = u32_to_hash_color(found.level * 7919u + bitcast<u32>(found.page.x) * 104729u + bitcast<u32>(found.page.y));
176
+
177
+ // the page's edges, a texel and a half wide at its own resolution
178
+ let light_space = vsm_light_space(record, position);
179
+ let in_page = fract(light_space.xy / vsm_page_world_size(record, found.level)) * f32(record.page_size);
180
+ let edge = min(min(in_page.x, in_page.y), min(f32(record.page_size) - in_page.x, f32(record.page_size) - in_page.y));
181
+
182
+ if (edge < 1.5) {
183
+ tint = vec3f(0.0);
184
+ }
185
+ }
186
+ }
187
+
188
+ // modulated by the picture, so the shadows stay readable under the tint
189
+ let luminance = dot(scene.rgb, vec3f(0.2126, 0.7152, 0.0722));
190
+
191
+ return vec4f(tint * (0.15 + luminance), scene.a);
192
+ }
193
+ `,
194
+ [
195
+ CAMERA_UNIFORM_STRUCT.declaration_chunk,
196
+ RECORD_TABLE.chunk_read,
197
+ SLOT_TABLE.chunk_read,
198
+ chunk_project_position_from_depth,
199
+ chunk_vsm_find_page,
200
+ chunk_lut_turbo,
201
+ chunk_u32_to_hash_color,
202
+ ]
203
+ ),
204
+ }),
205
+ targets: [
206
+ {
207
+ label: "vsm debug",
208
+ format: "rgba16float",
209
+ }
210
+ ],
211
+ });
212
+
213
+ /**
214
+ * The playground's view into a virtual shadow map, drawn over the frame before it is presented:
215
+ * a tint per pixel saying what shadows it ({@link VSMDebugView}), and an inset of the physical pool
216
+ * — every slot's depth, its edge tinted by its page's level, washed red where the page manager holds
217
+ * it stale (a mover crossed it and it has not been drawn since), its edge grey where it is empty.
218
+ *
219
+ * The tint runs the lighting's own page lookup on the frame's light database rows, so the page it
220
+ * names for a pixel is the page the lighting samples there. The stale state is the CPU's, uploaded
221
+ * each frame the inset is drawn.
222
+ */
223
+ export class VSMDebugOverlay extends RenderExtension {
224
+ name = 'playground/vsm debug overlay';
225
+ phase = FramePhase.BeforePresent;
226
+ relative_order = 1000;
227
+
228
+ /**
229
+ * @type {number} a {@link VSMDebugView}
230
+ */
231
+ mode = VSMDebugView.None;
232
+
233
+ /**
234
+ * Whether to draw the pool inset.
235
+ * @type {boolean}
236
+ */
237
+ inset = false;
238
+
239
+ /**
240
+ * The map to show; the overlay draws nothing without one.
241
+ * @type {import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap|null}
242
+ */
243
+ map = null;
244
+
245
+ /**
246
+ * The shadow context whose atlas the map's pool is in.
247
+ * @type {import("../../renderer/shadow/map/GPUSceneShadowmapContext.js").GPUSceneShadowmapContext|null}
248
+ */
249
+ shadows = null;
250
+
251
+ /**
252
+ * @type {import("../../renderer/GraphicsContext.js").GraphicsContext}
253
+ */
254
+ #graphics;
255
+
256
+ /**
257
+ * The page manager's stale state, a word per slot, and the buffer the inset reads it from.
258
+ */
259
+ #stale_words = new Uint32Array(0);
260
+ #stale_buffer = null;
261
+
262
+ /**
263
+ * @param {import("../../renderer/GraphicsContext.js").GraphicsContext} graphics
264
+ */
265
+ constructor(graphics) {
266
+ super();
267
+
268
+ this.#graphics = graphics;
269
+ }
270
+
271
+ /**
272
+ * Upload which slots the page manager holds stale.
273
+ *
274
+ * @param {import("../../renderer/shadow/vsm/VSMPageManager.js").VSMPageManager} manager
275
+ * @returns {GPUBuffer}
276
+ */
277
+ #upload_stale(manager) {
278
+ const count = manager.slots.capacity;
279
+ const device = this.#graphics.device;
280
+
281
+ if (this.#stale_words.length !== count) {
282
+ this.#stale_buffer?.destroy();
283
+
284
+ this.#stale_words = new Uint32Array(count);
285
+ this.#stale_buffer = device.createBuffer({
286
+ label: 'playground/vsm debug / slot stale',
287
+ size: count * Uint32Array.BYTES_PER_ELEMENT,
288
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
289
+ });
290
+ }
291
+
292
+ const words = this.#stale_words;
293
+
294
+ for (let slot = 0; slot < count; slot++) {
295
+ words[slot] = manager.slot_stale(slot) ? 1 : 0;
296
+ }
297
+
298
+ // queued ahead of the frame's commands, behind the last frame's
299
+ device.queue.writeBuffer(this.#stale_buffer, 0, words);
300
+
301
+ return this.#stale_buffer;
302
+ }
303
+
304
+ /**
305
+ * @param {import("../../renderer/extension/FrameContext.js").FrameContext} frame
306
+ */
307
+ record(frame) {
308
+ const map = this.map;
309
+
310
+ if (map === null || map.destroyed || map.record_row === -1) {
311
+ return;
312
+ }
313
+
314
+ if (this.mode === VSMDebugView.None && !this.inset) {
315
+ return;
316
+ }
317
+
318
+ const graph = frame.graph;
319
+ const view = frame.view;
320
+ const resolution = frame.resolution;
321
+
322
+ const [output] = graph_image_pass({
323
+ graph,
324
+ shader: shader_vsm_debug,
325
+ inputs: {
326
+ settings: {
327
+ record_row: map.record_row,
328
+ mode: this.mode,
329
+ inset: this.inset ? 1 : 0,
330
+ output_width: resolution[0],
331
+ output_height: resolution[1],
332
+ },
333
+ tScene: frame.get(SceneColor).color,
334
+ tDepth: frame.get(ViewTextures).depth,
335
+ tAtlas: graph_import_texture(graph, this.shadows.texture, 'vsm debug / atlas'),
336
+ camera: view.camera.gpu_buffer,
337
+ light_database: view.scene.lights.database.buffer,
338
+ slot_stale: this.#upload_stale(map.manager),
339
+ },
340
+ output_resolution: resolution,
341
+ });
342
+
343
+ frame.get(SceneColor).color = output;
344
+ }
345
+
346
+ destroy() {
347
+ this.#stale_buffer?.destroy();
348
+ this.#stale_buffer = null;
349
+ this.#stale_words = new Uint32Array(0);
350
+ }
351
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @param {HTMLCanvasElement} canvas
3
+ * @param {import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap} map
4
+ * @param {number[]} camera_position world
5
+ * @param {number} only one level to draw alone, or -1 for every level side by side
6
+ */
7
+ export function draw_clipmap_panel(canvas: HTMLCanvasElement, map: import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap, camera_position: number[], only: number): void;
8
+ //# sourceMappingURL=clipmap_panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipmap_panel.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/vsm/clipmap_panel.js"],"names":[],"mappings":"AA2BA;;;;;GAKG;AACH,2CALW,iBAAiB,OACjB,OAAO,+CAA+C,EAAE,gBAAgB,mBACxE,MAAM,EAAE,QACR,MAAM,QA0GhB"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * A picture of a virtual shadow map's clipmap, from the CPU's side of it: one panel per level, one
3
+ * pixel per page of the level's window, in world order with light-space y up.
4
+ *
5
+ * - dark: nothing resident
6
+ * - green: resident; white: rendered this frame
7
+ * - red: resident and stale — a mover crossed it since it was drawn
8
+ * - amber: wanted by the latest reading and missing
9
+ * - a cyan cross: the page the camera stands over
10
+ *
11
+ * Every number comes from the page manager's public accessors, so what it shows is what the CPU
12
+ * believes; the page table the GPU reads is written from the same state.
13
+ */
14
+
15
+ /** Gap between panels, in cells. */
16
+ const GAP = 2;
17
+
18
+ /** Panels per row. */
19
+ const COLUMNS = 4;
20
+
21
+ const COLOR_EMPTY = [16, 20, 24];
22
+ const COLOR_RESIDENT = [46, 130, 66];
23
+ const COLOR_RENDERED = [235, 255, 235];
24
+ const COLOR_STALE = [225, 60, 40];
25
+ const COLOR_WANTED = [215, 170, 40];
26
+ const COLOR_CAMERA = [80, 220, 255];
27
+
28
+ /**
29
+ * @param {HTMLCanvasElement} canvas
30
+ * @param {import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap} map
31
+ * @param {number[]} camera_position world
32
+ * @param {number} only one level to draw alone, or -1 for every level side by side
33
+ */
34
+ export function draw_clipmap_panel(canvas, map, camera_position, only) {
35
+ const manager = map.manager;
36
+ const n = manager.pages_per_level;
37
+ const levels = manager.level_count;
38
+ const columns = only === -1 ? COLUMNS : 1;
39
+ const rows = only === -1 ? Math.ceil(levels / COLUMNS) : 1;
40
+
41
+ const width = columns * (n + GAP) - GAP;
42
+ const height = rows * (n + GAP) - GAP;
43
+
44
+ if (canvas.width !== width || canvas.height !== height) {
45
+ canvas.width = width;
46
+ canvas.height = height;
47
+ }
48
+
49
+ const context = canvas.getContext('2d');
50
+ const image = context.createImageData(width, height);
51
+ const pixels = image.data;
52
+
53
+ // what the latest reading wants, by cell
54
+ const wanted = new Uint8Array(manager.cell_count);
55
+
56
+ for (let i = 0; i < manager.want_count; i++) {
57
+ const level = manager.want_level(i);
58
+ const x = manager.want_x(i);
59
+ const y = manager.want_y(i);
60
+
61
+ if (manager.window_contains(level, x, y)) {
62
+ wanted[manager.cell_of(level, x, y)] = 1;
63
+ }
64
+ }
65
+
66
+ // the camera in light space
67
+ const view = map.light_camera.view_matrix;
68
+ const [cx, cy, cz] = camera_position;
69
+ const light_x = view[0] * cx + view[4] * cy + view[8] * cz + view[12];
70
+ const light_y = view[1] * cx + view[5] * cy + view[9] * cz + view[13];
71
+
72
+ const frame = map.frame_index;
73
+
74
+ const put = (px, py, rgb) => {
75
+ const o = (py * width + px) * 4;
76
+
77
+ pixels[o] = rgb[0];
78
+ pixels[o + 1] = rgb[1];
79
+ pixels[o + 2] = rgb[2];
80
+ pixels[o + 3] = 255;
81
+ };
82
+
83
+ for (let level = 0; level < levels; level++) {
84
+ if (only !== -1 && level !== only) {
85
+ continue;
86
+ }
87
+
88
+ const index = only === -1 ? level : 0;
89
+ const panel_x = (index % columns) * (n + GAP);
90
+ const panel_y = Math.floor(index / columns) * (n + GAP);
91
+
92
+ const origin_x = manager.origin_x(level);
93
+ const origin_y = manager.origin_y(level);
94
+
95
+ for (let j = 0; j < n; j++) {
96
+ for (let i = 0; i < n; i++) {
97
+ const cell = manager.cell_of(level, origin_x + i, origin_y + j);
98
+ const slot = manager.cell_slot(cell);
99
+
100
+ let rgb = COLOR_EMPTY;
101
+
102
+ if (slot !== -1) {
103
+ if (manager.slot_stale(slot)) {
104
+ rgb = COLOR_STALE;
105
+ } else if (manager.slot_rendered_frame(slot) === frame) {
106
+ rgb = COLOR_RENDERED;
107
+ } else {
108
+ rgb = COLOR_RESIDENT;
109
+ }
110
+ } else if (wanted[cell] !== 0) {
111
+ rgb = COLOR_WANTED;
112
+ }
113
+
114
+ // light-space y up
115
+ put(panel_x + i, panel_y + (n - 1 - j), rgb);
116
+ }
117
+ }
118
+
119
+ const size = manager.page_world_size(level);
120
+ const camera_i = Math.floor(light_x / size) - origin_x;
121
+ const camera_j = Math.floor(light_y / size) - origin_y;
122
+
123
+ for (let d = -2; d <= 2; d++) {
124
+ const i = camera_i + d;
125
+ const j = camera_j + d;
126
+
127
+ if (i >= 0 && i < n && camera_j >= 0 && camera_j < n) {
128
+ put(panel_x + i, panel_y + (n - 1 - camera_j), COLOR_CAMERA);
129
+ }
130
+
131
+ if (j >= 0 && j < n && camera_i >= 0 && camera_i < n) {
132
+ put(panel_x + camera_i, panel_y + (n - 1 - j), COLOR_CAMERA);
133
+ }
134
+ }
135
+ }
136
+
137
+ context.putImageData(image, 0, 0);
138
+ }
@@ -0,0 +1,170 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Meep — virtual shadow maps</title>
7
+ <style>
8
+ :root {
9
+ color-scheme: dark;
10
+ font: 13px/1.45 system-ui, sans-serif;
11
+ --panel: rgba(20, 25, 33, 0.92);
12
+ --line: #34404f;
13
+ --text: #e2e8f0;
14
+ --muted: #9aa8ba;
15
+ --pass: #8fd6a8;
16
+ --fail: #ff9a9a;
17
+ }
18
+
19
+ * { box-sizing: border-box; }
20
+
21
+ html, body { margin: 0; height: 100%; background: #0b0e13; color: var(--text); overflow: hidden; }
22
+
23
+ #view { position: fixed; inset: 0; width: 100vw; height: 100vh; display: block; }
24
+
25
+ #panel {
26
+ position: fixed; top: 12px; right: 12px; bottom: 12px; width: 300px;
27
+ overflow-y: auto; padding: 14px 16px;
28
+ background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
29
+ }
30
+
31
+ h1 { font-size: 16px; margin: 0 0 4px; font-weight: 600; }
32
+ h2 { font-size: 12px; margin: 14px 0 6px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
33
+ p.lead { margin: 0 0 8px; color: var(--muted); }
34
+
35
+ label { display: block; margin: 6px 0; }
36
+ label > span { display: flex; justify-content: space-between; color: var(--muted); font-size: 12px; margin-bottom: 2px; }
37
+ label.check { display: flex; gap: 8px; align-items: center; }
38
+
39
+ select, button { width: 100%; background: #232c39; border: 1px solid #45556a; color: inherit; border-radius: 4px; padding: 5px 6px; font: inherit; }
40
+ button { cursor: pointer; }
41
+ button:hover { background: #2f3b4d; }
42
+ input[type=range] { width: 100%; accent-color: #6fc3ff; }
43
+
44
+ .row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
45
+
46
+ #stats { font: 11px/1.5 ui-monospace, Consolas, monospace; white-space: pre-wrap; color: var(--text); margin: 6px 0 0; }
47
+ #status { font: 11px/1.5 ui-monospace, Consolas, monospace; white-space: pre-wrap; color: var(--pass); margin: 8px 0 0; }
48
+ #status.fail { color: var(--fail); }
49
+
50
+ #clipmap { width: 100%; image-rendering: pixelated; border: 1px solid var(--line); background: #000; display: block; }
51
+
52
+ .legend { font-size: 11px; color: var(--muted); }
53
+ .legend b { font-weight: 600; }
54
+ .swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 3px; vertical-align: -1px; }
55
+ </style>
56
+ </head>
57
+ <body tabindex="0">
58
+ <canvas id="view" tabindex="0" aria-label="Virtual shadow map scene"></canvas>
59
+ <div id="panel">
60
+ <h1>Virtual shadow maps</h1>
61
+ <p class="lead">A clipmap of pages around the camera, drawn as the view asks for them and as moving casters make them stale.</p>
62
+
63
+ <h2>Shadows</h2>
64
+ <label><span>Technique</span>
65
+ <select id="technique">
66
+ <option value="vsm" selected>Virtual shadow map</option>
67
+ <option value="csm">Cascades (A/B)</option>
68
+ </select>
69
+ </label>
70
+ <label><span>Page updates per frame <output id="budget-value">8</output></span>
71
+ <input id="budget" type="range" min="0" max="64" step="1" value="8">
72
+ </label>
73
+ <label><span>LOD bias (coarser →) <output id="bias-value">0.0</output></span>
74
+ <input id="bias" type="range" min="-2" max="3" step="0.5" value="0">
75
+ </label>
76
+ <label><span>Finest texel</span>
77
+ <select id="texel">
78
+ <option value="0.001">1 mm</option>
79
+ <option value="0.01" selected>1 cm</option>
80
+ <option value="0.02">2 cm</option>
81
+ <option value="0.04">4 cm</option>
82
+ </select>
83
+ </label>
84
+ <label class="check"><input id="pause" type="checkbox">Pause page updates (budget 0)</label>
85
+ <label class="check"><input id="taa" type="checkbox">TAA</label>
86
+
87
+ <h2>Scene</h2>
88
+ <label><span>Scene</span>
89
+ <select id="scene">
90
+ <option value="courtyard" selected>Courtyard</option>
91
+ <option value="crowd">Crowd</option>
92
+ </select>
93
+ </label>
94
+ <label><span>Crowd size <output id="crowd-value">500</output></span>
95
+ <input id="crowd" type="range" min="50" max="6000" step="50" value="500">
96
+ </label>
97
+ <label class="check"><input id="animate" type="checkbox" checked>Animate movers</label>
98
+ <label class="check"><input id="sweep" type="checkbox">Sweep the sun</label>
99
+ <label><span>Sweep speed (rad/s)</span>
100
+ <input id="sweep-speed" type="range" min="0.005" max="0.5" step="0.005" value="0.05">
101
+ </label>
102
+ <button id="nudge">Nudge the sun (invalidate)</button>
103
+
104
+ <h2>Camera</h2>
105
+ <div class="row">
106
+ <button id="preset-near">Near</button>
107
+ <button id="preset-overview">Over</button>
108
+ <button id="preset-avenue">Avenue</button>
109
+ <button id="preset-crowd">Crowd</button>
110
+ </div>
111
+
112
+ <h2>Debug</h2>
113
+ <label><span>Overlay</span>
114
+ <select id="debug">
115
+ <option value="0">None</option>
116
+ <option value="1">Serving level</option>
117
+ <option value="2">Resolution deficit</option>
118
+ <option value="3">Page IDs and edges</option>
119
+ </select>
120
+ </label>
121
+ <label class="check"><input id="inset" type="checkbox">Physical pool inset</label>
122
+ <label class="check"><input id="panel-on" type="checkbox" checked>Clipmap panel</label>
123
+ <label><span>Panel shows</span>
124
+ <select id="panel-level">
125
+ <option value="-1">All levels</option>
126
+ <option value="0">Level 0</option>
127
+ <option value="1">Level 1</option>
128
+ <option value="2">Level 2</option>
129
+ <option value="3">Level 3</option>
130
+ <option value="4">Level 4</option>
131
+ <option value="5">Level 5</option>
132
+ <option value="6">Level 6</option>
133
+ <option value="7">Level 7</option>
134
+ <option value="8">Level 8</option>
135
+ <option value="9">Level 9</option>
136
+ <option value="10">Level 10</option>
137
+ <option value="11">Level 11</option>
138
+ </select>
139
+ </label>
140
+ <canvas id="clipmap" width="262" height="196"></canvas>
141
+ <p class="legend">
142
+ <span class="swatch" style="background:#2e8242"></span>resident
143
+ <span class="swatch" style="background:#ebffeb"></span>rendered now
144
+ <span class="swatch" style="background:#e13c28"></span>stale
145
+ <span class="swatch" style="background:#d7aa28"></span>wanted, missing
146
+ <span class="swatch" style="background:#50dcff"></span>camera
147
+ <br>Levels left to right, top to bottom, finest first; light-space y up.
148
+ </p>
149
+ <p class="legend">
150
+ <b>Serving level</b>: red finest → violet coarsest. <b>Deficit</b>: green as asked, yellow one level coarser, orange two, red more; magenta nothing resident.
151
+ <b>Pool inset</b>: slot depth, edges by level, red edge = flagged stale on the GPU, grey = empty.
152
+ </p>
153
+
154
+ <h2>State</h2>
155
+ <pre id="stats"></pre>
156
+ <p id="status">Starting WebGPU…</p>
157
+ </div>
158
+ <script type="module">
159
+ import { start } from './main.js';
160
+
161
+ start().catch(error => {
162
+ const status = document.getElementById('status');
163
+
164
+ status.className = 'fail';
165
+ status.textContent = String(error?.message ?? error);
166
+ console.error(error);
167
+ });
168
+ </script>
169
+ </body>
170
+ </html>
@@ -0,0 +1,2 @@
1
+ export function start(): Promise<void>;
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/vsm/main.js"],"names":[],"mappings":"AAsCA,uCA8VC"}