36 lines
1.2 KiB
GLSL
36 lines
1.2 KiB
GLSL
#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));
|
|
}
|