struct Uniforms { screen_size: vec2f, cursor_pos: vec2f, // Outer rounded rect: inset from screen edge outer_inset: f32, outer_corner_radius: f32, // Inner rounded rect: inset further by ring_width ring_width: f32, inner_corner_radius: f32, // Glow glow_spread: f32, // Cursor avoidance cursor_avoid_radius: f32, cursor_avoid_falloff: f32, // Color temperature (linear RGB) _pad: f32, color: vec3f, _pad2: f32, } @group(0) @binding(0) var u: Uniforms; @vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f { let x = f32(i32(i) / 2) * 4.0 - 1.0; let y = f32(i32(i) % 2) * 4.0 - 1.0; return vec4f(x, y, 0.0, 1.0); } // Rounded rectangle SDF (Inigo Quilez). fn rounded_rect_sdf(p: vec2f, h: vec2f, r: f32) -> f32 { let q = abs(p) - h + vec2f(r); return length(max(q, vec2f(0.0))) + min(max(q.x, q.y), 0.0) - r; } @fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f { let center = u.screen_size / 2.0; let p = pos.xy - center; // Outer rounded rect let outer_half = center - vec2f(u.outer_inset); let sd_outer = rounded_rect_sdf(p, outer_half, u.outer_corner_radius); // Inner rounded rect let inner_half = outer_half - vec2f(u.ring_width); let sd_inner = rounded_rect_sdf(p, inner_half, u.inner_corner_radius); // Ring: inside outer AND outside inner = solid at full brightness var alpha: f32; if sd_outer <= 0.0 && sd_inner >= 0.0 { alpha = 1.0; } else if sd_outer > 0.0 { // Gaussian glow fading outward let t = sd_outer / u.glow_spread; alpha = exp(-3.0 * t * t); } else { // Gaussian glow fading inward let t = -sd_inner / u.glow_spread; alpha = exp(-3.0 * t * t); } // Cursor avoidance — rounded square (box SDF with corner rounding) let cursor_half = vec2f(u.cursor_avoid_radius); let cursor_corner = u.cursor_avoid_radius * 0.3; // 30% rounding smooths the diagonals let cursor_sd = rounded_rect_sdf(pos.xy - u.cursor_pos, cursor_half, cursor_corner); if cursor_sd < u.cursor_avoid_falloff { let t_avoid = clamp(cursor_sd / u.cursor_avoid_falloff, 0.0, 1.0); alpha *= t_avoid * t_avoid * (3.0 - 2.0 * t_avoid); } // Premultiplied color output let rgb = u.color * alpha; return vec4f(rgb, alpha); }