2023-06-13 06:49:47 +00:00
|
|
|
#ifdef GIZMO_3D
|
2023-03-20 20:57:54 +00:00
|
|
|
#import bevy_pbr::mesh_view_bindings
|
|
|
|
#else
|
|
|
|
#import bevy_sprite::mesh2d_view_bindings
|
|
|
|
#endif
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
struct LineGizmoUniform {
|
|
|
|
line_width: f32,
|
|
|
|
depth_bias: f32,
|
|
|
|
#ifdef SIXTEEN_BYTE_ALIGNMENT
|
|
|
|
// WebGL2 structs must be 16 byte aligned.
|
|
|
|
_padding: vec2<f32>,
|
|
|
|
#endif
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
@group(1) @binding(0)
|
|
|
|
var<uniform> line_gizmo: LineGizmoUniform;
|
|
|
|
|
|
|
|
struct VertexInput {
|
|
|
|
@location(0) position_a: vec3<f32>,
|
|
|
|
@location(1) position_b: vec3<f32>,
|
|
|
|
@location(2) color_a: vec4<f32>,
|
|
|
|
@location(3) color_b: vec4<f32>,
|
|
|
|
@builtin(vertex_index) index: u32,
|
|
|
|
};
|
|
|
|
|
2023-03-20 20:57:54 +00:00
|
|
|
struct VertexOutput {
|
2023-06-13 06:49:47 +00:00
|
|
|
@builtin(position) clip_position: vec4<f32>,
|
2023-03-20 20:57:54 +00:00
|
|
|
@location(0) color: vec4<f32>,
|
2023-06-13 06:49:47 +00:00
|
|
|
};
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
@vertex
|
|
|
|
fn vertex(vertex: VertexInput) -> VertexOutput {
|
|
|
|
var positions = array<vec3<f32>, 6>(
|
|
|
|
vec3(0., -0.5, 0.),
|
|
|
|
vec3(0., -0.5, 1.),
|
|
|
|
vec3(0., 0.5, 1.),
|
|
|
|
vec3(0., -0.5, 0.),
|
|
|
|
vec3(0., 0.5, 1.),
|
|
|
|
vec3(0., 0.5, 0.)
|
|
|
|
);
|
|
|
|
let position = positions[vertex.index];
|
|
|
|
|
|
|
|
// algorithm based on https://wwwtyro.net/2019/11/18/instanced-lines.html
|
|
|
|
let clip_a = view.view_proj * vec4(vertex.position_a, 1.);
|
|
|
|
let clip_b = view.view_proj * vec4(vertex.position_b, 1.);
|
|
|
|
let clip = mix(clip_a, clip_b, position.z);
|
|
|
|
|
|
|
|
let resolution = view.viewport.zw;
|
|
|
|
let screen_a = resolution * (0.5 * clip_a.xy / clip_a.w + 0.5);
|
|
|
|
let screen_b = resolution * (0.5 * clip_b.xy / clip_b.w + 0.5);
|
|
|
|
|
|
|
|
let x_basis = normalize(screen_a - screen_b);
|
|
|
|
let y_basis = vec2(-x_basis.y, x_basis.x);
|
|
|
|
|
|
|
|
var color = mix(vertex.color_a, vertex.color_b, position.z);
|
|
|
|
|
|
|
|
var line_width = line_gizmo.line_width;
|
|
|
|
var alpha = 1.;
|
|
|
|
|
|
|
|
#ifdef PERSPECTIVE
|
|
|
|
line_width /= clip.w;
|
2023-03-29 18:05:03 +00:00
|
|
|
#endif
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
// Line thinness fade from https://acegikmo.com/shapes/docs/#anti-aliasing
|
|
|
|
if line_width < 1. {
|
|
|
|
color.a *= line_width;
|
|
|
|
line_width = 1.;
|
|
|
|
}
|
|
|
|
|
|
|
|
let offset = line_width * (position.x * x_basis + position.y * y_basis);
|
|
|
|
let screen = mix(screen_a, screen_b, position.z) + offset;
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
var depth: f32;
|
|
|
|
if line_gizmo.depth_bias >= 0. {
|
|
|
|
depth = clip.z * (1. - line_gizmo.depth_bias);
|
|
|
|
} else {
|
|
|
|
let epsilon = 4.88e-04;
|
|
|
|
// depth * (clip.w / depth)^-depth_bias. So that when -depth_bias is 1.0, this is equal to clip.w
|
|
|
|
// and when equal to 0.0, it is exactly equal to depth.
|
|
|
|
// the epsilon is here to prevent the depth from exceeding clip.w when -depth_bias = 1.0
|
|
|
|
// clip.w represents the near plane in homogenous clip space in bevy, having a depth
|
|
|
|
// of this value means nothing can be in front of this
|
|
|
|
// The reason this uses an exponential function is that it makes it much easier for the
|
|
|
|
// user to chose a value that is convinient for them
|
|
|
|
depth = clip.z * exp2(-line_gizmo.depth_bias * log2(clip.w / clip.z - epsilon));
|
|
|
|
}
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
var clip_position = vec4(clip.w * ((2. * screen) / resolution - 1.), depth, clip.w);
|
|
|
|
|
|
|
|
return VertexOutput(clip_position, color);
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
struct FragmentInput {
|
|
|
|
@location(0) color: vec4<f32>,
|
|
|
|
};
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
struct FragmentOutput {
|
|
|
|
@location(0) color: vec4<f32>,
|
|
|
|
};
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
@fragment
|
|
|
|
fn fragment(in: FragmentInput) -> FragmentOutput {
|
|
|
|
return FragmentOutput(in.color);
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|