@woosh/meep-engine 3.61.3 → 3.62.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/package.json +1 -1
- package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
- package/src/engine/graphics3/PickingSystem.js +415 -413
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +2 -1
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +26 -16
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_tile_copy.js +6 -11
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +6 -2
- package/src/engine/graphics3/highlight/shader_highlight_outline.d.ts.map +1 -1
- package/src/engine/graphics3/highlight/shader_highlight_outline.js +167 -150
- package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -1
- package/src/engine/graphics3/shader_picking_gather.js +133 -120
- package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUTexture.js +11 -0
- package/src/shade/device/pipeline/rp_validate_and_rewrite_for_color_attachments.js +1 -1
- package/src/shade/playground/contact_shadows/ContactShadowLab.js +6 -6
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts.map +1 -1
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.js +6 -4
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts.map +1 -1
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.js +6 -4
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts.map +1 -1
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.js +6 -4
- package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +1 -1
- package/src/shade/playground/ssr_variance/capture.js +1 -1
- package/src/shade/renderer/Renderer.d.ts +2 -2
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +40 -53
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.js +3 -1
- package/src/shade/renderer/deferred/chunk_ss_trace_contact_shadow_soft.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_ss_trace_contact_shadow_soft.js +5 -4
- package/src/shade/renderer/deferred/shader_deferred_main.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_deferred_main.js +6 -4
- package/src/shade/renderer/extension/GBufferTextures.d.ts +5 -1
- package/src/shade/renderer/extension/GBufferTextures.d.ts.map +1 -1
- package/src/shade/renderer/extension/GBufferTextures.js +5 -1
- package/src/shade/renderer/extension/ViewTextures.d.ts +11 -7
- package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
- package/src/shade/renderer/extension/ViewTextures.js +17 -13
- package/src/shade/renderer/gbuffer/G_BUFFER_ALBEDO_FORMAT.d.ts +2 -0
- package/src/shade/renderer/gbuffer/G_BUFFER_ALBEDO_FORMAT.d.ts.map +1 -1
- package/src/shade/renderer/gbuffer/G_BUFFER_ALBEDO_FORMAT.js +2 -0
- package/src/shade/renderer/gbuffer/G_BUFFER_COLOR_TARGETS.d.ts.map +1 -1
- package/src/shade/renderer/gbuffer/G_BUFFER_COLOR_TARGETS.js +8 -5
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts +7 -5
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +29 -16
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.d.ts +9 -3
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.js +40 -32
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +14 -15
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_debug_draw.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_debug_draw.js +7 -3
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_diffuse.js +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.js +5 -3
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.js +1 -3
- package/src/shade/renderer/global_illumination/ibl/shader_diffuse_IBL.js +1 -1
- package/src/shade/renderer/global_illumination/ibl/shader_specular_IBL.js +2 -2
- package/src/shade/renderer/global_illumination/lpv/shader_diffuse_LPV.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +14 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +10 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +5 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +1 -1
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.js +5 -3
- package/src/shade/renderer/global_illumination/sharc/shader/debug/shader_colored_hash.js +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/debug/shader_sharc_debug_radiance.js +1 -1
- package/src/shade/renderer/global_illumination/sharc/shader/shader_sharc_update.js +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +22 -9
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +159 -65
- package/src/shade/renderer/material/MATERIAL_MASK.d.ts +19 -0
- package/src/shade/renderer/material/MATERIAL_MASK.d.ts.map +1 -0
- package/src/shade/renderer/material/MATERIAL_MASK.js +19 -0
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts +8 -8
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts.map +1 -1
- package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.js +11 -92
- package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts.map +1 -1
- package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.js +10 -2
- package/src/shade/renderer/material/dispatch/gbuffer_compute.js +2 -2
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts +7 -7
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts.map +1 -1
- package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.js +20 -16
- package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts.map +1 -1
- package/src/shade/renderer/material/dispatch/shader_material_pixel_count.js +3 -1
- package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts.map +1 -1
- package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.js +3 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +26 -25
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts +10 -8
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +16 -13
- package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts +1 -1
- package/src/shade/renderer/material/template/ShadeMaterialTemplate.js +1 -1
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts +5 -2
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.js +7 -4
- package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.d.ts +3 -3
- package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.js +12 -10
- package/src/shade/renderer/postprocess/denoise/fragment_shader_denoise_ao.js +2 -2
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.js +6 -4
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +9 -7
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +11 -8
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts +3 -3
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +17 -12
- package/src/shade/renderer/postprocess/gtao/chunk_integrate_lighting_sample.js +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +4 -4
- package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.js +2 -2
- package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.js +41 -41
- package/src/shade/renderer/postprocess/ssr/prefilter/chunk_load_neighbourhood_sample.js +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +3 -3
- package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_add_hit_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_add_hit_irradiance.js +5 -2
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +4 -4
- package/src/shade/renderer/postprocess/ssr/ssr_combine_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_combine_shader.js +4 -2
- package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.d.ts +2 -1
- package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.js +10 -2
- package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +1 -1
- package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +4 -4
- package/src/shade/renderer/postprocess/taa/shader_reprojection_map.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/shader_reprojection_map.js +6 -4
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts +6 -8
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +29 -33
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.js +1 -0
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts +6 -3
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.js +8 -3
- package/src/shade/renderer/rasterize/expand/GPUCollectionLimits.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/GPUCollectionLimits.js +3 -0
- package/src/shade/renderer/rasterize/expand/RasterizationCollectionType.d.ts +1 -0
- package/src/shade/renderer/rasterize/expand/RasterizationCollectionType.js +5 -0
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts +8 -3
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +54 -5
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +1 -0
- 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/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +2 -1
- package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.d.ts +7 -2
- package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +73 -9
- package/src/shade/renderer/rasterize/native/viz/shader_vertex.js +4 -4
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +23 -40
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_opaque_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_opaque_pass_descriptor.js +55 -76
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts +4 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +6 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts +4 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +6 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts +5 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +43 -2
- package/src/shade/renderer/rasterize/visibility/VISIBILITY_BUFFER.d.ts +39 -0
- package/src/shade/renderer/rasterize/visibility/VISIBILITY_BUFFER.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/visibility/VISIBILITY_BUFFER.js +45 -0
- package/src/shade/renderer/rasterize/visibility/chunk_visibility_decode.d.ts +26 -0
- package/src/shade/renderer/rasterize/visibility/chunk_visibility_decode.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/visibility/chunk_visibility_decode.js +48 -0
- package/src/shade/renderer/rasterize/visibility/shader_visible_meshlets_append.d.ts +40 -0
- package/src/shade/renderer/rasterize/visibility/shader_visible_meshlets_append.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/visibility/shader_visible_meshlets_append.js +172 -0
- package/src/shade/renderer/restir/di/chunk_restir_reconstruct_surface.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_reconstruct_surface.js +6 -4
- package/src/shade/renderer/restir/di/chunk_restir_spatial_reuse.js +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_denoise.js +2 -2
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_sRGBTransferEOTF.d.ts +9 -0
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_sRGBTransferEOTF.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_sRGBTransferEOTF.js +18 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_determinant.d.ts +20 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_determinant.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_determinant.js +26 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +60 -18
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +163 -45
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.js +19 -18
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_face_normal.d.ts +13 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_face_normal.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_face_normal.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.d.ts +8 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.js +10 -8
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_face_normal.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_face_normal.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_face_normal.js +32 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_normal.d.ts +11 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_g_buffer_normal.js +14 -6
- package/src/shade/renderer/shader/chunk/material/chunk_decode_g_buffer_albedo.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/material/chunk_decode_g_buffer_albedo.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/material/chunk_decode_g_buffer_albedo.js +24 -0
- package/src/shade/renderer/shader/chunk/material/chunk_encode_g_buffer_albedo.d.ts +17 -0
- package/src/shade/renderer/shader/chunk/material/chunk_encode_g_buffer_albedo.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/material/chunk_encode_g_buffer_albedo.js +27 -0
- package/src/shade/renderer/shader/chunk/screen_space/SCREEN_SPACE_RESOURCES.d.ts +7 -1
- package/src/shade/renderer/shader/chunk/screen_space/SCREEN_SPACE_RESOURCES.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/screen_space/SCREEN_SPACE_RESOURCES.js +8 -1
- package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_load_world_space_normal.js +1 -1
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_newton_ray.js +10 -10
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +8 -0
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +9 -0
- package/src/shade/renderer/shader/util/shader_decode_octahedral_normal.js +1 -1
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts +3 -3
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts.map +1 -1
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.js +3 -3
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts.map +1 -1
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.js +6 -4
- package/src/shade/renderer/shadow/ray/RTXShadows.d.ts +6 -4
- package/src/shade/renderer/shadow/ray/RTXShadows.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/RTXShadows.js +16 -5
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.js +7 -7
- package/src/shade/renderer/shadow/ray/shader_shadow_upscale.js +2 -2
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.d.ts +4 -2
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +79 -74
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +7 -7
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_soft_shadows.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/cascade/shader_scene_sdf_soft_shadows.js +7 -3
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts +7 -5
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
- package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +29 -16
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts +5 -5
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +8 -8
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +13 -14
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +2 -1
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +6 -4
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_transport.js +11 -9
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +13 -11
- package/src/shade/renderer/gbuffer/G_BUFFER_MIP_LEVELS.d.ts +0 -7
- package/src/shade/renderer/gbuffer/G_BUFFER_MIP_LEVELS.d.ts.map +0 -1
- package/src/shade/renderer/gbuffer/G_BUFFER_MIP_LEVELS.js +0 -6
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts +0 -3
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.d.ts.map +0 -1
- package/src/shade/renderer/postprocess/ssr/shader_downsample_encoded_normal.js +0 -104
|
@@ -1,413 +1,415 @@
|
|
|
1
|
-
import { assert } from "../../core/assert.js";
|
|
2
|
-
import { m4_invert } from "../../core/geom/3d/mat4/m4_invert.js";
|
|
3
|
-
import { BufferResourceDescriptor } from "../../shade/device/graph/BufferResourceDescriptor.js";
|
|
4
|
-
import { graph_read_buffer } from "../../shade/renderer/buffer/graph_read_buffer.js";
|
|
5
|
-
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
6
|
-
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
7
|
-
import { ViewTextures } from "../../shade/renderer/extension/ViewTextures.js";
|
|
8
|
-
import { VIZ_BUFFER_INVALID_MESH_VALUE } from "../../shade/renderer/rasterize/native/viz/VIZ_BUFFER_INVALID_MESH_VALUE.js";
|
|
9
|
-
import { entity_of_row } from "../../shade/renderer/scene/rows/GPUSceneRows.js";
|
|
10
|
-
import { ParentEntity } from "../ecs/parent/ParentEntity.js";
|
|
11
|
-
import { System } from "../ecs/System.js";
|
|
12
|
-
import { Pickable } from "./Pickable.js";
|
|
13
|
-
import { PickingResult } from "./PickingResult.js";
|
|
14
|
-
import {
|
|
15
|
-
PICKING_GATHER_STRIDE_WORDS,
|
|
16
|
-
PICKING_QUERY_OFF_VIEW,
|
|
17
|
-
shader_picking_gather
|
|
18
|
-
} from "./shader_picking_gather.js";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Bytes a query occupies in the gather buffer: the mesh row and the depth, one word each.
|
|
22
|
-
*
|
|
23
|
-
* @type {number}
|
|
24
|
-
*/
|
|
25
|
-
const QUERY_STRIDE = PICKING_GATHER_STRIDE_WORDS * 4;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Answers "what is under this pixel" for entities that asked to be pickable.
|
|
29
|
-
*
|
|
30
|
-
* **Off the visibility buffer.** The rasterizer writes every pixel's `meshes` row — an entity's
|
|
31
|
-
* row, one on — and its depth; a pick reads those two texels out of the frame that drew them and
|
|
32
|
-
* resolves the row to the entity that drew it, then up its parents to the one that opted in. What
|
|
33
|
-
* was drawn is what is picked: at triangle precision, under skinning, with nothing kept on the CPU
|
|
34
|
-
* for it — no bounds, no tree, no per-frame refresh.
|
|
35
|
-
*
|
|
36
|
-
* **Asynchronous and batched, of necessity.** The texels are gathered by the frame after the query
|
|
37
|
-
* was asked and read back when the device has finished it, so an answer is a frame or two late and
|
|
38
|
-
* arrives for the whole batch at once. A result is a promise for that reason, and nothing this
|
|
39
|
-
* tick can come to depend on it.
|
|
40
|
-
*
|
|
41
|
-
* Terrain picking, which is where the game's precision matters, does not come through here at all:
|
|
42
|
-
* it is an exact raycast against the terrain's own representation and is untouched by any of this.
|
|
43
|
-
*/
|
|
44
|
-
export class PickingSystem extends System {
|
|
45
|
-
/**
|
|
46
|
-
* @type {GraphicsEngine}
|
|
47
|
-
*/
|
|
48
|
-
#graphics;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @type {PickingExtension|null}
|
|
52
|
-
*/
|
|
53
|
-
#extension = null;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Entities that have opted in.
|
|
57
|
-
*
|
|
58
|
-
* @type {Set<number>}
|
|
59
|
-
*/
|
|
60
|
-
#pickable = new Set();
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Queries asked since the last frame took a batch, with the promise each batch answers.
|
|
64
|
-
*
|
|
65
|
-
* @type {{queries: PickingQuery[], resolve: function(PickingResult[]): void, reject: function(Error): void}[]}
|
|
66
|
-
*/
|
|
67
|
-
#waiting = [];
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @param {GraphicsEngine} graphics whose frames draw the view the picks read
|
|
71
|
-
*/
|
|
72
|
-
constructor(graphics) {
|
|
73
|
-
super();
|
|
74
|
-
|
|
75
|
-
assert.defined(graphics, 'graphics');
|
|
76
|
-
|
|
77
|
-
this.#graphics = graphics;
|
|
78
|
-
|
|
79
|
-
this.dependencies = [Pickable];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async startup(entityManager) {
|
|
83
|
-
this.entityManager = entityManager;
|
|
84
|
-
|
|
85
|
-
this.#extension = this.#graphics.add_extension(new PickingExtension(this));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async shutdown(entityManager) {
|
|
89
|
-
if (this.#extension !== null) {
|
|
90
|
-
this.#graphics.remove_extension(this.#extension);
|
|
91
|
-
this.#extension = null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this.#pickable.clear();
|
|
95
|
-
|
|
96
|
-
// nothing will draw a frame for them
|
|
97
|
-
for (const batch of this.#waiting.splice(0)) {
|
|
98
|
-
batch.reject(new Error('the picking system shut down before a frame answered'));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @param {Pickable} pickable
|
|
104
|
-
* @param {number} entity
|
|
105
|
-
*/
|
|
106
|
-
link(pickable, entity) {
|
|
107
|
-
this.#pickable.add(entity);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @param {Pickable} pickable
|
|
112
|
-
* @param {number} entity
|
|
113
|
-
*/
|
|
114
|
-
unlink(pickable, entity) {
|
|
115
|
-
this.#pickable.delete(entity);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* How many entities have opted in.
|
|
120
|
-
*
|
|
121
|
-
* @returns {number}
|
|
122
|
-
*/
|
|
123
|
-
get pickable_count() {
|
|
124
|
-
return this.#pickable.size;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Batches asked and not yet answered by a frame.
|
|
129
|
-
*
|
|
130
|
-
* @returns {number}
|
|
131
|
-
*/
|
|
132
|
-
get waiting_count() {
|
|
133
|
-
return this.#waiting.length;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* What is drawn under each of these pixels.
|
|
138
|
-
*
|
|
139
|
-
* One result per query, in the order the queries were given. A pixel over nothing pickable
|
|
140
|
-
* still gets a result — `entity` is {@link PickingResult.NOTHING} — so the two arrays line up
|
|
141
|
-
* by position and a caller never has to search for the answer to its own question.
|
|
142
|
-
*
|
|
143
|
-
* Answered by the next frame that draws the view, when the device has finished it.
|
|
144
|
-
*
|
|
145
|
-
* @param {PickingQuery[]} queries
|
|
146
|
-
* @returns {Promise<PickingResult[]>}
|
|
147
|
-
*/
|
|
148
|
-
pick(queries) {
|
|
149
|
-
assert.isArray(queries, 'queries');
|
|
150
|
-
|
|
151
|
-
if (queries.length === 0) {
|
|
152
|
-
return Promise.resolve([]);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return new Promise((resolve, reject) => {
|
|
156
|
-
this.#waiting.push({ queries: queries.slice(), resolve, reject });
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Take everything asked since the last frame, to be answered by this one.
|
|
162
|
-
*
|
|
163
|
-
* @returns {{queries: PickingQuery[], resolve: function(PickingResult[]): void, reject: function(Error): void}[]}
|
|
164
|
-
*/
|
|
165
|
-
take_waiting() {
|
|
166
|
-
return this.#waiting.splice(0);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* The entity a drawn mesh row picks: the one that drew it, or the nearest of its ancestors,
|
|
171
|
-
* that opted in.
|
|
172
|
-
*
|
|
173
|
-
* @param {number} row a `meshes` row, as the visibility buffer holds it
|
|
174
|
-
* @returns {number} the entity, or {@link PickingResult.NOTHING}
|
|
175
|
-
*/
|
|
176
|
-
resolve_row(row) {
|
|
177
|
-
if (row >= VIZ_BUFFER_INVALID_MESH_VALUE) {
|
|
178
|
-
return PickingResult.NOTHING;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const dataset = this.entityManager.dataset;
|
|
182
|
-
const pickable = this.#pickable;
|
|
183
|
-
|
|
184
|
-
let entity = entity_of_row(row);
|
|
185
|
-
|
|
186
|
-
while (entity >= 0 && dataset.entityExists(entity)) {
|
|
187
|
-
if (pickable.has(entity)) {
|
|
188
|
-
return entity;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const parent = dataset.getComponent(entity, ParentEntity);
|
|
192
|
-
|
|
193
|
-
entity = parent === undefined || parent === null ? -1 : parent.entity;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return PickingResult.NOTHING;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Gathers the queried texels out of the frame that drew them, after the G-buffer is written and
|
|
202
|
-
* before anything overwrites the visibility buffer, and answers the batch when they land.
|
|
203
|
-
*/
|
|
204
|
-
export class PickingExtension extends RenderExtension {
|
|
205
|
-
name = "picking";
|
|
206
|
-
phase = FramePhase.AfterGBuffer;
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* @type {PickingSystem}
|
|
210
|
-
*/
|
|
211
|
-
#system;
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @param {PickingSystem} system
|
|
215
|
-
*/
|
|
216
|
-
constructor(system) {
|
|
217
|
-
super();
|
|
218
|
-
|
|
219
|
-
this.#system = system;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
224
|
-
*/
|
|
225
|
-
record(frame) {
|
|
226
|
-
const batches = this.#system.take_waiting();
|
|
227
|
-
|
|
228
|
-
if (batches.length === 0) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// the view's own resolution: what the visibility buffer is sized to, whatever the frame's
|
|
233
|
-
// target at this phase is
|
|
234
|
-
const resolution = frame.view.resolution;
|
|
235
|
-
const width = resolution[0];
|
|
236
|
-
const height = resolution[1];
|
|
237
|
-
|
|
238
|
-
// what the frame projected with, kept for when the answer comes: the frame's camera has
|
|
239
|
-
// moved on by then
|
|
240
|
-
const view_projection = new Float32Array(frame.view.camera.view_projection_matrix);
|
|
241
|
-
const camera = frame.view.camera.camera.transform;
|
|
242
|
-
const eye = [camera.translation_x, camera.translation_y, camera.translation_z];
|
|
243
|
-
|
|
244
|
-
/** @type {PickingQuery[]} every query of every batch, in order */
|
|
245
|
-
const queries = [];
|
|
246
|
-
|
|
247
|
-
for (const batch of batches) {
|
|
248
|
-
for (const query of batch.queries) {
|
|
249
|
-
queries.push(query);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/*
|
|
254
|
-
The pixel each query names, resolved here rather than in the shader: the fraction is the
|
|
255
|
-
caller's unit and the resolution is the frame's, and neither is the gather's business. A
|
|
256
|
-
query that is not on the view at all carries `PICKING_QUERY_OFF_VIEW` instead of a pixel.
|
|
257
|
-
*/
|
|
258
|
-
const pixels = new Uint32Array(queries.length * PICKING_GATHER_STRIDE_WORDS);
|
|
259
|
-
|
|
260
|
-
for (let i = 0; i < queries.length; i++) {
|
|
261
|
-
const query = queries[i];
|
|
262
|
-
const base = i * PICKING_GATHER_STRIDE_WORDS;
|
|
263
|
-
|
|
264
|
-
if (on_view(query)) {
|
|
265
|
-
pixels[base] = texel(query.u, width);
|
|
266
|
-
pixels[base + 1] = texel(query.v, height);
|
|
267
|
-
} else {
|
|
268
|
-
pixels[base] = PICKING_QUERY_OFF_VIEW;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const textures = frame.get(ViewTextures);
|
|
273
|
-
const graph = frame.graph;
|
|
274
|
-
|
|
275
|
-
const data = {};
|
|
276
|
-
const pass = graph.add("Picking / gather texels", data, (data, resources, context) => {
|
|
277
|
-
const encoder = context.encoder;
|
|
278
|
-
|
|
279
|
-
shader_picking_gather.dispatchThreads({
|
|
280
|
-
encoder,
|
|
281
|
-
bindings: {
|
|
282
|
-
query_count: queries.length,
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
data.
|
|
296
|
-
data.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
result.position.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* @
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
* @param {
|
|
391
|
-
* @param {
|
|
392
|
-
* @param {number}
|
|
393
|
-
* @param {number}
|
|
394
|
-
* @param {number}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { m4_invert } from "../../core/geom/3d/mat4/m4_invert.js";
|
|
3
|
+
import { BufferResourceDescriptor } from "../../shade/device/graph/BufferResourceDescriptor.js";
|
|
4
|
+
import { graph_read_buffer } from "../../shade/renderer/buffer/graph_read_buffer.js";
|
|
5
|
+
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
6
|
+
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
7
|
+
import { ViewTextures } from "../../shade/renderer/extension/ViewTextures.js";
|
|
8
|
+
import { VIZ_BUFFER_INVALID_MESH_VALUE } from "../../shade/renderer/rasterize/native/viz/VIZ_BUFFER_INVALID_MESH_VALUE.js";
|
|
9
|
+
import { entity_of_row } from "../../shade/renderer/scene/rows/GPUSceneRows.js";
|
|
10
|
+
import { ParentEntity } from "../ecs/parent/ParentEntity.js";
|
|
11
|
+
import { System } from "../ecs/System.js";
|
|
12
|
+
import { Pickable } from "./Pickable.js";
|
|
13
|
+
import { PickingResult } from "./PickingResult.js";
|
|
14
|
+
import {
|
|
15
|
+
PICKING_GATHER_STRIDE_WORDS,
|
|
16
|
+
PICKING_QUERY_OFF_VIEW,
|
|
17
|
+
shader_picking_gather
|
|
18
|
+
} from "./shader_picking_gather.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Bytes a query occupies in the gather buffer: the mesh row and the depth, one word each.
|
|
22
|
+
*
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const QUERY_STRIDE = PICKING_GATHER_STRIDE_WORDS * 4;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Answers "what is under this pixel" for entities that asked to be pickable.
|
|
29
|
+
*
|
|
30
|
+
* **Off the visibility buffer.** The rasterizer writes every pixel's `meshes` row — an entity's
|
|
31
|
+
* row, one on — and its depth; a pick reads those two texels out of the frame that drew them and
|
|
32
|
+
* resolves the row to the entity that drew it, then up its parents to the one that opted in. What
|
|
33
|
+
* was drawn is what is picked: at triangle precision, under skinning, with nothing kept on the CPU
|
|
34
|
+
* for it — no bounds, no tree, no per-frame refresh.
|
|
35
|
+
*
|
|
36
|
+
* **Asynchronous and batched, of necessity.** The texels are gathered by the frame after the query
|
|
37
|
+
* was asked and read back when the device has finished it, so an answer is a frame or two late and
|
|
38
|
+
* arrives for the whole batch at once. A result is a promise for that reason, and nothing this
|
|
39
|
+
* tick can come to depend on it.
|
|
40
|
+
*
|
|
41
|
+
* Terrain picking, which is where the game's precision matters, does not come through here at all:
|
|
42
|
+
* it is an exact raycast against the terrain's own representation and is untouched by any of this.
|
|
43
|
+
*/
|
|
44
|
+
export class PickingSystem extends System {
|
|
45
|
+
/**
|
|
46
|
+
* @type {GraphicsEngine}
|
|
47
|
+
*/
|
|
48
|
+
#graphics;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @type {PickingExtension|null}
|
|
52
|
+
*/
|
|
53
|
+
#extension = null;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Entities that have opted in.
|
|
57
|
+
*
|
|
58
|
+
* @type {Set<number>}
|
|
59
|
+
*/
|
|
60
|
+
#pickable = new Set();
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Queries asked since the last frame took a batch, with the promise each batch answers.
|
|
64
|
+
*
|
|
65
|
+
* @type {{queries: PickingQuery[], resolve: function(PickingResult[]): void, reject: function(Error): void}[]}
|
|
66
|
+
*/
|
|
67
|
+
#waiting = [];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {GraphicsEngine} graphics whose frames draw the view the picks read
|
|
71
|
+
*/
|
|
72
|
+
constructor(graphics) {
|
|
73
|
+
super();
|
|
74
|
+
|
|
75
|
+
assert.defined(graphics, 'graphics');
|
|
76
|
+
|
|
77
|
+
this.#graphics = graphics;
|
|
78
|
+
|
|
79
|
+
this.dependencies = [Pickable];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async startup(entityManager) {
|
|
83
|
+
this.entityManager = entityManager;
|
|
84
|
+
|
|
85
|
+
this.#extension = this.#graphics.add_extension(new PickingExtension(this));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async shutdown(entityManager) {
|
|
89
|
+
if (this.#extension !== null) {
|
|
90
|
+
this.#graphics.remove_extension(this.#extension);
|
|
91
|
+
this.#extension = null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.#pickable.clear();
|
|
95
|
+
|
|
96
|
+
// nothing will draw a frame for them
|
|
97
|
+
for (const batch of this.#waiting.splice(0)) {
|
|
98
|
+
batch.reject(new Error('the picking system shut down before a frame answered'));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {Pickable} pickable
|
|
104
|
+
* @param {number} entity
|
|
105
|
+
*/
|
|
106
|
+
link(pickable, entity) {
|
|
107
|
+
this.#pickable.add(entity);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {Pickable} pickable
|
|
112
|
+
* @param {number} entity
|
|
113
|
+
*/
|
|
114
|
+
unlink(pickable, entity) {
|
|
115
|
+
this.#pickable.delete(entity);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* How many entities have opted in.
|
|
120
|
+
*
|
|
121
|
+
* @returns {number}
|
|
122
|
+
*/
|
|
123
|
+
get pickable_count() {
|
|
124
|
+
return this.#pickable.size;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Batches asked and not yet answered by a frame.
|
|
129
|
+
*
|
|
130
|
+
* @returns {number}
|
|
131
|
+
*/
|
|
132
|
+
get waiting_count() {
|
|
133
|
+
return this.#waiting.length;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* What is drawn under each of these pixels.
|
|
138
|
+
*
|
|
139
|
+
* One result per query, in the order the queries were given. A pixel over nothing pickable
|
|
140
|
+
* still gets a result — `entity` is {@link PickingResult.NOTHING} — so the two arrays line up
|
|
141
|
+
* by position and a caller never has to search for the answer to its own question.
|
|
142
|
+
*
|
|
143
|
+
* Answered by the next frame that draws the view, when the device has finished it.
|
|
144
|
+
*
|
|
145
|
+
* @param {PickingQuery[]} queries
|
|
146
|
+
* @returns {Promise<PickingResult[]>}
|
|
147
|
+
*/
|
|
148
|
+
pick(queries) {
|
|
149
|
+
assert.isArray(queries, 'queries');
|
|
150
|
+
|
|
151
|
+
if (queries.length === 0) {
|
|
152
|
+
return Promise.resolve([]);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return new Promise((resolve, reject) => {
|
|
156
|
+
this.#waiting.push({ queries: queries.slice(), resolve, reject });
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Take everything asked since the last frame, to be answered by this one.
|
|
162
|
+
*
|
|
163
|
+
* @returns {{queries: PickingQuery[], resolve: function(PickingResult[]): void, reject: function(Error): void}[]}
|
|
164
|
+
*/
|
|
165
|
+
take_waiting() {
|
|
166
|
+
return this.#waiting.splice(0);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The entity a drawn mesh row picks: the one that drew it, or the nearest of its ancestors,
|
|
171
|
+
* that opted in.
|
|
172
|
+
*
|
|
173
|
+
* @param {number} row a `meshes` row, as the visibility buffer holds it
|
|
174
|
+
* @returns {number} the entity, or {@link PickingResult.NOTHING}
|
|
175
|
+
*/
|
|
176
|
+
resolve_row(row) {
|
|
177
|
+
if (row >= VIZ_BUFFER_INVALID_MESH_VALUE) {
|
|
178
|
+
return PickingResult.NOTHING;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const dataset = this.entityManager.dataset;
|
|
182
|
+
const pickable = this.#pickable;
|
|
183
|
+
|
|
184
|
+
let entity = entity_of_row(row);
|
|
185
|
+
|
|
186
|
+
while (entity >= 0 && dataset.entityExists(entity)) {
|
|
187
|
+
if (pickable.has(entity)) {
|
|
188
|
+
return entity;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const parent = dataset.getComponent(entity, ParentEntity);
|
|
192
|
+
|
|
193
|
+
entity = parent === undefined || parent === null ? -1 : parent.entity;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return PickingResult.NOTHING;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Gathers the queried texels out of the frame that drew them, after the G-buffer is written and
|
|
202
|
+
* before anything overwrites the visibility buffer, and answers the batch when they land.
|
|
203
|
+
*/
|
|
204
|
+
export class PickingExtension extends RenderExtension {
|
|
205
|
+
name = "picking";
|
|
206
|
+
phase = FramePhase.AfterGBuffer;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @type {PickingSystem}
|
|
210
|
+
*/
|
|
211
|
+
#system;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {PickingSystem} system
|
|
215
|
+
*/
|
|
216
|
+
constructor(system) {
|
|
217
|
+
super();
|
|
218
|
+
|
|
219
|
+
this.#system = system;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
224
|
+
*/
|
|
225
|
+
record(frame) {
|
|
226
|
+
const batches = this.#system.take_waiting();
|
|
227
|
+
|
|
228
|
+
if (batches.length === 0) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// the view's own resolution: what the visibility buffer is sized to, whatever the frame's
|
|
233
|
+
// target at this phase is
|
|
234
|
+
const resolution = frame.view.resolution;
|
|
235
|
+
const width = resolution[0];
|
|
236
|
+
const height = resolution[1];
|
|
237
|
+
|
|
238
|
+
// what the frame projected with, kept for when the answer comes: the frame's camera has
|
|
239
|
+
// moved on by then
|
|
240
|
+
const view_projection = new Float32Array(frame.view.camera.view_projection_matrix);
|
|
241
|
+
const camera = frame.view.camera.camera.transform;
|
|
242
|
+
const eye = [camera.translation_x, camera.translation_y, camera.translation_z];
|
|
243
|
+
|
|
244
|
+
/** @type {PickingQuery[]} every query of every batch, in order */
|
|
245
|
+
const queries = [];
|
|
246
|
+
|
|
247
|
+
for (const batch of batches) {
|
|
248
|
+
for (const query of batch.queries) {
|
|
249
|
+
queries.push(query);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
The pixel each query names, resolved here rather than in the shader: the fraction is the
|
|
255
|
+
caller's unit and the resolution is the frame's, and neither is the gather's business. A
|
|
256
|
+
query that is not on the view at all carries `PICKING_QUERY_OFF_VIEW` instead of a pixel.
|
|
257
|
+
*/
|
|
258
|
+
const pixels = new Uint32Array(queries.length * PICKING_GATHER_STRIDE_WORDS);
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < queries.length; i++) {
|
|
261
|
+
const query = queries[i];
|
|
262
|
+
const base = i * PICKING_GATHER_STRIDE_WORDS;
|
|
263
|
+
|
|
264
|
+
if (on_view(query)) {
|
|
265
|
+
pixels[base] = texel(query.u, width);
|
|
266
|
+
pixels[base + 1] = texel(query.v, height);
|
|
267
|
+
} else {
|
|
268
|
+
pixels[base] = PICKING_QUERY_OFF_VIEW;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const textures = frame.get(ViewTextures);
|
|
273
|
+
const graph = frame.graph;
|
|
274
|
+
|
|
275
|
+
const data = {};
|
|
276
|
+
const pass = graph.add("Picking / gather texels", data, (data, resources, context) => {
|
|
277
|
+
const encoder = context.encoder;
|
|
278
|
+
|
|
279
|
+
shader_picking_gather.dispatchThreads({
|
|
280
|
+
encoder,
|
|
281
|
+
bindings: {
|
|
282
|
+
query_count: queries.length,
|
|
283
|
+
visibility: resources.get(data.visibility),
|
|
284
|
+
visible_meshlets: resources.get(data.visible_meshlets),
|
|
285
|
+
viz_depth: resources.get(data.depth),
|
|
286
|
+
queries: encoder.allocateTransientBufferAndLoad(
|
|
287
|
+
pixels.buffer, GPUBufferUsage.STORAGE
|
|
288
|
+
),
|
|
289
|
+
results: resources.get(data.results),
|
|
290
|
+
},
|
|
291
|
+
thread_count_x: queries.length,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
data.visibility = pass.read(textures.visibility);
|
|
296
|
+
data.visible_meshlets = pass.read(textures.visible_meshlets);
|
|
297
|
+
data.depth = pass.read(textures.depth);
|
|
298
|
+
data.results = pass.create("picking/results", BufferResourceDescriptor.from(
|
|
299
|
+
queries.length * QUERY_STRIDE,
|
|
300
|
+
GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
301
|
+
));
|
|
302
|
+
|
|
303
|
+
const system = this.#system;
|
|
304
|
+
|
|
305
|
+
graph_read_buffer({ graph, buffer: data.results })
|
|
306
|
+
.then(ref => {
|
|
307
|
+
try {
|
|
308
|
+
const words = new Uint32Array(ref.getValue());
|
|
309
|
+
const floats = new Float32Array(words.buffer);
|
|
310
|
+
|
|
311
|
+
let index = 0;
|
|
312
|
+
|
|
313
|
+
for (const batch of batches) {
|
|
314
|
+
const results = [];
|
|
315
|
+
|
|
316
|
+
for (let i = 0; i < batch.queries.length; i++, index++) {
|
|
317
|
+
const query = batch.queries[i];
|
|
318
|
+
const result = new PickingResult();
|
|
319
|
+
|
|
320
|
+
results.push(result);
|
|
321
|
+
|
|
322
|
+
if (!on_view(query)) {
|
|
323
|
+
// the gather writes an invalid row here too; this is the same
|
|
324
|
+
// answer without depending on a dispatch having run
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const base = index * PICKING_GATHER_STRIDE_WORDS;
|
|
329
|
+
const entity = system.resolve_row(words[base]);
|
|
330
|
+
|
|
331
|
+
if (entity === PickingResult.NOTHING) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
result.entity = entity;
|
|
336
|
+
|
|
337
|
+
unproject(
|
|
338
|
+
result.position, view_projection,
|
|
339
|
+
texel(query.u, width), texel(query.v, height), width, height,
|
|
340
|
+
floats[base + 1]
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
result.distance = Math.hypot(
|
|
344
|
+
result.position.x - eye[0],
|
|
345
|
+
result.position.y - eye[1],
|
|
346
|
+
result.position.z - eye[2]
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
batch.resolve(results);
|
|
351
|
+
}
|
|
352
|
+
} finally {
|
|
353
|
+
ref.release();
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
.catch(error => {
|
|
357
|
+
for (const batch of batches) {
|
|
358
|
+
batch.reject(error instanceof Error ? error : new Error('the picking readback failed'));
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* @param {PickingQuery} query
|
|
366
|
+
* @returns {boolean} whether the point is on the view at all
|
|
367
|
+
*/
|
|
368
|
+
function on_view(query) {
|
|
369
|
+
return query.u >= 0 && query.u < 1 && query.v >= 0 && query.v < 1;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* The texel a fraction of the view falls in.
|
|
374
|
+
*
|
|
375
|
+
* @param {number} fraction in [0, 1)
|
|
376
|
+
* @param {number} extent texels
|
|
377
|
+
* @returns {number}
|
|
378
|
+
*/
|
|
379
|
+
function texel(fraction, extent) {
|
|
380
|
+
return Math.min(extent - 1, Math.floor(fraction * extent));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const SCRATCH_INVERSE = new Float32Array(16);
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* The world point a pixel's depth stands for, through the inverse of what the frame projected
|
|
387
|
+
* with. Depth is what the buffer holds — reverse-Z, `1` at the near plane — and WebGPU's clip z
|
|
388
|
+
* is that same `[0, 1]`, so it goes straight in.
|
|
389
|
+
*
|
|
390
|
+
* @param {Vector3} target
|
|
391
|
+
* @param {Float32Array} view_projection
|
|
392
|
+
* @param {number} x pixel
|
|
393
|
+
* @param {number} y pixel
|
|
394
|
+
* @param {number} width
|
|
395
|
+
* @param {number} height
|
|
396
|
+
* @param {number} depth
|
|
397
|
+
*/
|
|
398
|
+
function unproject(target, view_projection, x, y, width, height, depth) {
|
|
399
|
+
const m = SCRATCH_INVERSE;
|
|
400
|
+
|
|
401
|
+
m4_invert(m, view_projection);
|
|
402
|
+
|
|
403
|
+
// the pixel's centre, in NDC: x to the right, y up
|
|
404
|
+
const nx = ((x + 0.5) / width) * 2 - 1;
|
|
405
|
+
const ny = 1 - ((y + 0.5) / height) * 2;
|
|
406
|
+
const nz = depth;
|
|
407
|
+
|
|
408
|
+
// column-major: column c is m[c * 4 .. c * 4 + 3]
|
|
409
|
+
const wx = m[0] * nx + m[4] * ny + m[8] * nz + m[12];
|
|
410
|
+
const wy = m[1] * nx + m[5] * ny + m[9] * nz + m[13];
|
|
411
|
+
const wz = m[2] * nx + m[6] * ny + m[10] * nz + m[14];
|
|
412
|
+
const ww = m[3] * nx + m[7] * ny + m[11] * nz + m[15];
|
|
413
|
+
|
|
414
|
+
target.set(wx / ww, wy / ww, wz / ww);
|
|
415
|
+
}
|