aboutsummaryrefslogtreecommitdiffstats
path: root/mpv/shaders/deband.glsl
blob: 1b2f047d07b2983c94bfcb0d20990e7876721194 (plain)
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
40
41
42
// vim: set ft=glsl:

// roughly corresponds to f3kdb parameters, which this algorithm is
// loosely inspired by
#define threshold 64
#define range     16
#define grain     24

float rand(vec2 co){
    return fract(sin(dot(co.yx, vec2(12.9898,78.233))) * 43758.5453);
}

vec4 sample(sampler2D tex, vec2 pos, vec2 tex_size)
{
    // Compute a random angle and distance
    float dist = rand(pos + vec2(random)) * range;
    vec2 pt = dist / image_size;
    float dir = rand(pos.yx - vec2(random)) * 6.2831853;
    vec2 o = vec2(cos(dir), sin(dir));

    // Sample at quarter-turn intervals around the source pixel
    vec4 ref[4];
    ref[0] = texture(tex, pos + pt * vec2( o.x,  o.y));
    ref[1] = texture(tex, pos + pt * vec2(-o.y,  o.x));
    ref[2] = texture(tex, pos + pt * vec2(-o.x, -o.y));
    ref[3] = texture(tex, pos + pt * vec2( o.y, -o.x));

    // Average and compare with the actual sample
    vec4 avg = cmul*(ref[0] + ref[1] + ref[2] + ref[3])/4.0;
    vec4 col = cmul*texture(tex, pos);
    vec4 diff = abs(col - avg);

    // Use the average if below the threshold
    col = mix(avg, col, greaterThan(diff, vec4(threshold/16384.0)));

    // Add some random noise to the output
    vec3 noise = vec3(rand(2*pos + vec2(random)),
                      rand(3*pos + vec2(random)),
                      rand(4*pos + vec2(random)));
    col.rgb += (grain/8192.0) * (noise - vec3(0.5));
    return col;
}