#version 450 core // Scatter-as-gather bokeh blur over a golden-angle disc at half resolution. // Samples farther than the center cannot spread over it (keeps in-focus // subjects from smearing into the background); nearer samples can (near // field blur bleeds over sharp areas like a real lens). in vec2 vUV; layout(binding = 0) uniform sampler2D uHalf; uniform float uMaxRadius; uniform vec2 uTexel; layout(location = 0) out vec4 fragColor; const int SAMPLES = 64; void main() { vec4 c0 = texture(uHalf, vUV); float cc = c0.a; vec3 acc = c0.rgb; float wsum = 1.0; float nearCoverage = 0.0; for (int i = 0; i < SAMPLES; ++i) { float r = sqrt((float(i) + 0.5) / float(SAMPLES)) * uMaxRadius; float th = float(i) * 2.39996323; vec2 o = vec2(cos(th), sin(th)) * r; vec4 s = textureLod(uHalf, vUV + o * uTexel, 0.0); float cs = s.a; float e = abs(cs); if (cs > cc) e = min(e, abs(cc)); float w = clamp(e * uMaxRadius - r + 1.0, 0.0, 1.0); acc += s.rgb * w; wsum += w; if (cs < 0.0) nearCoverage = max(nearCoverage, w * abs(cs)); } fragColor = vec4(acc / wsum, max(abs(cc), nearCoverage)); }