Another project
1struct Frame {
2 clip_from_world: mat4x4<f32>,
3 glyph_color: vec4<f32>,
4 pixels_per_mm: f32,
5 offset_px: f32,
6 tile_px: f32,
7 _pad: f32,
8};
9
10struct Instance {
11 @location(0) anchor_mm: vec2<f32>,
12 @location(1) offset_dir: vec2<f32>,
13 @location(2) pick_id: u32,
14 @location(3) tile_index: u32,
15};
16
17struct VsOut {
18 @builtin(position) clip: vec4<f32>,
19 @location(0) uv: vec2<f32>,
20 @location(1) @interpolate(flat) pick_id: u32,
21};
22
23struct FsOut {
24 @location(0) color: vec4<f32>,
25 @location(1) pick_id: u32,
26};
27
28@group(0) @binding(0) var<uniform> u: Frame;
29@group(0) @binding(1) var atlas: texture_2d<f32>;
30@group(0) @binding(2) var atlas_sampler: sampler;
31
32const CORNERS: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
33 vec2<f32>(0.0, 0.0),
34 vec2<f32>(1.0, 0.0),
35 vec2<f32>(0.0, 1.0),
36 vec2<f32>(0.0, 1.0),
37 vec2<f32>(1.0, 0.0),
38 vec2<f32>(1.0, 1.0),
39);
40
41const GRID_DIM: f32 = 4.0;
42const TILE_UV: f32 = 1.0 / 4.0;
43const HALF_TEXEL: f32 = 0.5 / 128.0;
44const INNER_UV: f32 = TILE_UV - 2.0 * HALF_TEXEL;
45
46@vertex
47fn vs(@builtin(vertex_index) vid: u32, inst: Instance) -> VsOut {
48 var corners = CORNERS;
49 let corner = corners[vid];
50 let center_mm = inst.anchor_mm + inst.offset_dir * (u.offset_px / u.pixels_per_mm);
51 let half_mm = (u.tile_px * 0.5) / u.pixels_per_mm;
52 let corner_signed = corner * 2.0 - vec2<f32>(1.0, 1.0);
53 let world_mm = center_mm + corner_signed * half_mm;
54 let clip = u.clip_from_world * vec4<f32>(world_mm, 0.0, 1.0);
55
56 let col = f32(inst.tile_index % 4u);
57 let row = f32(inst.tile_index / 4u);
58 let local_u = corner.x;
59 let local_v = 1.0 - corner.y;
60 let u0 = col * TILE_UV + HALF_TEXEL;
61 let v0 = row * TILE_UV + HALF_TEXEL;
62 let uv = vec2<f32>(u0 + local_u * INNER_UV, v0 + local_v * INNER_UV);
63
64 var out: VsOut;
65 out.clip = clip;
66 out.uv = uv;
67 out.pick_id = inst.pick_id;
68 return out;
69}
70
71@fragment
72fn fs(in: VsOut) -> FsOut {
73 let sample = textureSample(atlas, atlas_sampler, in.uv);
74 let coverage = sample.a;
75 if (coverage <= 1.0e-3) {
76 discard;
77 }
78 let a = u.glyph_color.a * coverage;
79 var out: FsOut;
80 out.color = vec4<f32>(u.glyph_color.rgb * a, a);
81 out.pick_id = in.pick_id;
82 return out;
83}