// the equalizer's curve: a line through the sliders' knobs, eased between neighbours, // shivering up and down with the music, a faint wide stroke under a thin bright one. // island.rs fills the values: // 0: x of the first point, width the points span, steps, bands // 1: levels given, glow width, line width, unused // 2: glow colour, 3: line colour (plain, 0 to 1) // 4-6: the knobs' heights, one per band // 7-15: the live levels, low to high, 0 to 1 const PI: f32 = 3.14159265359; fn knob(band: u32) -> f32 { return values[4u + band / 4u][band % 4u]; } fn loudness(along: f32) -> f32 { let count = u32(values[1].x); if count == 0u { return 0.0; } let index = min(u32(round(along * f32(count - 1u))), count - 1u); return values[7u + index / 4u][index % 4u]; } // the curve's point number `step`, as island.rs placed it on the old canvas fn point(step: u32) -> vec2 { let steps = values[0].z; let bands = u32(values[0].w); let along = f32(step) / steps; let place = along * f32(bands - 1u); let band = min(u32(floor(place)), bands - 2u); let eased = (1.0 - cos((place - f32(band)) * PI)) / 2.0; let shiver = loudness(along) * 9.0 * select(0.6, -1.0, step % 2u == 0u); return vec2(values[0].x + along * values[0].y, mix(knob(band), knob(band + 1u), eased) + shiver); } fn segment(p: vec2, a: vec2, b: vec2) -> f32 { let ab = b - a; let t = clamp(dot(p - a, ab) / max(dot(ab, ab), 1e-5), 0.0, 1.0); return length(p - a - ab * t); } fn stroke(d: f32, width: f32, pixel: f32) -> f32 { return clamp((width / 2.0 - d) / pixel + 0.5, 0.0, 1.0); } @fragment fn main(@location(0) uv: vec2) -> @location(0) vec4 { let p = uv * size; let pixel = max(fwidth(p.x), 1e-4); let steps = u32(values[0].z); // the segment under this pixel and its neighbours: a stroke can't reach further let here = i32(floor((p.x - values[0].x) / max(values[0].y, 1e-5) * values[0].z)); var d = 1e9; for (var offset = -1; offset <= 1; offset++) { let first = clamp(here + offset, 0, i32(steps) - 1); d = min(d, segment(p, point(u32(first)), point(u32(first) + 1u))); } let glow = vec4(values[2].rgb * values[2].a, values[2].a) * stroke(d, values[1].y, pixel); let line = vec4(values[3].rgb * values[3].a, values[3].a) * stroke(d, values[1].z, pixel); let color = line + glow * (1.0 - line.a); if color.a <= 0.0 { return vec4(0.0); } return vec4(color.rgb / color.a, color.a); }