
const float PI = 3.141592653589793;

// --------------------------------------------------------------------
// Gaussian-Blur
// --------------------------------------------------------------------

const float INV_PI = 0.3183098861837907;

float gaussianSpaceWeight(in vec2 xy, in float sigma)
{
    float twoSqSigma = 1.0 / (2.0 * sigma * sigma);
    return exp(-dot(xy,xy) * twoSqSigma) * twoSqSigma * INV_PI;
}

vec3 gaussianBlur(in vec2 uv, in sampler2D tex, in float sigma)
{
    int radius = int(ceil(5.0 * sigma)*0.5);

    vec2 scale = 1.0 / vec2(textureSize(tex, 0));

    vec3 sum = vec3(0);

    for (int x = -radius; x <= radius; x++)
    for (int y = -radius; y <= radius; y++)
    {
        vec2 off = vec2(x, y) * scale;

        float w = gaussianSpaceWeight(vec2(x, y), sigma);

        vec3 col = texture(tex, uv + off).rgb * w;

        sum += col;
    }

    return sum;
}

// --------------------------------------------------------------------
// Tent-Blur
// --------------------------------------------------------------------

float tentKernel(in vec2 xy, in float r)
{
    return (1.0 - abs(xy.x/r)) * (1.0 - abs(xy.y/r)) / (r*r);
}

vec3 tentBlur(in vec2 uv, in sampler2D tex, in int r)
{

    vec2 scale = 1.0 / vec2(textureSize(tex, 0));

    vec3 sum = vec3(0);

    for (int x = -r; x <= r; x++)
    for (int y = -r; y <= r; y++)
    {
        vec2 off = vec2(x, y) * scale;

        float w = tentKernel(vec2(x, y), float(r));

        vec3 col = texture(tex, uv + off).rgb * w;

        sum += col;
    }

    return sum;
}

// --------------------------------------------------------------------
// Tent-Blur
// --------------------------------------------------------------------

vec3 boxBlur(in vec2 uv, in sampler2D tex, in int r)
{

    vec2 scale = 1.0 / vec2(textureSize(tex, 0));

    vec3 sum = vec3(0);

    for (int x = -r; x <= r; x++)
    for (int y = -r; y <= r; y++)
    {
        vec2 off = vec2(x, y) * scale;

        vec3 col = texture(tex, uv + off).rgb;

        sum += col;
    }

    return sum / float((2*r+1)*(2*r+1));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    vec3 col;

    if (uv.x > 0.75)
    {
        col = gaussianBlur(uv, iChannel0, 4.0);
    }
    else if (uv.x > 0.5 && uv.x < 0.75)
    {
        col = tentBlur(uv, iChannel0, 8);
    }
    else if(uv.x > 0.25 && uv.x < 0.5)
    {
        col = boxBlur(uv, iChannel0, 4);
    }
    else
    {
        col = texture(iChannel0, uv).rgb;
    }

    float border = abs(sin(uv.x*PI*4.0));

    col *= step(0.03, border);

    // Output to screen
    fragColor = vec4(col,1.0);
}
