Files
ringa/src/shader.wgsl
T
swaits dacc631d57 fix: use rounded-square SDF for cursor avoidance hole
Replace Chebyshev distance with a rounded box SDF for the cursor
avoidance shape. Eliminates diagonal artifacts where the sharp corners
of a pure square distance field intersected the ring geometry.
2026-04-07 12:28:38 -06:00

76 lines
2.4 KiB
WebGPU Shading Language

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<uniform> 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);
}