2#import bevy_render::{view::View, maths::affine3_to_square} 4@group(0) @binding(0) var<uniform> view: View; 7struct LineGizmoUniform { 8 world_from_local: mat3x4<f32>, 11 _joints_resolution: u32, 14#ifdef SIXTEEN_BYTE_ALIGNMENT 20@group(1) @binding(0) var<uniform> line_gizmo: LineGizmoUniform; 23 @location(0) position_a: vec3<f32>, 24 @location(1) position_b: vec3<f32>, 25 @location(2) color_a: vec4<f32>, 26 @location(3) color_b: vec4<f32>, 27 @builtin(vertex_index) index: u32, 31 @builtin(position) clip_position: vec4<f32>, 32 @location(0) color: vec4<f32>, 34 @location(2) line_fraction: f32, 37const EPSILON: f32 = 4.88e-04; 40fn vertex(vertex: VertexInput) -> VertexOutput { 41 var positions = array<vec2<f32>, 6>( 49 let position = positions[vertex.index]; 51 let world_from_local = affine3_to_square(line_gizmo.world_from_local); 54 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 55 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 58 clip_a = clip_near_plane(clip_a, clip_b); 59 clip_b = clip_near_plane(clip_b, clip_a); 60 let clip = mix(clip_a, clip_b, position.y); 62 let resolution = view.viewport.zw; 63 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 64 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 66 let y_basis = normalize(screen_b - screen_a); 67 let x_basis = vec2(-y_basis.y, y_basis.x); 69 var color = mix(vertex.color_a, vertex.color_b, position.y); 71 var line_width = line_gizmo.line_width; 79 let pos0 = view.view_from_clip * vec4(0, -1, 0, 1); 80 let pos1 = view.view_from_clip * vec4(0, 1, 0, 1); 81 let near_clipping_plane_height = length(pos0.xyz - pos1.xyz); 84 let position_a = view.world_from_clip * clip_a; 85 let position_b = view.world_from_clip * clip_b; 86 let world_distance = length(position_a.xyz - position_b.xyz); 89 let clipped_offset = length(position_a.xyz - vertex.position_a); 91 uv = (clipped_offset + position.y * world_distance) * resolution.y / near_clipping_plane_height / line_gizmo.line_width; 94 let camera_b = view.view_from_clip * clip_b; 98 var depth_adaptment: f32; 99 if (clip_b.w == 1.0) { 100 depth_adaptment = 1.0; 103 depth_adaptment = -camera_b.z; 105 uv = position.y * depth_adaptment * length(screen_b - screen_a) / line_gizmo.line_width; 109 if line_width > 0.0 && line_width < 1. { 110 color.a *= line_width; 114 let x_offset = line_width * position.x * x_basis; 115 let screen = mix(screen_a, screen_b, position.y) + x_offset; 118 if line_gizmo.depth_bias >= 0. { 119 depth = clip.z * (1. - line_gizmo.depth_bias); 128 depth = clip.z * exp2(-line_gizmo.depth_bias * log2(clip.w / clip.z - EPSILON)); 131 var clip_position = vec4(clip.w * ((2. * screen) / resolution - 1.), depth, clip.w); 133 let line_fraction = 2.0 * line_gizmo.line_scale / (line_gizmo.gap_scale + line_gizmo.line_scale); 134 uv /= (line_gizmo.gap_scale + line_gizmo.line_scale) / 2.0; 135 return VertexOutput(clip_position, color, uv, line_fraction); 138fn clip_near_plane(a: vec4<f32>, b: vec4<f32>) -> vec4<f32> { 141 if a.z * sign(a.w) > abs(a.w) && b.z * sign(b.w) <= abs(b.w) { 143 let distance_a = a.z - a.w; 144 let distance_b = b.z - b.w; 147 let t = distance_a / (distance_a - distance_b) + EPSILON; 153struct FragmentInput { 154 @builtin(position) position: vec4<f32>, 155 @location(0) color: vec4<f32>, 156 @location(1) uv: f32, 157 @location(2) line_fraction: f32, 160struct FragmentOutput { 161 @location(0) color: vec4<f32>, 165fn fragment_solid(in: FragmentInput) -> FragmentOutput { 166 return FragmentOutput(in.color); 169fn fragment_dotted(in: FragmentInput) -> FragmentOutput { 172 alpha = 1 - floor(in.uv % 2.0); 174 alpha = 1 - floor((in.uv * in.position.w) % 2.0); 177 return FragmentOutput(vec4(in.color.xyz, in.color.w * alpha)); 181fn fragment_dashed(in: FragmentInput) -> FragmentOutput { 185 let uv = in.uv * in.position.w; 187 let alpha = 1.0 - floor(min((uv % 2.0) / in.line_fraction, 1.0)); 189 return FragmentOutput(vec4(in.color.xyz, in.color.w * alpha));