struct Rect { color: u32, radius: f32, thickness: f32, inner_radius: f32, } @group(1) @binding(0) var rects: array; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { let rect = rects[in.idx]; var color = unpack4x8unorm(rect.color); let edge = 0.5; let size = in.bot_right - in.top_left; let corner = size / 2.0; let center = in.top_left + corner; let pos = in.clip_position.xy; let dist = distance_from_rect(pos, center, corner, rect.radius); color.a *= 1.0 - smoothstep(-min(edge, rect.radius), edge, dist); if rect.thickness > 0.0 { let dist2 = distance_from_rect(pos, center, corner - rect.thickness, rect.inner_radius); color.a *= smoothstep(-min(edge, rect.inner_radius), edge, dist2); } return masked(in, color); } fn distance_from_rect(pixel_pos: vec2, rect_center: vec2, rect_corner: vec2, radius: f32) -> f32 { // vec from center to pixel let p = pixel_pos - rect_center; // vec from inner rect corner to pixel let q = abs(p) - (rect_corner - radius); return length(max(q, vec2(0.0))) - radius; }