1import bevy_render::{view::View, maths::affine3_to_square}; 3@group(0) @binding(0) var<uniform> view: View; 6struct LineGizmoUniform { 7 world_from_local: mat3x4<f32>, 11 @if(SIXTEEN_BYTE_ALIGNMENT) 16@group(1) @binding(0) var<uniform> joints_gizmo: LineGizmoUniform; 19 @location(0) position_a: vec3<f32>, 20 @location(1) position_b: vec3<f32>, 21 @location(2) position_c: vec3<f32>, 22 @location(3) color: vec4<f32>, 23 @builtin(vertex_index) index: u32, 27 @builtin(position) clip_position: vec4<f32>, 28 @location(0) color: vec4<f32>, 31const EPSILON: f32 = 4.88e-04; 34fn vertex_bevel(vertex: VertexInput) -> VertexOutput { 35 var positions = array<vec2<f32>, 3>( 40 var position = positions[vertex.index]; 42 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 44 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 45 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 46 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 49 clip_a = clip_near_plane(clip_a, clip_c); 50 clip_b = clip_near_plane(clip_b, clip_a); 51 clip_c = clip_near_plane(clip_c, clip_b); 52 clip_a = clip_near_plane(clip_a, clip_c); 54 let resolution = view.viewport.zw; 55 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 56 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 57 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 59 var color = vertex.color; 60 var line_width = joints_gizmo.line_width; 63 line_width /= clip_b.w; 66 if line_width > 0.0 && line_width < 1. { 67 color.a *= line_width; 71 let ab = normalize(screen_b - screen_a); 72 let cb = normalize(screen_b - screen_c); 73 let ab_norm = vec2(-ab.y, ab.x); 74 let cb_norm = vec2(cb.y, -cb.x); 75 let tangent = normalize(ab - cb); 76 let normal = vec2(-tangent.y, tangent.x); 77 let sigma = sign(dot(ab + cb, normal)); 79 var p0 = line_width * sigma * ab_norm; 80 var p1 = line_width * sigma * cb_norm; 82 let screen = screen_b + position.x * p0 + position.y * p1; 84 let depth = depth(clip_b); 86 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 87 return VertexOutput(clip_position, color); 91fn vertex_miter(vertex: VertexInput) -> VertexOutput { 92 var positions = array<vec3<f32>, 6>( 100 var position = positions[vertex.index]; 102 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 104 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 105 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 106 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 109 clip_a = clip_near_plane(clip_a, clip_c); 110 clip_b = clip_near_plane(clip_b, clip_a); 111 clip_c = clip_near_plane(clip_c, clip_b); 112 clip_a = clip_near_plane(clip_a, clip_c); 114 let resolution = view.viewport.zw; 115 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 116 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 117 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 119 var color = vertex.color; 120 var line_width = joints_gizmo.line_width; 123 line_width /= clip_b.w; 126 if line_width > 0.0 && line_width < 1. { 127 color.a *= line_width; 131 let ab = normalize(screen_b - screen_a); 132 let cb = normalize(screen_b - screen_c); 133 let ab_norm = vec2(-ab.y, ab.x); 134 let cb_norm = vec2(cb.y, -cb.x); 135 let tangent = normalize(ab - cb); 136 let normal = vec2(-tangent.y, tangent.x); 137 let sigma = sign(dot(ab + cb, normal)); 139 var p0 = line_width * sigma * ab_norm; 140 var p1 = line_width * sigma * normal / dot(normal, ab_norm); 141 var p2 = line_width * sigma * cb_norm; 143 var screen = screen_b + position.x * p0 + position.y * p1 + position.z * p2; 145 var depth = depth(clip_b); 147 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 148 return VertexOutput(clip_position, color); 152fn vertex_round(vertex: VertexInput) -> VertexOutput { 153 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 155 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 156 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 157 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 160 clip_a = clip_near_plane(clip_a, clip_c); 161 clip_b = clip_near_plane(clip_b, clip_a); 162 clip_c = clip_near_plane(clip_c, clip_b); 163 clip_a = clip_near_plane(clip_a, clip_c); 165 let resolution = view.viewport.zw; 166 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 167 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 168 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 170 var color = vertex.color; 171 var line_width = joints_gizmo.line_width; 174 line_width /= clip_b.w; 177 if line_width > 0.0 && line_width < 1. { 178 color.a *= line_width; 182 let ab = normalize(screen_b - screen_a); 183 let cb = normalize(screen_b - screen_c); 184 let ab_norm = vec2(-ab.y, ab.x); 185 let cb_norm = vec2(cb.y, -cb.x); 191 var in_triangle_index = f32(vertex.index) % 3.0; 192 var tri_index = floor(f32(vertex.index) / 3.0); 193 var radius = sign(in_triangle_index) * 0.5 * line_width; 194 var theta = acos(dot(ab_norm, cb_norm)); 195 let sigma = sign(dot(ab_norm, cb)); 196 var angle = theta * (tri_index + in_triangle_index - 1) / f32(joints_gizmo.resolution); 197 var position_x = sigma * radius * cos(angle); 198 var position_y = radius * sin(angle); 200 var screen = screen_b + position_x * ab_norm + position_y * ab; 202 var depth = depth(clip_b); 204 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 205 return VertexOutput(clip_position, color); 208fn clip_near_plane(a: vec4<f32>, b: vec4<f32>) -> vec4<f32> { 210 if a.z > a.w && b.z <= b.w { 212 let distance_a = a.z - a.w; 213 let distance_b = b.z - b.w; 216 let t = distance_a / (distance_a - distance_b) + EPSILON; 222fn depth(clip: vec4<f32>) -> f32 { 224 if joints_gizmo.depth_bias >= 0. { 225 depth = clip.z * (1. - joints_gizmo.depth_bias); 234 depth = clip.z * exp2(-joints_gizmo.depth_bias * log2(clip.w / clip.z - EPSILON)); 239struct FragmentInput { 240 @location(0) color: vec4<f32>, 243struct FragmentOutput { 244 @location(0) color: vec4<f32>, 248fn fragment(in: FragmentInput) -> FragmentOutput { 250 return FragmentOutput(in.color);