1@if(WIREFRAME_WIDE) import package::render::{ 3 mesh_view_bindings::view, 4 view_transformations::position_world_to_clip, 6@if(WIREFRAME_WIDE) import bevy_render::maths::affine3_to_square; 7@if(!WIREFRAME_WIDE) import package::render::forward_io::VertexOutput; 14 @if(SIXTEEN_BYTE_ALIGNMENT) 16 @if(SIXTEEN_BYTE_ALIGNMENT) 20var<immediate> immediates: Immediates; 22struct VertexPullParams { 28@group(3) @binding(0) var<storage, read> vertex_data: array<u32>; 29@group(3) @binding(1) var<storage, read> index_data: array<u32>; 30@group(3) @binding(2) var<uniform> vp_params: VertexPullParams; 32struct WireframeVertexOutput { 33 @builtin(position) position: vec4<f32>, 34 @location(0) @interpolate(linear) edge_distance: vec4<f32>, 38fn point_line_distance(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 { 40 let len = length(edge); 44 return abs(edge.x * (p.y - a.y) - edge.y * (p.x - a.x)) / len; 50fn read_local_position(first_vertex: u32, vertex_index: u32) -> vec3<f32> { 51 let base = (first_vertex + vertex_index) * vp_params.vertex_stride 52 + vp_params.position_offset; 54 bitcast<f32>(vertex_data[base]), 55 bitcast<f32>(vertex_data[base + 1u]), 56 bitcast<f32>(vertex_data[base + 2u]), 62 @builtin(vertex_index) vertex_index: u32, 63 @builtin(instance_index) instance_index: u32, 64) -> WireframeVertexOutput { 65 var out: WireframeVertexOutput; 67 let first_vertex = mesh[instance_index].first_vertex_index; 68 let draw_id = vertex_index - first_vertex; 69 let corner = draw_id % 3u; 70 let tri_base = draw_id - corner; 72 let idx0 = index_data[vp_params.index_offset + tri_base]; 73 let idx1 = index_data[vp_params.index_offset + tri_base + 1u]; 74 let idx2 = index_data[vp_params.index_offset + tri_base + 2u]; 76 let p0 = read_local_position(first_vertex, idx0); 77 let p1 = read_local_position(first_vertex, idx1); 78 let p2 = read_local_position(first_vertex, idx2); 80 let world_from_local = affine3_to_square(mesh[instance_index].world_from_local); 81 let clip0 = position_world_to_clip((world_from_local * vec4(p0, 1.0)).xyz); 82 let clip1 = position_world_to_clip((world_from_local * vec4(p1, 1.0)).xyz); 83 let clip2 = position_world_to_clip((world_from_local * vec4(p2, 1.0)).xyz); 85 let viewport_size = view.viewport.zw; 86 let screen0 = (clip0.xy / clip0.w) * viewport_size * 0.5; 87 let screen1 = (clip1.xy / clip1.w) * viewport_size * 0.5; 88 let screen2 = (clip2.xy / clip2.w) * viewport_size * 0.5; 90 let area2 = abs((screen1.x - screen0.x) * (screen2.y - screen0.y) 91 - (screen2.x - screen0.x) * (screen1.y - screen0.y)); 93 let len01 = length(screen1 - screen0); 94 let len12 = length(screen2 - screen1); 95 let len20 = length(screen0 - screen2); 101 let h0 = area2 / max(len12, 0.001); 102 let h1 = area2 / max(len20, 0.001); 103 let h2 = area2 / max(len01, 0.001); 105@if(WIREFRAME_QUADS) { 107 let quad_base = (draw_id / 6u) * 6u; 108 let tri_in_quad = (draw_id / 3u) % 2u; 109 let other_tri_base = quad_base + (1u - tri_in_quad) * 3u; 111 let j0 = index_data[vp_params.index_offset + other_tri_base]; 112 let j1 = index_data[vp_params.index_offset + other_tri_base + 1u]; 113 let j2 = index_data[vp_params.index_offset + other_tri_base + 2u]; 115 let in_other_0 = (idx0 == j0) || (idx0 == j1) || (idx0 == j2); 116 let in_other_1 = (idx1 == j0) || (idx1 == j1) || (idx1 == j2); 117 let in_other_2 = (idx2 == j0) || (idx2 == j1) || (idx2 == j2); 120 let diag_01 = in_other_0 && in_other_1; 121 let diag_12 = in_other_1 && in_other_2; 122 let diag_20 = in_other_2 && in_other_0; 123 let has_diagonal = diag_01 || diag_12 || diag_20; 130 var other_d0 = vec2<f32>(1e6); 131 var other_d1 = vec2<f32>(1e6); 132 var other_d2 = vec2<f32>(1e6); 136 let j0_shared = (j0 == idx0) || (j0 == idx1) || (j0 == idx2); 137 let j1_shared = (j1 == idx0) || (j1 == idx1) || (j1 == idx2); 141 } else if !j1_shared { 145 let p_extra = read_local_position(first_vertex, extra_idx); 146 let clip_extra = position_world_to_clip((world_from_local * vec4(p_extra, 1.0)).xyz); 147 let screen_extra = (clip_extra.xy / clip_extra.w) * viewport_size * 0.5; 151 var diag_a = screen0; 152 var diag_b = screen1; 164 other_d0 = vec2<f32>( 165 point_line_distance(screen0, screen_extra, diag_a), 166 point_line_distance(screen0, screen_extra, diag_b), 168 other_d1 = vec2<f32>( 169 point_line_distance(screen1, screen_extra, diag_a), 170 point_line_distance(screen1, screen_extra, diag_b), 172 other_d2 = vec2<f32>( 173 point_line_distance(screen2, screen_extra, diag_a), 174 point_line_distance(screen2, screen_extra, diag_b), 178 let mask = vec3<f32>( 179 select(1.0, 0.0, diag_12), 180 select(1.0, 0.0, diag_20), 181 select(1.0, 0.0, diag_01), 183 let suppress = vec3<f32>(1.0) - mask; 194 let ed = vec3<f32>(h0, 0.0, 0.0) * mask + suppress * other_d0.x; 195 out.edge_distance = vec4<f32>(ed.x, ed.y, ed.z, other_d0.y); 196 out.position = clip0; 197 } else if corner == 1u { 198 let ed = vec3<f32>(0.0, h1, 0.0) * mask + suppress * other_d1.x; 199 out.edge_distance = vec4<f32>(ed.x, ed.y, ed.z, other_d1.y); 200 out.position = clip1; 202 let ed = vec3<f32>(0.0, 0.0, h2) * mask + suppress * other_d2.x; 203 out.edge_distance = vec4<f32>(ed.x, ed.y, ed.z, other_d2.y); 204 out.position = clip2; 208 out.edge_distance = vec4<f32>(h0, 0.0, 0.0, 1e6); 209 out.position = clip0; 210 } else if corner == 1u { 211 out.edge_distance = vec4<f32>(0.0, h1, 0.0, 1e6); 212 out.position = clip1; 214 out.edge_distance = vec4<f32>(0.0, 0.0, h2, 1e6); 215 out.position = clip2; 223fn fragment(in: WireframeVertexOutput) -> @location(0) vec4<f32> { 224 let d = min(min(in.edge_distance.x, in.edge_distance.y), 225 min(in.edge_distance.z, in.edge_distance.w)); 227 let width = immediates.line_width; 228 let smoothing = immediates.smoothing; 230 let effective_width = max(width, 1.0); 231 let alpha_scale = min(width, 1.0); 233 let half_width = effective_width * 0.5; 235 let alpha = (1.0 - smoothstep(half_width, half_width + smoothing, d)) 237 * immediates.color.a; 243 return vec4<f32>(immediates.color.rgb, alpha); 249@if(!WIREFRAME_WIDE) { 254var<immediate> immediates: Immediates; 257fn fragment(in: VertexOutput) -> @location(0) vec4<f32> { 258 return immediates.color;