1#import 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#ifdef SIXTEEN_BYTE_ALIGNMENT 17@group(1) @binding(0) var<uniform> joints_gizmo: LineGizmoUniform; 20 @location(0) position_a: vec3<f32>, 21 @location(1) position_b: vec3<f32>, 22 @location(2) position_c: vec3<f32>, 23 @location(3) color: vec4<f32>, 24 @builtin(vertex_index) index: u32, 28 @builtin(position) clip_position: vec4<f32>, 29 @location(0) color: vec4<f32>, 32const EPSILON: f32 = 4.88e-04; 35fn vertex_bevel(vertex: VertexInput) -> VertexOutput { 36 var positions = array<vec2<f32>, 3>( 41 var position = positions[vertex.index]; 43 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 45 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 46 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 47 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 50 clip_a = clip_near_plane(clip_a, clip_c); 51 clip_b = clip_near_plane(clip_b, clip_a); 52 clip_c = clip_near_plane(clip_c, clip_b); 53 clip_a = clip_near_plane(clip_a, clip_c); 55 let resolution = view.viewport.zw; 56 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 57 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 58 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 60 var color = vertex.color; 61 var line_width = joints_gizmo.line_width; 64 line_width /= clip_b.w; 68 if line_width > 0.0 && line_width < 1. { 69 color.a *= line_width; 73 let ab = normalize(screen_b - screen_a); 74 let cb = normalize(screen_b - screen_c); 75 let ab_norm = vec2(-ab.y, ab.x); 76 let cb_norm = vec2(cb.y, -cb.x); 77 let tangent = normalize(ab - cb); 78 let normal = vec2(-tangent.y, tangent.x); 79 let sigma = sign(dot(ab + cb, normal)); 81 var p0 = line_width * sigma * ab_norm; 82 var p1 = line_width * sigma * cb_norm; 84 let screen = screen_b + position.x * p0 + position.y * p1; 86 let depth = depth(clip_b); 88 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 89 return VertexOutput(clip_position, color); 93fn vertex_miter(vertex: VertexInput) -> VertexOutput { 94 var positions = array<vec3<f32>, 6>( 102 var position = positions[vertex.index]; 104 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 106 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 107 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 108 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 111 clip_a = clip_near_plane(clip_a, clip_c); 112 clip_b = clip_near_plane(clip_b, clip_a); 113 clip_c = clip_near_plane(clip_c, clip_b); 114 clip_a = clip_near_plane(clip_a, clip_c); 116 let resolution = view.viewport.zw; 117 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 118 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 119 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 121 var color = vertex.color; 122 var line_width = joints_gizmo.line_width; 125 line_width /= clip_b.w; 129 if line_width > 0.0 && line_width < 1. { 130 color.a *= line_width; 134 let ab = normalize(screen_b - screen_a); 135 let cb = normalize(screen_b - screen_c); 136 let ab_norm = vec2(-ab.y, ab.x); 137 let cb_norm = vec2(cb.y, -cb.x); 138 let tangent = normalize(ab - cb); 139 let normal = vec2(-tangent.y, tangent.x); 140 let sigma = sign(dot(ab + cb, normal)); 142 var p0 = line_width * sigma * ab_norm; 143 var p1 = line_width * sigma * normal / dot(normal, ab_norm); 144 var p2 = line_width * sigma * cb_norm; 146 var screen = screen_b + position.x * p0 + position.y * p1 + position.z * p2; 148 var depth = depth(clip_b); 150 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 151 return VertexOutput(clip_position, color); 155fn vertex_round(vertex: VertexInput) -> VertexOutput { 156 let world_from_local = affine3_to_square(joints_gizmo.world_from_local); 158 var clip_a = view.clip_from_world * world_from_local * vec4(vertex.position_a, 1.); 159 var clip_b = view.clip_from_world * world_from_local * vec4(vertex.position_b, 1.); 160 var clip_c = view.clip_from_world * world_from_local * vec4(vertex.position_c, 1.); 163 clip_a = clip_near_plane(clip_a, clip_c); 164 clip_b = clip_near_plane(clip_b, clip_a); 165 clip_c = clip_near_plane(clip_c, clip_b); 166 clip_a = clip_near_plane(clip_a, clip_c); 168 let resolution = view.viewport.zw; 169 let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5); 170 let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5); 171 let screen_c = resolution * (0.5 * clip_c.xy / clip_c.w + 0.5); 173 var color = vertex.color; 174 var line_width = joints_gizmo.line_width; 177 line_width /= clip_b.w; 181 if line_width > 0.0 && line_width < 1. { 182 color.a *= line_width; 186 let ab = normalize(screen_b - screen_a); 187 let cb = normalize(screen_b - screen_c); 188 let ab_norm = vec2(-ab.y, ab.x); 189 let cb_norm = vec2(cb.y, -cb.x); 195 var in_triangle_index = f32(vertex.index) % 3.0; 196 var tri_index = floor(f32(vertex.index) / 3.0); 197 var radius = sign(in_triangle_index) * 0.5 * line_width; 198 var theta = acos(dot(ab_norm, cb_norm)); 199 let sigma = sign(dot(ab_norm, cb)); 200 var angle = theta * (tri_index + in_triangle_index - 1) / f32(joints_gizmo.resolution); 201 var position_x = sigma * radius * cos(angle); 202 var position_y = radius * sin(angle); 204 var screen = screen_b + position_x * ab_norm + position_y * ab; 206 var depth = depth(clip_b); 208 var clip_position = vec4(clip_b.w * ((2. * screen) / resolution - 1.), depth, clip_b.w); 209 return VertexOutput(clip_position, color); 212fn clip_near_plane(a: vec4<f32>, b: vec4<f32>) -> vec4<f32> { 214 if a.z > a.w && b.z <= b.w { 216 let distance_a = a.z - a.w; 217 let distance_b = b.z - b.w; 220 let t = distance_a / (distance_a - distance_b) + EPSILON; 226fn depth(clip: vec4<f32>) -> f32 { 228 if joints_gizmo.depth_bias >= 0. { 229 depth = clip.z * (1. - joints_gizmo.depth_bias); 238 depth = clip.z * exp2(-joints_gizmo.depth_bias * log2(clip.w / clip.z - EPSILON)); 243struct FragmentInput { 244 @location(0) color: vec4<f32>, 247struct FragmentOutput { 248 @location(0) color: vec4<f32>, 252fn fragment(in: FragmentInput) -> FragmentOutput { 254 return FragmentOutput(in.color);