@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.
- package/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +17 -4
- package/src/engine/asset/loaders/image/avif/threaded_image_encoder.js +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
- package/src/engine/graphics/ecs/water/Water.d.ts +14 -17
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +100 -110
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.js +36 -38
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts +6 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.d.ts.map +1 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_3_4.js +10 -0
- package/src/engine/graphics/ecs/water/WaterWaves.d.ts +3 -3
- package/src/engine/graphics/ecs/water/WaterWaves.js +46 -46
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_to_avif.js +8 -5
- package/src/engine/graphics3/WaterSystem.d.ts +21 -74
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +174 -367
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/format/image/avif/api/convert_to_rgba.d.ts +2 -2
- package/src/format/image/avif/api/convert_to_rgba.d.ts.map +1 -1
- package/src/format/image/avif/api/convert_to_rgba.js +10 -9
- package/src/format/image/avif/api/decode_avif.d.ts +2 -2
- package/src/format/image/avif/api/decode_avif.d.ts.map +1 -1
- package/src/format/image/avif/api/decode_avif.js +1 -1
- package/src/shade/playground/ssr_reprojection/README.md +111 -103
- package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +68 -68
- package/src/shade/playground/ssr_reprojection/index.html +80 -79
- package/src/shade/playground/ssr_reprojection/main.js +256 -247
- package/src/shade/playground/ssr_variance/capture.js +96 -96
- package/src/shade/playground/ssr_variance/reference.js +78 -78
- package/src/shade/playground/vsm/README.md +96 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.d.ts +49 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.d.ts.map +1 -0
- package/src/shade/playground/vsm/VSMDebugOverlay.js +351 -0
- package/src/shade/playground/vsm/clipmap_panel.d.ts +8 -0
- package/src/shade/playground/vsm/clipmap_panel.d.ts.map +1 -0
- package/src/shade/playground/vsm/clipmap_panel.js +138 -0
- package/src/shade/playground/vsm/index.html +170 -0
- package/src/shade/playground/vsm/main.d.ts +2 -0
- package/src/shade/playground/vsm/main.d.ts.map +1 -0
- package/src/shade/playground/vsm/main.js +389 -0
- package/src/shade/playground/vsm/scenes.d.ts +52 -0
- package/src/shade/playground/vsm/scenes.d.ts.map +1 -0
- package/src/shade/playground/vsm/scenes.js +320 -0
- package/src/shade/playground/vsm/verify_vsm.d.ts +38 -0
- package/src/shade/playground/vsm/verify_vsm.d.ts.map +1 -0
- package/src/shade/playground/vsm/verify_vsm.js +305 -0
- package/src/shade/playground/water_refraction/README.md +57 -9
- package/src/shade/playground/water_refraction/main.js +12 -3
- package/src/shade/playground/water_refraction/world.d.ts +1 -0
- package/src/shade/playground/water_refraction/world.d.ts.map +1 -1
- package/src/shade/playground/water_refraction/world.js +15 -5
- package/src/shade/renderer/Renderer.d.ts +19 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +72 -1
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +8 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +18 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +7 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -0
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts +3 -1
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +10 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_read_code.js +28 -0
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/serde/table_wgsl_gen_write_code.js +31 -1
- package/src/shade/renderer/geometry/MeshletGeometry.d.ts +3 -0
- package/src/shade/renderer/geometry/MeshletGeometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/MeshletGeometry.js +1 -0
- package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/light/LIGHT_DATABASE_SPEC.js +62 -4
- package/src/shade/renderer/light/environment/rgbe/parse_rgbe.d.ts +1 -1
- package/src/shade/renderer/light/environment/rgbe/parse_rgbe.js +2 -2
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts +2 -2
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/rgbe/rgbe_byte_to_rgb_half.js +6 -14
- package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/sh_exponential/chunk_sh_exp_workgroup_sum.js +5 -1
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/medium/ParticipatingMedium.d.ts +3 -0
- package/src/shade/renderer/medium/ParticipatingMedium.d.ts.map +1 -1
- package/src/shade/renderer/medium/ParticipatingMedium.js +7 -0
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/shader_autoexposure_build_histogram.js +5 -35
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts +12 -4
- package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/SSR.js +36 -8
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts +3 -0
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/SSR_DENOISE_TILE_SIZE.js +2 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts +8 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_denoise_tile_active.js +40 -0
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +150 -137
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts +3 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_classify.js +44 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts +5 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/shader_ssr_denoise_tile_dilate.js +35 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts +26 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/ssr/ssr_graph_denoise_tiles.js +42 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +1 -0
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +113 -105
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts +2 -0
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +177 -167
- package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/DEPTH_STENCIL_STATE_SHADOW.js +10 -0
- package/src/shade/renderer/rasterize/RasterizationJob.d.ts +1 -2
- package/src/shade/renderer/rasterize/RasterizationJob.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/RasterizationJob.js +1 -2
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +5 -6
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +5 -6
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +2 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +1 -1
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +11 -0
- package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/atmosphere/phase/jd/build_lut_fog_parameters_jendersie_deon.js +4 -5
- package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.js +1 -5
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts +30 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_importance.js +54 -0
- package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.d.ts.map +1 -1
- package/src/shade/renderer/shader/type/serde/read_gpu_typed_buffer.js +3 -2
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts +19 -0
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/DIRECTIONAL_SHADOWMAP_STRUCT.js +27 -0
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts +1 -0
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +4 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +54 -0
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +502 -10
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts +3 -2
- package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/Shadowmap.js +3 -2
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts +8 -0
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_sample_shadowmap_atlas_for_light.js +34 -3
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +3 -2
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +17 -2
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +137 -133
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts +15 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_FIRST_TEXEL_SIZE.js +14 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts +16 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_PAGE_BUDGET.js +15 -0
- package/src/shade/renderer/shadow/vsm/PLAN.md +440 -0
- package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +43 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts +42 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSMMoverTracker.js +153 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts +327 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSMPageManager.js +1408 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts +14 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_COVER_LEVEL_STEP.js +13 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts +63 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_FEEDBACK_LAYOUT.js +70 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts +11 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_LEVEL_LIMIT.js +10 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts +54 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.js +75 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts +23 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_RECORD_STRUCT.js +85 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts +16 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/VSM_SLOT_STRUCT.js +29 -0
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts +136 -25
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.d.ts.map +1 -1
- package/src/shade/renderer/shadow/vsm/VirtualShadowMap.js +282 -116
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts +39 -0
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/graph_vsm_feedback.js +289 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts +18 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_virtual.js +65 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts +17 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_addressing.js +75 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts +14 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.js +45 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts +17 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_find_page.js +100 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts +15 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_page_view_projection.js +47 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts +26 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_demand.js +156 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts +13 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_gather_counts.js +65 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts +30 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.js +184 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts +23 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.js +109 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts +56 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/shader_vsm_stale.js +211 -0
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts +1 -1
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/decode_typed_gpu_data.js +3 -13
- package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -1
- package/src/shade/renderer/texture/format/infer_format_from_parameters.js +2 -3
- package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
- package/src/shade/renderer/texture/texture_write_to_gpu.js +16 -16
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts +4 -90
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +6 -210
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts +119 -0
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.d.ts.map +1 -0
- package/src/shade/renderer/texture/virtual/VTPhysicalSlots.js +245 -0
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts +1 -1
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +3 -19
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts +13 -0
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.d.ts.map +1 -0
- package/src/shade/renderer/texture/virtual/chunk_vt_page_table_entry.js +34 -0
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +7 -2
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +49 -49
- package/src/shade/renderer/water/chunk_water_transport.js +3 -3
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +11 -25
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +64 -116
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts +1 -20
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/WATER_BODIES_STRUCT.js +10 -42
- package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts +3 -0
- package/src/shade/renderer/water/medium/chunk_water_bodies.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/chunk_water_bodies.js +3 -0
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts +1 -5
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/shader_water_bodies_derive.js +32 -30
- package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts +4 -0
- package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/shader_water_meshlets.js +69 -0
- package/src/shade/renderer/water/optics/chunk_water_inscatter.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_inscatter.js +124 -123
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +75 -74
- package/src/shade/renderer/water/shader_water.d.ts +1 -1
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +490 -406
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts +12 -85
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.js +128 -408
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts +6 -0
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.js +23 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts +9 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/chunk_water_tessellation.js +144 -0
- package/src/shade/renderer/water/surface/chunk_water_wave.d.ts +3 -5
- package/src/shade/renderer/water/surface/chunk_water_wave.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/chunk_water_wave.js +40 -48
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +14 -0
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +34 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.d.ts +4 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_tiles.js +123 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts +6 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_wave_batch.js +85 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts +6 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts.map +1 -0
- package/src/shade/renderer/water/surface/shader_water_wave_domain.js +83 -0
- package/src/shade/renderer/water/water_height_texture_from_sampler.d.ts.map +1 -1
- package/src/shade/renderer/water/water_height_texture_from_sampler.js +4 -3
- package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts +0 -2
- package/src/engine/graphics/ecs/water/WATER_SIZE.d.ts.map +0 -1
- package/src/engine/graphics/ecs/water/WATER_SIZE.js +0 -1
- package/src/shade/renderer/light/GPUViewLightContext.d.ts +0 -22
- package/src/shade/renderer/light/GPUViewLightContext.d.ts.map +0 -1
- package/src/shade/renderer/light/GPUViewLightContext.js +0 -62
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts +0 -14
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/shadow/map/csm/CSM_SHADOWMAP_STRUCT.js +0 -20
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts +0 -27
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/GPUViewShadowMaps.js +0 -147
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts +0 -7
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/GPUVirtualShadowTextureResidence.js +0 -10
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts +0 -2
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_RESIDENCE_WORKGROUP_TILE_RESOLUTION.js +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts +0 -3
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VSM_UNIFORMS_STRUCT.js +0 -8
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts +0 -27
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/VirtualShadowmapRenderer.js +0 -102
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts +0 -8
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/debug_inspect_coarse_bounds_buffer.js +0 -34
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts +0 -10
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/debug_inspect_residence_buffer.js +0 -64
- package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts +0 -11
- package/src/shade/renderer/shadow/vsm/decode_tile_address.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/decode_tile_address.js +0 -26
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts +0 -2
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/render/vms_render_tiles.js +0 -11
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts +0 -20
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vms_pipeline_compute_coarse_bounds.js +0 -184
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts +0 -25
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vsm_residence_pipeline.js +0 -230
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts +0 -19
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.d.ts.map +0 -1
- package/src/shade/renderer/shadow/vsm/vsm_tile_allocation_pipeline.js +0 -127
- package/src/shade/renderer/texture/encode/ENCODE_NOTES_2026_09_02.md +0 -462
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts +0 -23
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance.d.ts.map +0 -1
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts +0 -18
- package/src/shade/renderer/water/optics/chunk_water_light_transmittance_dry.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts +0 -12
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_SURFACE_VERTEX_STRUCT.js +0 -27
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts +0 -14
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/WATER_WAVE_PARAMETERS_STRUCT.js +0 -49
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts +0 -9
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/chunk_water_wave_grid.js +0 -47
- package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts +0 -10
- package/src/shade/renderer/water/surface/shader_water_surface_write.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/shader_water_surface_write.js +0 -51
- package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts +0 -12
- package/src/shade/renderer/water/surface/shader_water_wave_step.d.ts.map +0 -1
- package/src/shade/renderer/water/surface/shader_water_wave_step.js +0 -54
- package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts +0 -13
- package/src/shade/renderer/water/surface/water_surface_grid_indices.d.ts.map +0 -1
- 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
|
+
}
|