1#define_import_path bevy_pbr::meshlet_visibility_buffer_resolve 6 meshlet_visibility_buffer, 7 meshlet_cluster_meshlet_ids, 9 meshlet_cluster_instance_ids, 10 meshlet_instance_uniforms, 11 get_meshlet_vertex_id, 12 get_meshlet_vertex_position, 13 get_meshlet_vertex_normal, 14 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}, 21#import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack} 23#ifdef PREPASS_FRAGMENT 24#ifdef MOTION_VECTOR_PREPASS 26 prepass_bindings::previous_view_uniforms, 27 pbr_prepass_functions::calculate_motion_vector, 34#ifdef MESHLET_MESH_MATERIAL_PASS 35struct PartialDerivatives { 36 barycentrics: vec3<f32>, 42fn compute_partial_derivatives(vertex_world_positions: array<vec4<f32>, 3>, ndc_uv: vec2<f32>, half_screen_size: vec2<f32>) -> PartialDerivatives { 43 var result: PartialDerivatives; 45 let vertex_clip_position_0 = position_world_to_clip(vertex_world_positions[0].xyz); 46 let vertex_clip_position_1 = position_world_to_clip(vertex_world_positions[1].xyz); 47 let vertex_clip_position_2 = position_world_to_clip(vertex_world_positions[2].xyz); 49 let inv_w = 1.0 / vec3(vertex_clip_position_0.w, vertex_clip_position_1.w, vertex_clip_position_2.w); 50 let ndc_0 = vertex_clip_position_0.xy * inv_w[0]; 51 let ndc_1 = vertex_clip_position_1.xy * inv_w[1]; 52 let ndc_2 = vertex_clip_position_2.xy * inv_w[2]; 54 let inv_det = 1.0 / determinant(mat2x2(ndc_2 - ndc_1, ndc_0 - ndc_1)); 55 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; 56 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; 58 var ddx_sum = dot(result.ddx, vec3(1.0)); 59 var ddy_sum = dot(result.ddy, vec3(1.0)); 61 let delta_v = ndc_uv - ndc_0; 62 let interp_inv_w = inv_w.x + delta_v.x * ddx_sum + delta_v.y * ddy_sum; 63 let interp_w = 1.0 / interp_inv_w; 65 result.barycentrics = vec3( 66 interp_w * (inv_w[0] + delta_v.x * result.ddx.x + delta_v.y * result.ddy.x), 67 interp_w * (delta_v.x * result.ddx.y + delta_v.y * result.ddy.y), 68 interp_w * (delta_v.x * result.ddx.z + delta_v.y * result.ddy.z), 71 result.ddx *= half_screen_size.x; 72 result.ddy *= half_screen_size.y; 73 ddx_sum *= half_screen_size.x; 74 ddy_sum *= half_screen_size.y; 79 let interp_ddx_w = 1.0 / (interp_inv_w + ddx_sum); 80 let interp_ddy_w = 1.0 / (interp_inv_w + ddy_sum); 82 result.ddx = interp_ddx_w * (result.barycentrics * interp_inv_w + result.ddx) - result.barycentrics; 83 result.ddy = interp_ddy_w * (result.barycentrics * interp_inv_w + result.ddy) - result.barycentrics; 89 world_position: vec4<f32>, 90 world_normal: vec3<f32>, 94 world_tangent: vec4<f32>, 97 material_bind_group_slot: u32, 98#ifdef PREPASS_FRAGMENT 99#ifdef MOTION_VECTOR_PREPASS 100 motion_vector: vec2<f32>, 106fn resolve_vertex_output(frag_coord: vec4<f32>) -> VertexOutput { 107 let packed_ids = u32(textureLoad(meshlet_visibility_buffer, vec2<u32>(frag_coord.xy)).r); 108 let cluster_id = packed_ids >> 7u; 109 let meshlet_id = meshlet_cluster_meshlet_ids[cluster_id]; 110 var meshlet = meshlets[meshlet_id]; 112 let triangle_id = extractBits(packed_ids, 0u, 7u); 113 let index_ids = meshlet.start_index_id + (triangle_id * 3u) + vec3(0u, 1u, 2u); 114 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])); 115 let vertex_0 = load_vertex(&meshlet, vertex_ids[0]); 116 let vertex_1 = load_vertex(&meshlet, vertex_ids[1]); 117 let vertex_2 = load_vertex(&meshlet, vertex_ids[2]); 119 let instance_id = meshlet_cluster_instance_ids[cluster_id]; 120 var instance_uniform = meshlet_instance_uniforms[instance_id]; 122 let world_from_local = affine3_to_square(instance_uniform.world_from_local); 123 let world_position_0 = mesh_position_local_to_world(world_from_local, vec4(vertex_0.position, 1.0)); 124 let world_position_1 = mesh_position_local_to_world(world_from_local, vec4(vertex_1.position, 1.0)); 125 let world_position_2 = mesh_position_local_to_world(world_from_local, vec4(vertex_2.position, 1.0)); 127 let frag_coord_ndc = frag_coord_to_ndc(frag_coord).xy; 128 let partial_derivatives = compute_partial_derivatives( 129 array(world_position_0, world_position_1, world_position_2), 131 view.viewport.zw / 2.0, 134 let world_position = mat3x4(world_position_0, world_position_1, world_position_2) * partial_derivatives.barycentrics; 135 let world_positions_camera_relative = mat3x3( 136 world_position_0.xyz - view.world_position, 137 world_position_1.xyz - view.world_position, 138 world_position_2.xyz - view.world_position, 140 let ddx_world_position = world_positions_camera_relative * partial_derivatives.ddx; 141 let ddy_world_position = world_positions_camera_relative * partial_derivatives.ddy; 143 let world_normal = mat3x3( 144 normal_local_to_world(vertex_0.normal, &instance_uniform), 145 normal_local_to_world(vertex_1.normal, &instance_uniform), 146 normal_local_to_world(vertex_2.normal, &instance_uniform), 147 ) * partial_derivatives.barycentrics; 149 let uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.barycentrics; 150 let ddx_uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.ddx; 151 let ddy_uv = mat3x2(vertex_0.uv, vertex_1.uv, vertex_2.uv) * partial_derivatives.ddy; 153 let world_tangent = calculate_world_tangent(world_normal, ddx_world_position, ddy_world_position, ddx_uv, ddy_uv); 155#ifdef PREPASS_FRAGMENT 156#ifdef MOTION_VECTOR_PREPASS 157 let previous_world_from_local = affine3_to_square(instance_uniform.previous_world_from_local); 158 let previous_world_position_0 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_0.position, 1.0)); 159 let previous_world_position_1 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_1.position, 1.0)); 160 let previous_world_position_2 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_2.position, 1.0)); 161 let previous_world_position = mat3x4(previous_world_position_0, previous_world_position_1, previous_world_position_2) * partial_derivatives.barycentrics; 162 let motion_vector = calculate_motion_vector(world_position, previous_world_position); 174 instance_uniform.flags, 175 instance_id ^ meshlet_id, 176 instance_uniform.material_and_lightmap_bind_group_slot & 0xffffu, 177#ifdef PREPASS_FRAGMENT 178#ifdef MOTION_VECTOR_PREPASS 185struct MeshletVertex { 191fn load_vertex(meshlet: ptr<function, Meshlet>, vertex_id: u32) -> MeshletVertex { 192 return MeshletVertex( 193 get_meshlet_vertex_position(meshlet, vertex_id), 194 get_meshlet_vertex_normal(meshlet, vertex_id), 195 get_meshlet_vertex_uv(meshlet, vertex_id), 199fn normal_local_to_world(vertex_normal: vec3<f32>, instance_uniform: ptr<function, Mesh>) -> vec3<f32> { 200 if any(vertex_normal != vec3<f32>(0.0)) { 202 mat2x4_f32_to_mat3x3_unpack( 203 (*instance_uniform).local_from_world_transpose_a, 204 (*instance_uniform).local_from_world_transpose_b, 208 return vertex_normal; 213fn calculate_world_tangent( 214 world_normal: vec3<f32>, 215 ddx_world_position: vec3<f32>, 216 ddy_world_position: vec3<f32>, 221 let ddx_world_position_s = ddx_world_position - dot(ddx_world_position, world_normal) * world_normal; 222 let ddy_world_position_s = ddy_world_position - dot(ddy_world_position, world_normal) * world_normal; 225 let jacobian_sign = sign(ddx_uv.x * ddy_uv.y - ddx_uv.y * ddy_uv.x); 227 var world_tangent = jacobian_sign * (ddy_uv.y * ddx_world_position_s - ddx_uv.y * ddy_world_position_s); 230 if jacobian_sign != 0.0 { 231 world_tangent = normalize(world_tangent); 236 let w = jacobian_sign * sign(dot(ddy_world_position, cross(world_normal, ddx_world_position))); 238 return vec4(world_tangent, -w);