summaryrefslogtreecommitdiff
path: root/shaders/bloom-down.frag.glsl
blob: 3465926d1fc31642e270fe5bc78bc5f385874ab2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#version 450

// Bloom, down (docs/effects.md G4): one step of a dual Kawase filter, a
// source half as big again sampled at five points, the first step over the
// frame through a bright pass in linear light. Written to a float target.

layout(set = 2, binding = 0) uniform sampler2D source;
layout(std140, set = 3, binding = 0) uniform BloomStep {
    // xy: a source texel; zw: a target texel.
    vec4 texels;
    // x: the bright pass's threshold on a channel's linear peak (above the
    // page's own), 0 for none (a later step); y: its soft knee.
    vec4 pass;
} u;

layout(location = 0) out vec4 o_col;

vec3 toLinear(vec3 c) {
    return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045)));
}

vec3 tap(vec2 uv) {
    vec3 c = texture(source, uv).rgb;
    if (u.pass.x <= 0.0) return c;
    c = toLinear(c);
    float peak = max(c.r, max(c.g, c.b));
    return c * smoothstep(u.pass.x, u.pass.x + u.pass.y, peak);
}

void main() {
    vec2 uv = gl_FragCoord.xy * u.texels.zw;
    vec2 h = 0.5 * u.texels.xy;
    vec3 sum = tap(uv) * 4.0;
    sum += tap(uv - h);
    sum += tap(uv + h);
    sum += tap(uv + vec2(h.x, -h.y));
    sum += tap(uv - vec2(h.x, -h.y));
    o_col = vec4(sum / 8.0, 1.0);
}