// Prepended to every primitive's shader, which declares its own instance data // as `var : array` at group 1 binding 0, and an `fs_main` // shading one instance of it. What it samples, if anything, is bound at group // 2: the texture at binding 0 and the sampler at binding 1. @group(0) @binding(0) var window: WindowUniform; @group(0) @binding(1) var masks: array; struct WindowUniform { dim: vec2, }; struct Mask { x: UiSpan, y: UiSpan, } struct UiSpan { start: UiScalar, end: UiScalar, } struct UiScalar { rel: f32, abs: f32, } struct InstanceInput { @location(0) x_start: vec2, @location(1) x_end: vec2, @location(2) y_start: vec2, @location(3) y_end: vec2, @location(4) mask_idx: u32, } struct VertexOutput { @location(0) top_left: vec2, @location(1) bot_right: vec2, @location(2) uv: vec2, @location(3) @interpolate(flat) mask_idx: u32, @location(4) @interpolate(flat) idx: u32, @builtin(position) clip_position: vec4, }; @vertex fn vs_main( @builtin(vertex_index) vi: u32, @builtin(instance_index) ii: u32, in: InstanceInput, ) -> VertexOutput { var out: VertexOutput; let top_left_rel = vec2(in.x_start.x, in.y_start.x); let top_left_abs = vec2(in.x_start.y, in.y_start.y); let bot_right_rel = vec2(in.x_end.x, in.y_end.x); let bot_right_abs = vec2(in.x_end.y, in.y_end.y); let top_left = floor(top_left_rel * window.dim) + floor(top_left_abs); let bot_right = floor(bot_right_rel * window.dim) + floor(bot_right_abs); let size = bot_right - top_left; let uv = vec2( f32(vi % 2u), f32(vi / 2u) ); let pos = (top_left + uv * size) / window.dim * 2.0 - 1.0; out.clip_position = vec4(pos.x, -pos.y, 0.0, 1.0); out.uv = uv; out.top_left = top_left; out.bot_right = bot_right; out.mask_idx = in.mask_idx; out.idx = ii; return out; } fn masked(in: VertexOutput, color: vec4) -> vec4 { if in.mask_idx == 4294967295u { return color; } let mask = masks[in.mask_idx]; let tl = vec2(mask.x.start.rel, mask.y.start.rel); let tl_abs = vec2(mask.x.start.abs, mask.y.start.abs); let br = vec2(mask.x.end.rel, mask.y.end.rel); let br_abs = vec2(mask.x.end.abs, mask.y.end.abs); let top_left = floor(tl * window.dim) + floor(tl_abs); let bot_right = floor(br * window.dim) + floor(br_abs); let pos = in.clip_position.xy; if pos.x < top_left.x || pos.x > bot_right.x || pos.y < top_left.y || pos.y > bot_right.y { return color * 0.0; } return color; }