Another project
1struct Grid {
2 world_from_clip: mat4x4<f32>,
3 minor: vec4<f32>,
4 major: vec4<f32>,
5 axis_x: vec4<f32>,
6 axis_y: vec4<f32>,
7 origin: vec4<f32>,
8 viewport: vec2<f32>,
9 minor_spacing: f32,
10 major_every: f32,
11 line_width_px: f32,
12 axis_width_px: f32,
13 origin_radius_px: f32,
14 pixels_per_mm: f32,
15};
16
17@group(0) @binding(0) var<uniform> u: Grid;
18
19@vertex
20fn vs(@builtin(vertex_index) vid: u32) -> @builtin(position) vec4<f32> {
21 var positions = array<vec2<f32>, 3>(
22 vec2<f32>(-1.0, -1.0),
23 vec2<f32>( 3.0, -1.0),
24 vec2<f32>(-1.0, 3.0),
25 );
26 return vec4<f32>(positions[vid], 0.0, 1.0);
27}
28
29fn line_distance_world(coord: f32, spacing: f32) -> f32 {
30 let nearest = round(coord / spacing) * spacing;
31 return abs(coord - nearest);
32}
33
34fn line_alpha(dist_px: f32, half_width_px: f32) -> f32 {
35 let aa = min(0.5, half_width_px);
36 return 1.0 - smoothstep(half_width_px - aa, half_width_px + aa, dist_px);
37}
38
39fn over(dst_pma: vec4<f32>, src: vec4<f32>, coverage: f32) -> vec4<f32> {
40 let a = src.a * coverage;
41 let src_pma = vec4<f32>(src.rgb * a, a);
42 return src_pma + dst_pma * (1.0 - a);
43}
44
45@fragment
46fn fs(@builtin(position) pos: vec4<f32>) -> @location(0) vec4<f32> {
47 let ndc = (pos.xy / u.viewport) * vec2<f32>(2.0, -2.0) + vec2<f32>(-1.0, 1.0);
48 let world4 = u.world_from_clip * vec4<f32>(ndc, 0.0, 1.0);
49 let world = world4.xy / world4.w;
50
51 var acc = vec4<f32>(0.0, 0.0, 0.0, 0.0);
52
53 let half_line = u.line_width_px * 0.5;
54 let dx_minor = line_distance_world(world.x, u.minor_spacing) * u.pixels_per_mm;
55 let dy_minor = line_distance_world(world.y, u.minor_spacing) * u.pixels_per_mm;
56 let minor_cov = max(line_alpha(dx_minor, half_line), line_alpha(dy_minor, half_line));
57 acc = over(acc, u.minor, minor_cov);
58
59 let major_spacing = u.minor_spacing * u.major_every;
60 let dx_major = line_distance_world(world.x, major_spacing) * u.pixels_per_mm;
61 let dy_major = line_distance_world(world.y, major_spacing) * u.pixels_per_mm;
62 let major_cov = max(line_alpha(dx_major, half_line), line_alpha(dy_major, half_line));
63 acc = over(acc, u.major, major_cov);
64
65 let axis_half = u.axis_width_px * 0.5;
66 let ax_y_cov = line_alpha(abs(world.x) * u.pixels_per_mm, axis_half);
67 acc = over(acc, u.axis_y, ax_y_cov);
68 let ax_x_cov = line_alpha(abs(world.y) * u.pixels_per_mm, axis_half);
69 acc = over(acc, u.axis_x, ax_x_cov);
70
71 let d_origin_px = length(world) * u.pixels_per_mm;
72 let origin_cov = 1.0 - smoothstep(u.origin_radius_px - 1.0, u.origin_radius_px + 1.0, d_origin_px);
73 acc = over(acc, u.origin, origin_cov);
74
75 return acc;
76}