#define_import_path bevy_pbr::meshlet_bindings #import bevy_pbr::mesh_types::Mesh #import bevy_render::view::View #import bevy_pbr::prepass_bindings::PreviousViewUniforms struct PackedMeshletVertex { a: vec4, b: vec4, tangent: vec4, } // TODO: Octahedral encode normal, remove tangent and derive from UV derivatives struct MeshletVertex { position: vec3, normal: vec3, uv: vec2, tangent: vec4, } fn unpack_meshlet_vertex(packed: PackedMeshletVertex) -> MeshletVertex { var vertex: MeshletVertex; vertex.position = packed.a.xyz; vertex.normal = vec3(packed.a.w, packed.b.xy); vertex.uv = packed.b.zw; vertex.tangent = packed.tangent; return vertex; } struct Meshlet { start_vertex_id: u32, start_index_id: u32, triangle_count: u32, } struct MeshletBoundingSpheres { self_culling: MeshletBoundingSphere, self_lod: MeshletBoundingSphere, parent_lod: MeshletBoundingSphere, } struct MeshletBoundingSphere { center: vec3, radius: f32, } struct DrawIndirectArgs { vertex_count: atomic, instance_count: u32, first_vertex: u32, first_instance: u32, } #ifdef MESHLET_CULLING_PASS @group(0) @binding(0) var meshlet_thread_meshlet_ids: array; // Per cluster (instance of a meshlet) @group(0) @binding(1) var meshlet_bounding_spheres: array; // Per asset meshlet @group(0) @binding(2) var meshlet_thread_instance_ids: array; // Per cluster (instance of a meshlet) @group(0) @binding(3) var meshlet_instance_uniforms: array; // Per entity instance @group(0) @binding(4) var meshlet_view_instance_visibility: array; // 1 bit per entity instance, packed as a bitmask @group(0) @binding(5) var meshlet_second_pass_candidates: array>; // 1 bit per cluster (instance of a meshlet), packed as a bitmask @group(0) @binding(6) var meshlets: array; // Per asset meshlet @group(0) @binding(7) var draw_indirect_args: DrawIndirectArgs; // Single object shared between all workgroups/meshlets/triangles @group(0) @binding(8) var draw_triangle_buffer: array; // Single object shared between all workgroups/meshlets/triangles @group(0) @binding(9) var depth_pyramid: texture_2d; // From the end of the last frame for the first culling pass, and from the first raster pass for the second culling pass @group(0) @binding(10) var view: View; @group(0) @binding(11) var previous_view: PreviousViewUniforms; fn should_cull_instance(instance_id: u32) -> bool { let bit_offset = instance_id % 32u; let packed_visibility = meshlet_view_instance_visibility[instance_id / 32u]; return bool(extractBits(packed_visibility, bit_offset, 1u)); } fn meshlet_is_second_pass_candidate(cluster_id: u32) -> bool { let packed_candidates = meshlet_second_pass_candidates[cluster_id / 32u]; let bit_offset = cluster_id % 32u; return bool(extractBits(packed_candidates, bit_offset, 1u)); } #endif #ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS @group(0) @binding(0) var meshlet_thread_meshlet_ids: array; // Per cluster (instance of a meshlet) @group(0) @binding(1) var meshlets: array; // Per asset meshlet @group(0) @binding(2) var meshlet_indices: array; // Many per asset meshlet @group(0) @binding(3) var meshlet_vertex_ids: array; // Many per asset meshlet @group(0) @binding(4) var meshlet_vertex_data: array; // Many per asset meshlet @group(0) @binding(5) var meshlet_thread_instance_ids: array; // Per cluster (instance of a meshlet) @group(0) @binding(6) var meshlet_instance_uniforms: array; // Per entity instance @group(0) @binding(7) var meshlet_instance_material_ids: array; // Per entity instance @group(0) @binding(8) var draw_triangle_buffer: array; // Single object shared between all workgroups/meshlets/triangles @group(0) @binding(9) var view: View; fn get_meshlet_index(index_id: u32) -> u32 { let packed_index = meshlet_indices[index_id / 4u]; let bit_offset = (index_id % 4u) * 8u; return extractBits(packed_index, bit_offset, 8u); } #endif #ifdef MESHLET_MESH_MATERIAL_PASS @group(1) @binding(0) var meshlet_visibility_buffer: texture_2d; // Generated from the meshlet raster passes @group(1) @binding(1) var meshlet_thread_meshlet_ids: array; // Per cluster (instance of a meshlet) @group(1) @binding(2) var meshlets: array; // Per asset meshlet @group(1) @binding(3) var meshlet_indices: array; // Many per asset meshlet @group(1) @binding(4) var meshlet_vertex_ids: array; // Many per asset meshlet @group(1) @binding(5) var meshlet_vertex_data: array; // Many per asset meshlet @group(1) @binding(6) var meshlet_thread_instance_ids: array; // Per cluster (instance of a meshlet) @group(1) @binding(7) var meshlet_instance_uniforms: array; // Per entity instance fn get_meshlet_index(index_id: u32) -> u32 { let packed_index = meshlet_indices[index_id / 4u]; let bit_offset = (index_id % 4u) * 8u; return extractBits(packed_index, bit_offset, 8u); } #endif