Another project
1struct Frame {
2 viewport_px: vec2<f32>,
3 atlas_px: vec2<f32>,
4 grid_cols: f32,
5 tile_pad: f32,
6 _pad: vec2<f32>,
7 pages: array<vec4<f32>, 4>,
8};
9
10@group(0) @binding(0) var<uniform> u: Frame;
11@group(0) @binding(1) var atlas: texture_2d<f32>;
12@group(0) @binding(2) var samp: sampler;
13
14struct VsOut {
15 @builtin(position) clip: vec4<f32>,
16 @location(0) uv: vec2<f32>,
17 @location(1) tint: vec4<f32>,
18};
19
20fn select_page(requested_px: f32) -> vec4<f32> {
21 if requested_px <= u.pages[0].w {
22 return u.pages[0];
23 }
24 if requested_px <= u.pages[1].w {
25 return u.pages[1];
26 }
27 if requested_px <= u.pages[2].w {
28 return u.pages[2];
29 }
30 return u.pages[3];
31}
32
33@vertex
34fn vs(
35 @builtin(vertex_index) vid: u32,
36 @location(0) rect_xywh_px: vec4<f32>,
37 @location(1) tint: vec4<f32>,
38 @location(2) tile_index: u32,
39) -> VsOut {
40 var corners = array<vec2<f32>, 6>(
41 vec2<f32>(0.0, 0.0),
42 vec2<f32>(1.0, 0.0),
43 vec2<f32>(0.0, 1.0),
44 vec2<f32>(1.0, 0.0),
45 vec2<f32>(1.0, 1.0),
46 vec2<f32>(0.0, 1.0),
47 );
48 let c = corners[vid];
49 let pos_px = rect_xywh_px.xy + c * rect_xywh_px.zw;
50 let ndc = vec2<f32>(
51 (pos_px.x / u.viewport_px.x) * 2.0 - 1.0,
52 1.0 - (pos_px.y / u.viewport_px.y) * 2.0,
53 );
54
55 let requested_px = max(rect_xywh_px.z, rect_xywh_px.w);
56 let page = select_page(requested_px);
57 let origin_y = page.x;
58 let cell_px = page.z;
59 let side_px = page.w;
60
61 let cols = u32(u.grid_cols);
62 let col = f32(tile_index % cols);
63 let row = f32(tile_index / cols);
64 let tile_origin = vec2<f32>(col, row) * cell_px + vec2<f32>(u.tile_pad, u.tile_pad);
65 let sample_px = tile_origin + c * side_px;
66 let global_px = vec2<f32>(sample_px.x, origin_y + sample_px.y);
67
68 var out: VsOut;
69 out.clip = vec4<f32>(ndc, 0.0, 1.0);
70 out.uv = global_px / u.atlas_px;
71 out.tint = tint;
72 return out;
73}
74
75@fragment
76fn fs(in: VsOut) -> @location(0) vec4<f32> {
77 let texel = textureSample(atlas, samp, in.uv);
78 return texel * in.tint;
79}