// synthesizes triangle and line vertices per-bin from a storage buffer, with mirrors as an instance axis. struct Globals { bounds: vec2, // full canvas in pixels base: vec2, // building rect in pixels, 0.55w by 0.5h when mirrored num_bins: u32, num_channels: u32, flags: u32, // 1=glass, 2=mirrored, 4=inverted, 8=stereo fade_bins: u32, // count of tail bins fading toward zero alpha when mirrored hue_param: f32, contrast: f32, brightness: f32, _pad0: f32, unified_hue: f32, unified_sat: f32, unified_val: f32, _pad1: f32, }; struct Bin { log_x: f32, // 0..1 along the log-frequency axis visual_norm: f32, // smoothed dB on a 0..1 scale primary_norm: f32, // primary dB on a 0..1 scale bright_mod: f32, alpha_mod: f32, hue: f32, sat: f32, val: f32, splash: f32, // 0..1 suppressed-energy color splash }; // 5/12 hue-wheel rotation per full splash, cycling all 12 wheel segments. const SPLASH_HUE_OFFSET: f32 = 0.4166667; @group(0) @binding(0) var globals: Globals; @group(0) @binding(1) var bins: array; struct VertexOut { @builtin(position) clip_position: vec4, @location(0) color: vec4, }; fn flag(bit: u32) -> bool { return (globals.flags & bit) != 0u; } fn hsv_to_rgb(h: f32, s: f32, v: f32) -> vec3 { let hh = fract(fract(h) + 1.0) * 6.0; let i = floor(hh); let f = hh - i; let p = v * (1.0 - s); let q = v * (1.0 - s * f); let t = v * (1.0 - s * (1.0 - f)); let ii = i32(i) % 6; if (ii == 0) { return vec3(v, t, p); } if (ii == 1) { return vec3(q, v, p); } if (ii == 2) { return vec3(p, v, t); } if (ii == 3) { return vec3(p, q, v); } if (ii == 4) { return vec3(t, p, v); } return vec3(v, p, q); } fn final_brightness(b: Bin) -> f32 { let base_b = sqrt(b.primary_norm); let bm = b.bright_mod; var b_mult: f32; if (bm >= 0.0) { b_mult = 1.0 + bm; } else { b_mult = 1.0 / (1.0 - bm * 2.0); } return clamp(base_b * b_mult * globals.brightness, 0.0, 1.0); } fn alpha_for(b: Bin, fade: f32) -> f32 { let am = b.alpha_mod; var a_mult: f32; if (am >= 0.0) { a_mult = 1.0 + am * 0.5; } else { a_mult = 1.0 + am; } a_mult = max(a_mult, 0.1); var a = 0.4 + (b.primary_norm - 0.5) * globals.contrast; a = clamp(a * a_mult, 0.0, 1.0); return a * fade; } fn dyn_rgb(b: Bin) -> vec3 { let fb = final_brightness(b); let hue = fract(b.hue + SPLASH_HUE_OFFSET * b.splash); let s = clamp((b.sat + 0.4 * b.splash) * globals.hue_param, 0.0, 1.0); let v = clamp((b.val + 0.4 * b.splash) * fb, 0.0, 1.0); return hsv_to_rgb(hue, s, v); } fn fill_rgb(b: Bin) -> vec3 { if (flag(1u)) { let fb = final_brightness(b); let hue = fract(globals.unified_hue + SPLASH_HUE_OFFSET * b.splash); let s = clamp(globals.unified_sat + 0.4 * b.splash, 0.0, 1.0); let v = clamp((globals.unified_val + 0.4 * b.splash) * fb, 0.0, 1.0); return hsv_to_rgb(hue, s, v); } return dyn_rgb(b); } fn channel_offset(rgb: vec3, ch: u32) -> vec3 { if (ch == 1u && flag(8u)) { let off = 40.0 / 255.0; return vec3( max(rgb.x - off, 0.0), max(rgb.y - off, 0.0), min(rgb.z + off, 1.0), ); } return rgb; } fn fade_factor(seg: u32) -> f32 { if (!flag(2u)) { return 1.0; } let from_end = i32(globals.num_bins) - 2 - i32(seg); if (from_end < i32(globals.fade_bins)) { var f = f32(from_end + 1) / f32(globals.fade_bins + 1u); f = f * f; return max(f, 0.0); } return 1.0; } fn pixel_to_clip(p: vec2) -> vec4 { let nx = (p.x / max(globals.bounds.x, 1.0)) * 2.0 - 1.0; let ny = 1.0 - (p.y / max(globals.bounds.y, 1.0)) * 2.0; return vec4(nx, ny, 0.0, 1.0); } fn mirror_xform(iid: u32, p: vec2) -> vec2 { var sx: f32 = 1.0; var sy: f32 = 1.0; var tx: f32 = 0.0; var ty: f32 = 0.0; if (iid == 1u) { sx = -1.0; tx = globals.bounds.x; } else if (iid == 2u) { sy = -1.0; ty = globals.bounds.y; } else if (iid == 3u) { sx = -1.0; sy = -1.0; tx = globals.bounds.x; ty = globals.bounds.y; } return vec2(p.x * sx + tx, p.y * sy + ty); } @vertex fn vs_fill(@builtin(vertex_index) vid: u32, @builtin(instance_index) iid: u32) -> VertexOut { let nb = globals.num_bins; let segs = max(nb, 1u) - 1u; let per_ch = segs * 6u; let ch = vid / per_ch; let in_ch = vid % per_ch; let seg = in_ch / 6u; let corner = in_ch % 6u; var i = seg; var j = seg + 1u; if (flag(4u)) { i = nb - 1u - seg; j = nb - 2u - seg; } let base = ch * nb; let bi = bins[base + i]; let bj = bins[base + j]; let w = globals.base.x; let h = globals.base.y; let x1 = bi.log_x * w; let x2 = bj.log_x * w; let y1 = h - bi.visual_norm * h; let y2 = h - bj.visual_norm * h; let anchor_y = h; var p: vec2; switch corner { case 0u: { p = vec2(x1, anchor_y); } case 1u: { p = vec2(x1, y1); } case 2u: { p = vec2(x2, y2); } case 3u: { p = vec2(x1, anchor_y); } case 4u: { p = vec2(x2, y2); } default: { p = vec2(x2, anchor_y); } } let pw = mirror_xform(iid, p); var rgb = fill_rgb(bi); rgb = channel_offset(rgb, ch); let a = alpha_for(bi, fade_factor(seg)); var out: VertexOut; out.clip_position = pixel_to_clip(pw); out.color = vec4(rgb, a); return out; } @vertex fn vs_line(@builtin(vertex_index) vid: u32, @builtin(instance_index) iid: u32) -> VertexOut { let nb = globals.num_bins; let per_ch = nb * 2u; let ch = vid / per_ch; let in_ch = vid % per_ch; let seg = in_ch / 2u; let endpoint = in_ch % 2u; var i = seg; if (flag(4u)) { i = nb - 1u - seg; } let bi = bins[ch * nb + i]; let w = globals.base.x; let h = globals.base.y; let x = bi.log_x * w; let y_top = h - bi.visual_norm * h; let anchor_y = h; var p: vec2; if (endpoint == 0u) { p = vec2(x, anchor_y); } else { p = vec2(x, y_top); } let pw = mirror_xform(iid, p); var rgb = dyn_rgb(bi); rgb = channel_offset(rgb, ch); var a = alpha_for(bi, fade_factor(seg)); a = min(a, 0.9); var out: VertexOut; out.clip_position = pixel_to_clip(pw); out.color = vec4(rgb, a); return out; } // cepstrum line strip in pixel space. struct CepIn { @location(0) position: vec2, @location(1) color: vec4, }; @vertex fn vs_cep(in: CepIn) -> VertexOut { var out: VertexOut; out.clip_position = pixel_to_clip(in.position); out.color = in.color; return out; } @fragment fn fs_main(in: VertexOut) -> @location(0) vec4 { return in.color; }