@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,320 @@
1
+ import { Color } from "../../../core/color/Color.js";
2
+ import Quaternion from "../../../core/geom/Quaternion.js";
3
+ import Vector3 from "../../../core/geom/Vector3.js";
4
+ import { EntityComponentDataset } from "../../../engine/ecs/EntityComponentDataset.js";
5
+ import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
6
+ import { BoxGeometry } from "../../renderer/geometry/BoxGeometry.js";
7
+ import { MeshoptClusterizer } from "../../renderer/geometry/meshlet/build/meshoptimizer/meshopt_clusterizer.js";
8
+ import { make_sunlight } from "../../renderer/light/make_sunlight.js";
9
+ import { place_light } from "../../renderer/light/place_light.js";
10
+ import { StandardShadeMaterial } from "../../renderer/material/StandardShadeMaterial.js";
11
+ import { move_primitive, place_primitive, remove_primitive } from "../../renderer/scene/rows/place_primitive.js";
12
+ import { Scene } from "../../renderer/scene/Scene.js";
13
+ import { make_flat_environment } from "../skinned_blas_refit/flat_environment.js";
14
+
15
+ /**
16
+ * @typedef {import("../../renderer/Renderer.js").Renderer} Renderer
17
+ */
18
+
19
+ /**
20
+ * Scratch for {@link aim_sun}, which a sweep calls every frame.
21
+ */
22
+ const scratch_direction = new Vector3();
23
+ const scratch_rotation = new Quaternion();
24
+
25
+ /**
26
+ * Turn a sun to shine down at a fixed elevation, from an azimuth about the vertical.
27
+ *
28
+ * @param {import("../../renderer/light/model/DirectionalLight.js").DirectionalLight} sun
29
+ * @param {number} azimuth radians
30
+ */
31
+ export function aim_sun(sun, azimuth) {
32
+ scratch_direction.set(-Math.cos(azimuth) * 0.45, -0.95, -Math.sin(azimuth) * 0.45);
33
+ scratch_direction.normalize();
34
+
35
+ scratch_rotation.fromUnitVectors(Vector3.forward, scratch_direction);
36
+ scratch_rotation.normalize();
37
+
38
+ sun.transform.setRotation(scratch_rotation.x, scratch_rotation.y, scratch_rotation.z, scratch_rotation.w);
39
+ sun.transform.updateMatrix();
40
+ }
41
+
42
+ /**
43
+ * What both scenes share: a scene with a dataset, its context, a box geometry, a material maker,
44
+ * a box placer, a flat sky and a sun.
45
+ *
46
+ * @param {Renderer} renderer
47
+ */
48
+ async function scene_base(renderer) {
49
+ await MeshoptClusterizer.ready;
50
+
51
+ const scene = new Scene();
52
+
53
+ scene.dataset = new EntityComponentDataset();
54
+
55
+ const scene_context = renderer.scenes.obtain(scene);
56
+ const cube = new BoxGeometry();
57
+
58
+ /**
59
+ * @param {number[]} rgb
60
+ * @param {number} [roughness]
61
+ * @returns {StandardShadeMaterial}
62
+ */
63
+ const material = (rgb, roughness = 0.75) => {
64
+ const result = new StandardShadeMaterial();
65
+
66
+ result.diffuse_color.copy(new Color(...rgb));
67
+ result.roughness_factor = roughness;
68
+ result.metallic_factor = 0;
69
+
70
+ return result;
71
+ };
72
+
73
+ /**
74
+ * A box at an entity of its own; the transform stays the caller's to move.
75
+ *
76
+ * @param {string} name
77
+ * @param {number[]} position
78
+ * @param {number[]} scale
79
+ * @param {StandardShadeMaterial} mat
80
+ * @returns {{entity: number, transform: Transform64}}
81
+ */
82
+ const box = (name, position, scale, mat) => {
83
+ const transform = new Transform64();
84
+
85
+ transform.setTranslation(position[0], position[1], position[2]);
86
+ transform.setScale(scale[0], scale[1], scale[2]);
87
+ transform.updateMatrix();
88
+
89
+ return { entity: place_primitive(scene_context, cube, mat, transform, { name }), transform };
90
+ };
91
+
92
+ scene.lights.environment = make_flat_environment([0.06, 0.075, 0.1]);
93
+
94
+ const sun = make_sunlight({ intensity: 3, temperature: 5800 });
95
+
96
+ aim_sun(sun, 0.6);
97
+ place_light(scene, sun);
98
+
99
+ return { scene, scene_context, material, box, sun };
100
+ }
101
+
102
+ /**
103
+ * The courtyard: static structure at every scale a clipmap level covers, and casters that move in
104
+ * every way the mover pass has to see.
105
+ *
106
+ * - a fence of 5 cm slats by the camera for the finest levels, pillars and walls a few metres out,
107
+ * an overhang on posts, thin poles twenty metres off, and an avenue of pillars reaching two
108
+ * hundred metres down the coarser levels;
109
+ * - movers: boxes orbiting (a translation), a column bobbing (a translation along the light more or
110
+ * less), a bar turning about its centre (a rotation that keeps its centre still), and a block that
111
+ * blinks in and out of the scene every few seconds (a row appearing and leaving).
112
+ *
113
+ * @param {Renderer} renderer
114
+ */
115
+ export async function create_courtyard(renderer) {
116
+ const { scene, scene_context, material, box, sun } = await scene_base(renderer);
117
+
118
+ const ground = material([0.55, 0.53, 0.5], 0.9);
119
+ const stone = material([0.72, 0.68, 0.6]);
120
+ const dark = material([0.3, 0.32, 0.36]);
121
+ const wood = material([0.55, 0.38, 0.22]);
122
+
123
+ box('Ground', [0, -0.1, -60], [240, 0.2, 320], ground);
124
+
125
+ // a fence of slats by the camera: the finest levels' business
126
+ for (let i = 0; i < 40; i++) {
127
+ box('Slat', [-4 + i * 0.2, 0.6, 3], [0.05, 1.2, 0.05], wood);
128
+ }
129
+
130
+ box('Fence rail', [0, 1.15, 3], [8.2, 0.06, 0.06], wood);
131
+
132
+ // pillars and walls a few metres out
133
+ for (let x = -20; x <= 20; x += 8) {
134
+ for (let z = -20; z <= 4; z += 8) {
135
+ if (Math.abs(x) < 5 && Math.abs(z) < 5) {
136
+ continue;
137
+ }
138
+
139
+ // 4, 6 or 8 m tall; % keeps the sign of x + z, and a negative remainder made pillars of
140
+ // no height lying in the ground's top face
141
+ const step = ((x + z) % 3 + 3) % 3;
142
+
143
+ box('Pillar', [x, 2 + step, z], [0.6, 4 + 2 * step, 0.6], stone);
144
+ }
145
+ }
146
+
147
+ box('Wall', [-12, 1.5, -6], [0.4, 3, 12], stone);
148
+ box('Wall', [14, 1.25, -14], [10, 2.5, 0.4], stone);
149
+
150
+ // an overhang on four posts
151
+ for (const [x, z] of [[4, -8], [12, -8], [4, -2], [12, -2]]) {
152
+ box('Post', [x, 2, z], [0.3, 4, 0.3], dark);
153
+ }
154
+
155
+ box('Overhang', [8, 4.15, -5], [9, 0.3, 7], stone);
156
+
157
+ // thin poles twenty metres off
158
+ for (let i = 0; i < 16; i++) {
159
+ box('Pole', [-15 + i * 2, 2.5, -22], [0.05, 5, 0.05], dark);
160
+ }
161
+
162
+ // an avenue of pillars down the coarser levels
163
+ for (let z = -30; z >= -220; z -= 7) {
164
+ box('Avenue pillar', [-7, 3, z], [0.8, 6, 0.8], stone);
165
+ box('Avenue pillar', [7, 3, z], [0.8, 6, 0.8], stone);
166
+ }
167
+
168
+ const movers_material = material([0.85, 0.25, 0.15], 0.5);
169
+ const orbiters = [];
170
+
171
+ for (let i = 0; i < 4; i++) {
172
+ orbiters.push(box('Orbiter', [0, 1, 0], [1, 1, 1], movers_material));
173
+ }
174
+
175
+ const column = box('Bobbing column', [-6, 2, -10], [1, 3, 1], material([0.2, 0.55, 0.85], 0.5));
176
+ const bar = box('Turning bar', [0, 2.6, -12], [6, 0.25, 0.25], material([0.95, 0.75, 0.15], 0.5));
177
+
178
+ const blinker_material = material([0.6, 0.2, 0.8], 0.5);
179
+ const blinker_transform = new Transform64();
180
+
181
+ blinker_transform.setTranslation(16, 1.25, -2);
182
+ blinker_transform.setScale(2, 2.5, 2);
183
+ blinker_transform.updateMatrix();
184
+
185
+ const cube = new BoxGeometry();
186
+ let blinker = -1;
187
+
188
+ const rotation = new Quaternion();
189
+
190
+ return {
191
+ scene,
192
+ sun,
193
+ mover_count: orbiters.length + 3,
194
+
195
+ /**
196
+ * Put every mover where it is at time `t`.
197
+ *
198
+ * @param {number} t seconds
199
+ */
200
+ update(t) {
201
+ for (let i = 0; i < orbiters.length; i++) {
202
+ const a = t * 0.6 + i * Math.PI / 2;
203
+ const o = orbiters[i];
204
+
205
+ o.transform.setTranslation(Math.cos(a) * 6, 1.2 + Math.sin(t * 1.3 + i) * 0.8, Math.sin(a) * 6 - 6);
206
+ move_primitive(scene_context, o.entity, o.transform);
207
+ }
208
+
209
+ column.transform.setTranslation(-6, 2.5 + Math.sin(t * 0.9) * 2, -10);
210
+ move_primitive(scene_context, column.entity, column.transform);
211
+
212
+ rotation.fromAxisAngle(Vector3.up, t * 0.7);
213
+ bar.transform.setRotation(rotation.x, rotation.y, rotation.z, rotation.w);
214
+ move_primitive(scene_context, bar.entity, bar.transform);
215
+
216
+ // in for two seconds, out for two
217
+ const present = Math.floor(t / 2) % 2 === 0;
218
+
219
+ if (present && blinker === -1) {
220
+ blinker = place_primitive(scene_context, cube, blinker_material, blinker_transform, { name: 'Blinker' });
221
+ } else if (!present && blinker !== -1) {
222
+ remove_primitive(scene_context, blinker);
223
+ blinker = -1;
224
+ }
225
+ },
226
+ };
227
+ }
228
+
229
+ /**
230
+ * The crowd: a field of small boxes wandering, as many as asked for — past the mover list's capacity
231
+ * if that is the point — to load the stale pass and the page budget. {@link resize} adds walkers to
232
+ * the same scene or takes them away, which the mover pass sees as rows appearing and leaving.
233
+ *
234
+ * @param {Renderer} renderer
235
+ * @param {number} count
236
+ */
237
+ export async function create_crowd(renderer, count) {
238
+ const { scene, scene_context, material, box, sun } = await scene_base(renderer);
239
+
240
+ box('Ground', [0, -0.1, 0], [160, 0.2, 160], material([0.5, 0.52, 0.48], 0.9));
241
+
242
+ // a few fixed landmarks for scale
243
+ for (let i = 0; i < 8; i++) {
244
+ const a = i / 8 * Math.PI * 2;
245
+
246
+ box('Landmark', [Math.cos(a) * 40, 4, Math.sin(a) * 40], [2, 8, 2], material([0.7, 0.66, 0.6]));
247
+ }
248
+
249
+ const walker_material = material([0.85, 0.3, 0.2], 0.5);
250
+ const walkers = [];
251
+
252
+ // a fixed sequence of walkers, so a given count is always the same crowd
253
+ let seed = 12345;
254
+ const random = () => {
255
+ seed = (seed * 1664525 + 1013904223) >>> 0;
256
+ return seed / 4294967296;
257
+ };
258
+
259
+ /**
260
+ * Lay the walkers out on a square grid sized to their number.
261
+ */
262
+ const lay_out = () => {
263
+ const side = Math.ceil(Math.sqrt(walkers.length));
264
+ const spacing = Math.min(1.6, 70 / side);
265
+
266
+ for (let i = 0; i < walkers.length; i++) {
267
+ walkers[i].x = (i % side - side / 2) * spacing;
268
+ walkers[i].z = (Math.floor(i / side) - side / 2) * spacing;
269
+ }
270
+ };
271
+
272
+ /**
273
+ * Add walkers or take them away until there are `target`.
274
+ *
275
+ * @param {number} target
276
+ */
277
+ const resize = target => {
278
+ while (walkers.length > target) {
279
+ remove_primitive(scene_context, walkers.pop().entity);
280
+ }
281
+
282
+ while (walkers.length < target) {
283
+ walkers.push({
284
+ ...box('Walker', [0, 0.6, 0], [0.5, 1.2, 0.5], walker_material),
285
+ x: 0,
286
+ z: 0,
287
+ phase: random() * Math.PI * 2,
288
+ speed: 0.4 + random() * 0.8,
289
+ radius: 0.5 + random() * 1.5,
290
+ });
291
+ }
292
+
293
+ lay_out();
294
+ };
295
+
296
+ resize(count);
297
+
298
+ return {
299
+ scene,
300
+ sun,
301
+ resize,
302
+
303
+ get mover_count() {
304
+ return walkers.length;
305
+ },
306
+
307
+ /**
308
+ * @param {number} t seconds
309
+ */
310
+ update(t) {
311
+ for (let i = 0; i < walkers.length; i++) {
312
+ const w = walkers[i];
313
+ const a = t * w.speed + w.phase;
314
+
315
+ w.transform.setTranslation(w.x + Math.cos(a) * w.radius, 0.6, w.z + Math.sin(a * 1.3) * w.radius);
316
+ move_primitive(scene_context, w.entity, w.transform);
317
+ }
318
+ },
319
+ };
320
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Check a virtual shadow map against itself on the device: hold still, let the pages settle, then
3
+ * read the light database back from the GPU and compare what the shaders read with what the CPU
4
+ * believes, and with itself.
5
+ *
6
+ * 1. **Settles**: with nothing moving, a reading recorded after the scene stopped asks for pages,
7
+ * and leaves nothing uncovered and nothing waiting — a page refused a slot is waiting — within
8
+ * {@link SETTLE_FRAMES} frames.
9
+ * 2. **Rows**: every row the map claimed comes back.
10
+ * 3. **Record**: the map's `shadow_virtual` row names its runs and depth range.
11
+ * 4. **Page table**: every `shadow_virtual_page` row on the GPU equals the CPU's entry for its cell.
12
+ * 5. **Slots**: every `shadow_virtual_slot` row on the GPU names the page the CPU says the slot holds.
13
+ * 6. **Page to slot to page**: on the GPU alone, every resident entry's slot names a page whose cell
14
+ * is the entry's own.
15
+ * 7. **Windows**: every `shadow_virtual_level` row on the GPU is the CPU's window corner.
16
+ * 8. **One slot per page**: no world page is held by two slots.
17
+ *
18
+ * The caller holds the movers and the sun still across this, and holds page updates when asked —
19
+ * the readbacks span frames, and no page is drawn or given back between them and the comparison.
20
+ *
21
+ * @param {object} options
22
+ * @param {import("../../renderer/Renderer.js").Renderer} options.renderer
23
+ * @param {import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap|null} options.map
24
+ * @param {import("../../renderer/scene/Scene.js").Scene} options.scene
25
+ * @param {function(boolean): void} options.hold_pages stop or restart page updates
26
+ * @returns {Promise<{pass: boolean, checks: object[], stats: object}>}
27
+ */
28
+ export function verify_vsm({ renderer, map, scene, hold_pages }: {
29
+ renderer: import("../../renderer/Renderer.js").Renderer;
30
+ map: import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap | null;
31
+ scene: import("../../renderer/scene/Scene.js").Scene;
32
+ hold_pages: (arg0: boolean) => void;
33
+ }): Promise<{
34
+ pass: boolean;
35
+ checks: object[];
36
+ stats: object;
37
+ }>;
38
+ //# sourceMappingURL=verify_vsm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify_vsm.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/vsm/verify_vsm.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IANkE,QAAQ,EAA/D,OAAO,4BAA4B,EAAE,QAAQ;IAC0C,GAAG,EAA1F,OAAO,+CAA+C,EAAE,gBAAgB,GAAC,IAAI;IACtB,KAAK,EAA5D,OAAO,+BAA+B,EAAE,KAAK;IACZ,UAAU,SAAlC,OAAO,KAAG,IAAI;IACrB,QAAQ;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC,CAuPrE"}
@@ -0,0 +1,305 @@
1
+ import { VSM_READBACKS_IN_FLIGHT } from "../../renderer/shadow/vsm/graph_vsm_feedback.js";
2
+ import { VSM_SLOT_EMPTY } from "../../renderer/shadow/vsm/VSM_SLOT_STRUCT.js";
3
+ import { vt_entry_unpack } from "../../renderer/texture/virtual/VT_CONSTANTS.js";
4
+
5
+ /**
6
+ * Frames to wait, at most, for a still scene's pages to settle.
7
+ * @type {number}
8
+ */
9
+ const SETTLE_FRAMES = 240;
10
+
11
+ /**
12
+ * @returns {Promise<void>} after the next frame
13
+ */
14
+ function next_frame() {
15
+ return new Promise(resolve => requestAnimationFrame(() => resolve()));
16
+ }
17
+
18
+ /**
19
+ * Check a virtual shadow map against itself on the device: hold still, let the pages settle, then
20
+ * read the light database back from the GPU and compare what the shaders read with what the CPU
21
+ * believes, and with itself.
22
+ *
23
+ * 1. **Settles**: with nothing moving, a reading recorded after the scene stopped asks for pages,
24
+ * and leaves nothing uncovered and nothing waiting — a page refused a slot is waiting — within
25
+ * {@link SETTLE_FRAMES} frames.
26
+ * 2. **Rows**: every row the map claimed comes back.
27
+ * 3. **Record**: the map's `shadow_virtual` row names its runs and depth range.
28
+ * 4. **Page table**: every `shadow_virtual_page` row on the GPU equals the CPU's entry for its cell.
29
+ * 5. **Slots**: every `shadow_virtual_slot` row on the GPU names the page the CPU says the slot holds.
30
+ * 6. **Page to slot to page**: on the GPU alone, every resident entry's slot names a page whose cell
31
+ * is the entry's own.
32
+ * 7. **Windows**: every `shadow_virtual_level` row on the GPU is the CPU's window corner.
33
+ * 8. **One slot per page**: no world page is held by two slots.
34
+ *
35
+ * The caller holds the movers and the sun still across this, and holds page updates when asked —
36
+ * the readbacks span frames, and no page is drawn or given back between them and the comparison.
37
+ *
38
+ * @param {object} options
39
+ * @param {import("../../renderer/Renderer.js").Renderer} options.renderer
40
+ * @param {import("../../renderer/shadow/vsm/VirtualShadowMap.js").VirtualShadowMap|null} options.map
41
+ * @param {import("../../renderer/scene/Scene.js").Scene} options.scene
42
+ * @param {function(boolean): void} options.hold_pages stop or restart page updates
43
+ * @returns {Promise<{pass: boolean, checks: object[], stats: object}>}
44
+ */
45
+ export async function verify_vsm({ renderer, map, scene, hold_pages }) {
46
+ if (map === null) {
47
+ return { pass: false, checks: [{ name: 'map', pass: false, detail: 'no virtual shadow map — choose "Virtual shadow map"' }], stats: {} };
48
+ }
49
+
50
+ const manager = map.manager;
51
+ const checks = [];
52
+
53
+ // 1. settle, on readings recorded after the scene stopped: those in flight at the freeze land
54
+ // first, and the one after them was asked for still
55
+ const readings_at_freeze = manager.stats.readings_applied;
56
+
57
+ let settled_after = -1;
58
+
59
+ for (let i = 0; i < SETTLE_FRAMES; i++) {
60
+ await next_frame();
61
+
62
+ const s = manager.stats;
63
+
64
+ if (s.readings_applied > readings_at_freeze + VSM_READBACKS_IN_FLIGHT
65
+ && s.wants > 0
66
+ && s.uncovered === 0
67
+ && s.backlog === 0
68
+ && s.renders === 0) {
69
+ settled_after = i;
70
+ break;
71
+ }
72
+ }
73
+
74
+ const s = manager.stats;
75
+
76
+ checks.push({
77
+ name: 'settles',
78
+ pass: settled_after !== -1,
79
+ detail: settled_after !== -1
80
+ ? `${s.wants} pages wanted, nothing uncovered or waiting after ${settled_after + 1} frames`
81
+ : s.wants === 0
82
+ ? 'the readings ask for no page: point the camera at something the sun lights'
83
+ : `after ${SETTLE_FRAMES} frames, ${s.backlog} waiting (${s.refused} refused so far) and ${s.uncovered} uncovered`,
84
+ });
85
+
86
+ // 2–8. what the GPU holds, read with page updates held so that nothing changes on either side
87
+ // while the readbacks are on their way
88
+ hold_pages(true);
89
+
90
+ const database = renderer.scenes.obtain(scene).lights.database;
91
+
92
+ let records;
93
+ let pages;
94
+ let slots;
95
+ let levels;
96
+
97
+ try {
98
+ // a frame with the hold in place, so that whatever the last one wrote has gone up
99
+ await next_frame();
100
+
101
+ [records, pages, slots, levels] = await Promise.all([
102
+ database.debug_table_read_all('shadow_virtual'),
103
+ database.debug_table_read_all('shadow_virtual_page'),
104
+ database.debug_table_read_all('shadow_virtual_slot'),
105
+ database.debug_table_read_all('shadow_virtual_level'),
106
+ ]);
107
+ } finally {
108
+ hold_pages(false);
109
+ }
110
+
111
+ // 2. every claimed row is there
112
+ const missing = [];
113
+
114
+ const count_missing = (rows, first, count, table) => {
115
+ let absent = 0;
116
+
117
+ for (let i = 0; i < count; i++) {
118
+ if (rows[first + i] === undefined) {
119
+ absent++;
120
+ }
121
+ }
122
+
123
+ if (absent > 0) {
124
+ missing.push(`${table}: ${absent} of ${count}`);
125
+ }
126
+ };
127
+
128
+ count_missing(records, map.record_row, 1, 'shadow_virtual');
129
+ count_missing(pages, map.first_page, manager.cell_count, 'shadow_virtual_page');
130
+ count_missing(slots, map.first_slot, manager.slots.capacity, 'shadow_virtual_slot');
131
+ count_missing(levels, map.first_level, manager.level_count, 'shadow_virtual_level');
132
+
133
+ checks.push({
134
+ name: 'rows',
135
+ pass: missing.length === 0,
136
+ detail: missing.length === 0 ? 'every row the map claimed came back' : `missing ${missing.join(', ')}`,
137
+ });
138
+
139
+ if (missing.length > 0) {
140
+ return finish(checks, manager);
141
+ }
142
+
143
+ // 3. the record
144
+ const record = records[map.record_row];
145
+ const record_faults = [];
146
+
147
+ const expect_field = (name, gpu, cpu) => {
148
+ if (gpu !== cpu) {
149
+ record_faults.push(`${name}: gpu ${gpu} cpu ${cpu}`);
150
+ }
151
+ };
152
+
153
+ expect_field('first_page', record.first_page, map.first_page);
154
+ expect_field('page_count', record.page_count, manager.cell_count);
155
+ expect_field('first_slot', record.first_slot, map.first_slot);
156
+ expect_field('slot_count', record.slot_count, manager.slots.capacity);
157
+ expect_field('first_level', record.first_level, map.first_level);
158
+ expect_field('level_count', record.level_count, manager.level_count);
159
+ expect_field('near', record.near, Math.fround(map.near));
160
+ expect_field('far', record.far, Math.fround(map.far));
161
+
162
+ checks.push({
163
+ name: 'record',
164
+ pass: record_faults.length === 0,
165
+ detail: record_faults.length === 0 ? 'runs and depth range agree' : record_faults.join('; '),
166
+ });
167
+
168
+ // 4. the page table
169
+ let page_mismatches = 0;
170
+ let first_page_mismatch = '';
171
+
172
+ for (let cell = 0; cell < manager.cell_count; cell++) {
173
+ const gpu = pages[map.first_page + cell];
174
+ const cpu = manager.cell_entry(cell);
175
+
176
+ if (gpu !== cpu) {
177
+ if (page_mismatches === 0) {
178
+ first_page_mismatch = `cell ${cell}: gpu ${gpu} cpu ${cpu}`;
179
+ }
180
+
181
+ page_mismatches++;
182
+ }
183
+ }
184
+
185
+ checks.push({
186
+ name: 'page table',
187
+ pass: page_mismatches === 0,
188
+ detail: page_mismatches === 0 ? `${manager.cell_count} entries agree` : `${page_mismatches} differ, first ${first_page_mismatch}`,
189
+ });
190
+
191
+ // 5, 8. the slots, and no page twice
192
+ let slot_mismatches = 0;
193
+ const held = new Set();
194
+ let doubled = 0;
195
+
196
+ for (let slot = 0; slot < manager.slots.capacity; slot++) {
197
+ const gpu = slots[map.first_slot + slot];
198
+ const level = manager.slot_level(slot);
199
+
200
+ if (level === -1) {
201
+ if (gpu.level !== VSM_SLOT_EMPTY) {
202
+ slot_mismatches++;
203
+ }
204
+
205
+ continue;
206
+ }
207
+
208
+ if (gpu.level !== level || gpu.x !== manager.slot_x(slot) || gpu.y !== manager.slot_y(slot)) {
209
+ slot_mismatches++;
210
+ }
211
+
212
+ const key = `${level}:${manager.slot_x(slot)},${manager.slot_y(slot)}`;
213
+
214
+ if (held.has(key)) {
215
+ doubled++;
216
+ }
217
+
218
+ held.add(key);
219
+ }
220
+
221
+ checks.push({
222
+ name: 'slots',
223
+ pass: slot_mismatches === 0,
224
+ detail: `${slot_mismatches} of ${manager.slots.capacity} differ`,
225
+ });
226
+
227
+ // 6. the GPU's rows against each other: an entry's slot holds a page of the entry's own cell
228
+ const slots_per_axis = manager.slots.slots_per_axis;
229
+
230
+ let resident_entries = 0;
231
+ let broken_links = 0;
232
+ let first_broken = '';
233
+
234
+ for (let cell = 0; cell < manager.cell_count; cell++) {
235
+ const entry = vt_entry_unpack(pages[map.first_page + cell]);
236
+
237
+ if (!entry.valid) {
238
+ continue;
239
+ }
240
+
241
+ resident_entries++;
242
+
243
+ const slot = entry.phys_y * slots_per_axis + entry.phys_x;
244
+ const page = slots[map.first_slot + slot];
245
+
246
+ const linked = page !== undefined
247
+ && page.level === entry.mip
248
+ && manager.window_contains(page.level, page.x, page.y)
249
+ && manager.cell_of(page.level, page.x, page.y) === cell;
250
+
251
+ if (!linked) {
252
+ if (broken_links === 0) {
253
+ first_broken = `cell ${cell} → slot ${slot} → ${page === undefined ? 'nothing' : `${page.level}:${page.x},${page.y}`}`;
254
+ }
255
+
256
+ broken_links++;
257
+ }
258
+ }
259
+
260
+ checks.push({
261
+ name: 'page to slot to page',
262
+ pass: broken_links === 0,
263
+ detail: broken_links === 0 ? `${resident_entries} resident entries link back` : `${broken_links} do not, first ${first_broken}`,
264
+ });
265
+
266
+ checks.push({
267
+ name: 'one slot per page',
268
+ pass: doubled === 0,
269
+ detail: `${held.size} pages held, ${doubled} twice`,
270
+ });
271
+
272
+ // 7. the windows
273
+ let level_mismatches = 0;
274
+
275
+ for (let level = 0; level < manager.level_count; level++) {
276
+ const corner = levels[map.first_level + level];
277
+
278
+ if (corner[0] !== manager.origin_x(level) || corner[1] !== manager.origin_y(level)) {
279
+ level_mismatches++;
280
+ }
281
+ }
282
+
283
+ checks.push({
284
+ name: 'windows',
285
+ pass: level_mismatches === 0,
286
+ detail: `${level_mismatches} of ${manager.level_count} differ`,
287
+ });
288
+
289
+ return finish(checks, manager);
290
+ }
291
+
292
+ /**
293
+ * @param {object[]} checks
294
+ * @param {import("../../renderer/shadow/vsm/VSMPageManager.js").VSMPageManager} manager
295
+ * @returns {{pass: boolean, checks: object[], stats: object}}
296
+ */
297
+ function finish(checks, manager) {
298
+ console.table(checks);
299
+
300
+ return {
301
+ pass: checks.every(c => c.pass),
302
+ checks,
303
+ stats: { ...manager.stats, resident: manager.slots.used },
304
+ };
305
+ }