const BLUR: &str = r#"
void main() {
vec2 uv = gl_FragCoord.xy / u_res;
vec4 src = texture(tex, uv);
vec4 res = src;
float r = p0 * u_scale;
if (r >= 0.5) {
// ponytail: one-pass Vogel disc instead of a separable Gaussian - if quality matters,
// add a direction knob and let gpu.rs run this program twice (H then V).
vec4 acc = vec4(0.0);
float wsum = 0.0;
for (int i = 0; i < 24; i++) {
float fi = float(i) + 0.5;
float rad = sqrt(fi / 24.0) * r;
float ang = fi * 2.39996323;
float w = exp(-2.0 * rad * rad / (r * r));
acc += texture(tex, uv + vec2(cos(ang), sin(ang)) * rad / u_res) * w;
wsum += w;
}
res = acc / wsum;
}
float m = u_has_mask > 0.5 ? texture(u_mask, uv).r : 1.0;
out_color = mix(src, res, m);
}
"#;Expand description
24-tap Vogel disc, Gaussian-weighted; radius p0 project px.