6 meshlet_visibility_buffer, 7 meshlet_raster_clusters, 9 meshlet_instance_uniforms, 10 get_meshlet_vertex_id, 11 get_meshlet_vertex_position, 12 get_meshlet_vertex_normal, 13 get_meshlet_vertex_uv, 16 mesh_view_bindings::view, 17 mesh_functions::mesh_position_local_to_world, 19 view_transformations::{position_world_to_clip, frag_coord_to_ndc}, 22import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack}; 24@if(PREPASS_FRAGMENT && MOTION_VECTOR_PREPASS) 26 prepass::bindings::previous_view_uniforms, 27 render::pbr_prepass_functions::calculate_motion_vector, 30@if(MESHLET_MESH_MATERIAL_PASS) 31struct PartialDerivatives { 32 barycentrics: vec3<f32>, 38@if(MESHLET_MESH_MATERIAL_PASS) 39fn compute_partial_derivatives(vertex_world_positions: array<vec4<f32>, 3>, ndc_uv: vec2<f32>, two_over_screen_size: vec2<f32>) -> PartialDerivatives { 40 var result: PartialDerivatives; 42 let vertex_clip_position_0 = position_world_to_clip(vertex_world_positions[0].xyz); 43 let vertex_clip_position_1 = position_world_to_clip(vertex_world_positions[1].xyz); 44 let vertex_clip_position_2 = position_world_to_clip(vertex_world_positions[2].xyz); 46 let inv_w = 1.0 / vec3(vertex_clip_position_0.w, vertex_clip_position_1.w, vertex_clip_position_2.w); 47 let ndc_0 = vertex_clip_position_0.xy * inv_w[0]; 48 let ndc_1 = vertex_clip_position_1.xy * inv_w[1]; 49 let ndc_2 = vertex_clip_position_2.xy * inv_w[2]; 51 let inv_det = 1.0 / determinant(mat2x2(ndc_2 - ndc_1, ndc_0 - ndc_1)); 52 result.ddx = vec3(ndc_1.y - ndc_2.y, ndc_2.y - ndc_0.y, ndc_0.y - ndc_1.y) * inv_det * inv_w; 53 result.ddy = vec3(ndc_2.x - ndc_1.x, ndc_0.x - ndc_2.x, ndc_1.x - ndc_0.x) * inv_det * inv_w; 55 var ddx_sum = dot(result.ddx, vec3(1.0)); 56 var ddy_sum = dot(result.ddy, vec3(1.0)); 58 let delta_v = ndc_uv - ndc_0; 59 let interp_inv_w = inv_w.x + delta_v.x * ddx_sum + delta_v.y * ddy_sum; 60 let interp_w = 1.0 / interp_inv_w; 62 result.barycentrics = vec3( 63 interp_w * (inv_w[0] + delta_v.x * result.ddx.x + delta_v.y * result.ddy.x), 64 interp_w * (delta_v.x * result.ddx.y + delta_v.y * result.ddy.y), 65 interp_w * (delta_v.x * result.ddx.z + delta_v.y * result.ddy.z), 68 result.ddx *= two_over_screen_size.x; 69 result.ddy *= two_over_screen_size.y; 70 ddx_sum *= two_over_screen_size.x; 71 ddy_sum *= two_over_screen_size.y; 76 let interp_ddx_w = 1.0 / (interp_inv_w + ddx_sum); 77 let interp_ddy_w = 1.0 / (interp_inv_w + ddy_sum); 79 result.ddx = interp_ddx_w * (result.barycentrics * interp_inv_w + result.ddx) - result.barycentrics; 80 result.ddy = interp_ddy_w * (result.barycentrics * interp_inv_w + result.ddy) - result.barycentrics; 84@if(MESHLET_MESH_MATERIAL_PASS) 87 world_position: vec4<f32>, 88 world_normal: vec3<f32>, 92 world_tangent: vec4<f32>, 95 material_bind_group_slot: u32, 96 @if(PREPASS_FRAGMENT && MOTION_VECTOR_PREPASS) 97 motion_vector: vec2<f32>, 101@if(MESHLET_MESH_MATERIAL_PASS) 102fn resolve_vertex_output(frag_coord: vec4<f32>) -> VertexOutput { 103 let packed_ids = u32(textureLoad(meshlet_visibility_buffer, vec2<u32>(frag_coord.xy)).r); 104 let cluster_id = packed_ids >> 7u; 105 let instanced_offset = meshlet_raster_clusters[cluster_id]; 106 let meshlet_id = instanced_offset.offset; 107 var meshlet = meshlets[meshlet_id]; 109 let triangle_id = extractBits(packed_ids, 0u, 7u); 110 let index_ids = meshlet.start_index_id + (triangle_id * 3u) + vec3(0u, 1u, 2u); 111 let vertex_ids = vec3(get_meshlet_vertex_id(index_ids[0]), get_meshlet_vertex_id(index_ids[1]), get_meshlet_vertex_id(index_ids[2])); 112 let vertex_0 = load_vertex(&meshlet, vertex_ids[0]); 113 let vertex_1 = load_vertex(&meshlet, vertex_ids[1]); 114 let vertex_2 = load_vertex(&meshlet, vertex_ids[2]); 116 let instance_id = instanced_offset.instance_id; 117 var instance_uniform = meshlet_instance_uniforms[instance_id]; 119 let world_from_local = affine3_to_square(instance_uniform.world_from_local); 120 let world_position_0 = mesh_position_local_to_world(world_from_local, vec4(vertex_0.position, 1.0)); 121 let world_position_1 = mesh_position_local_to_world(world_from_local, vec4(vertex_1.position, 1.0)); 122 let world_position_2 = mesh_position_local_to_world(world_from_local, vec4(vertex_2.position, 1.0)); 124 let frag_coord_ndc = frag_coord_to_ndc(frag_coord).xy; 125 let partial_derivatives = compute_partial_derivatives( 126 array(world_position_0, world_position_1, world_position_2), 128 2.0 / view.viewport.zw, 131 let world_position = mat3x4(world_position_0, world_position_1, world_position_2) * partial_derivatives.barycentrics; 132 let world_positions_camera_relative = mat3x3( 133 world_position_0.xyz - view.world_position, 134 world_position_1.xyz - view.world_position, 135 world_position_2.xyz - view.world_position, 137 let ddx_world_position = world_positions_camera_relative * partial_derivatives.ddx; 138 let ddy_world_position = world_positions_camera_relative * partial_derivatives.ddy; 140 let world_normal = mat3x3( 141 normal_local_to_world(vertex_0.normal, &instance_uniform), 142 normal_local_to_world(vertex_1.normal, &instance_uniform), 143 normal_local_to_world(vertex_2.normal, &instance_uniform), 144 ) * partial_derivatives.barycentrics; 146 let uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.barycentrics; 147 let ddx_uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.ddx; 148 let ddy_uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.ddy; 150 let world_tangent = calculate_world_tangent(world_normal, ddx_world_position, ddy_world_position, ddx_uv, ddy_uv); 152 var motion_vector: vec2<f32>; 153@if(PREPASS_FRAGMENT && MOTION_VECTOR_PREPASS) { 154 let previous_world_from_local = affine3_to_square(instance_uniform.previous_world_from_local); 155 let previous_world_position_0 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_0.position, 1.0)); 156 let previous_world_position_1 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_1.position, 1.0)); 157 let previous_world_position_2 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_2.position, 1.0)); 158 let previous_world_position = mat3x4(previous_world_position_0, previous_world_position_1, previous_world_position_2) * partial_derivatives.barycentrics; 159 motion_vector = calculate_motion_vector(world_position, previous_world_position); 162 var out: VertexOutput; 163 out.position = frag_coord; 164 out.world_position = world_position; 165 out.world_normal = world_normal; 169 out.world_tangent = world_tangent; 170 out.mesh_flags = instance_uniform.flags; 171 out.cluster_id = instance_id ^ meshlet_id; 172 out.material_bind_group_slot = instance_uniform.material_and_lightmap_bind_group_slot & 0xffffu; 173 @if(PREPASS_FRAGMENT && MOTION_VECTOR_PREPASS) 174 out.motion_vector = motion_vector; 178@if(MESHLET_MESH_MATERIAL_PASS) 179struct MeshletVertex { 185@if(MESHLET_MESH_MATERIAL_PASS) 186fn load_vertex(meshlet: ptr<function, Meshlet>, vertex_id: u32) -> MeshletVertex { 187 return MeshletVertex( 188 get_meshlet_vertex_position(meshlet, vertex_id), 189 get_meshlet_vertex_normal(meshlet, vertex_id), 190 get_meshlet_vertex_uv(meshlet, vertex_id), 194@if(MESHLET_MESH_MATERIAL_PASS) 195fn normal_local_to_world(vertex_normal: vec3<f32>, instance_uniform: ptr<function, Mesh>) -> vec3<f32> { 196 if any(vertex_normal != vec3<f32>(0.0)) { 198 mat2x4_f32_to_mat3x3_unpack( 199 (*instance_uniform).local_from_world_transpose_a, 200 (*instance_uniform).local_from_world_transpose_b, 204 return vertex_normal; 209@if(MESHLET_MESH_MATERIAL_PASS) 210fn calculate_world_tangent( 211 world_normal: vec3<f32>, 212 ddx_world_position: vec3<f32>, 213 ddy_world_position: vec3<f32>, 218 let ddx_world_position_s = ddx_world_position - dot(ddx_world_position, world_normal) * world_normal; 219 let ddy_world_position_s = ddy_world_position - dot(ddy_world_position, world_normal) * world_normal; 222 let jacobian_sign = sign(ddx_uv.x * ddy_uv.y - ddx_uv.y * ddy_uv.x); 224 var world_tangent = jacobian_sign * (ddy_uv.y * ddx_world_position_s - ddx_uv.y * ddy_world_position_s); 227 if jacobian_sign != 0.0 { 228 world_tangent = normalize(world_tangent); 233 let w = jacobian_sign * sign(dot(ddy_world_position, cross(world_normal, ddx_world_position))); 235 return vec4(world_tangent, -w);