struct Globals {
time: f32,
dt: f32,
frame: f32,
cursor_x: f32,
cursor_y: f32,
cursor_pressed: f32,
_pad0: f32,
_pad1: f32,
}
@group(1) @binding(0) var<uniform> globals: Globals;
struct VertexInput {
@location(0) pos: vec2<f32>,
@location(1) uv: vec2<f32>,
@location(2) color: vec4<f32>,
@location(3) cr: vec2<f32>,
@location(4) widget_size: vec2<f32>,
@location(5) state: vec4<f32>,
}
struct VertexOutput {
@builtin(position) clip_pos: vec4<f32>,
@location(0) color: vec4<f32>,
@location(1) uv: vec2<f32>,
@location(2) cr: vec2<f32>,
@location(3) widget_size: vec2<f32>,
@location(4) state: vec4<f32>,
}
@vertex fn vs(in: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.clip_pos = vec4(in.pos, 0.0, 1.0);
out.color = in.color;
out.uv = in.uv;
out.cr = in.cr;
out.widget_size = in.widget_size;
out.state = in.state;
return out;
}
@fragment fn fs(in: VertexOutput) -> @location(0) vec4<f32> {
let uv = in.uv;
let px = fwidth(uv);
let r_px = in.cr.x;
// Work in pixel space so the SDF is correct for any aspect ratio,
// including very thin rects (dividers, progress bars, etc.)
let rw_px = 1.0 / max(px.x, 0.0001);
let rh_px = 1.0 / max(px.y, 0.0001);
let sx = (uv.x - 0.5) * rw_px;
let sy = (uv.y - 0.5) * rh_px;
let qx = abs(sx) - (rw_px * 0.5 - r_px);
let qy = abs(sy) - (rh_px * 0.5 - r_px);
let dist = length(max(vec2(qx, qy), vec2(0.0))) + min(max(qx, qy), 0.0) - r_px;
let alpha = 1.0 - smoothstep(-0.5, 0.5, dist);
var col = in.color;
col.a *= alpha;
return col;
}