@group(0) @binding(0) var input_sampler: sampler; @group(0) @binding(1) var input_tex: texture_2d; struct CommonUniforms { resolution: vec2, aspect_ratio: f32, time: f32, beat: f32, audio_intensity: f32, }; struct EffectParams { radius: f32, softness: f32, }; @group(0) @binding(2) var common: CommonUniforms; @group(0) @binding(3) var params: EffectParams; @vertex fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> @builtin(position) vec4 { var pos = array, 3>( vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0) ); return vec4(pos[vertex_idx], 0.0, 1.0); } @fragment fn fs_main(@builtin(position) pos: vec4) -> @location(0) vec4 { let uv = pos.xy / common.resolution; let color = textureSample(input_tex, input_sampler, uv); let d = distance(uv, vec2(0.5, 0.5)); let vignette = smoothstep(params.radius, params.radius - params.softness, d); return vec4(color.rgb * mix(1.0, vignette, common.audio_intensity), color.a); }