#version 430

layout(binding=0) uniform sampler2D srcBg;
layout(location = 0) out vec4 frag;
layout(location = 1) out vec4 frag2;

uniform float g_time;

precision highp float;
in highp vec2 coord;

uniform float g_vignette = 1.0;
uniform float g_radius = 0.70;
uniform float g_noise = 1.0;
uniform float g_posX = 0.0;
uniform float g_posY = 0.0;
uniform float g_aspect = 1.0;
uniform float g_scale = 1.0;
uniform float g_edgeChroma = 0.0;
uniform float g_edgeChromaHueFreq = 1.0;
uniform float g_edgeChromaHueOfs = 0.0;
uniform float g_edgeChromaClearRadius = 0.0;

uniform float g_edgeChromaDistortX = 0.0;
uniform float g_edgeChromaDistortY = 0.0;

uniform float g_edgeChromaDistortOfsX = 0.0;
uniform float g_edgeChromaDistortOfsY = 0.0;

uniform float g_edgeChromaDistortFreqX = 0.0;
uniform float g_edgeChromaDistortFreqY = 0.0;

uniform float g_specWeight = 1.0;
uniform float g_origWeight = 1.0;

uniform float g_vignetteRealSpecSpacing = 1.0;


vec3 tonemapUC2(vec3 x) {
    float A = 0.15;
    float B = 0.50;
    float C = 0.10;
    float D = 0.20;
    float E = 0.02;
    float F = 0.30;
    return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}

// google glsl rand gave this, thanks and credit flies to
// http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}


//vec3 spreadSpec3(vec3 c, float sp) {
//    sp = fract(sp);
//    c.r *= smoothstep(1.0, 0.0, (1.0-sp)*1.0);
//    c.g *= smoothstep(1.0, 0.0, abs((sp-0.5)*2.0));
//    c.b *= smoothstep(1.0, 0.0, sp*1.0);
//    return c;
//}

vec4 spreadSpec(vec4 c, float sp) {
    sp = fract(sp);
    c.r *= smoothstep(1.0, 0.0, (1.0-sp)*1.0);
    c.g *= smoothstep(1.0, 0.0, abs((sp-0.5)*2.0));
    c.b *= smoothstep(1.0, 0.0, sp*1.0);
    return c;
}


vec3 spreadSpec3(vec3 c, float sp) {
    vec3 res = c;
    sp = fract(sp);

    float widthM = g_vignetteRealSpecSpacing;
    float width = 1.0/(widthM/2.0);
    sp = -widthM/2.0+sp*(1.0+widthM/2.0);
                c.b *= 1.0;
                c.g *= 1.0;
                c.r *= 1.0;
    res.b = smoothstep(1.0, 0.0, abs((sp-0.0)*width))*c.b+smoothstep(1.0, 0.0, abs((sp-1.5)*width))*c.b;
    res.g = smoothstep(1.0, 0.0, abs((sp-0.5)*width))*c.g;
    res.r = smoothstep(1.0, 0.0, abs((sp-1.0)*width))*c.r+smoothstep(1.0, 0.0, abs((sp-(-0.5))*width))*c.r;

//    res.a = c.a;
    return res;
}


//vec4 spreadSpec(vec4 c, float sp) {
//    vec4 res;
//    //res.r = mix(c.r, 0.0, (1.0-sp)*1.0);
//    //res.g = mix(c.g, 0.0, abs((sp-0.5)*2.0));
//    //res.b = mix(c.b, 0.0, sp*1.0);

//    sp = fract(sp);

//    res.r = smoothstep(1.0, 0.0, (1.0-sp)*1.0)*c.r;
//    res.g = smoothstep(1.0, 0.0, abs((sp-0.5)*2.0))*c.g;
//    res.b = smoothstep(1.0, 0.0, sp*1.0)*c.b;

//    //            float widthM = 1.50;
//    //            float width = 1.0/(widthM/2.0);
//    //            sp = -widthM/2.0+sp*(1.0+widthM/2.0);
//    ////            c.b *= 0.3;
//    ////            c.g *= 0.6;
//    ////            c.r *= 1.0;
//    //            res.b = smoothstep(1.0, 0.0, abs((sp-0.0)*width))*c.b+smoothstep(1.0, 0.0, abs((sp-1.5)*width))*c.b;
//    //            res.g = smoothstep(1.0, 0.0, abs((sp-0.5)*width))*c.g;
//    //            res.r = smoothstep(1.0, 0.0, abs((sp-1.0)*width))*c.r+smoothstep(1.0, 0.0, abs((sp-(-0.5))*width))*c.r;

//    res.a = c.a;
//    return res;
//}


void main() {
    vec4 texBg = texture2D(srcBg, coord);
    vec3 color; // = texBg.rgb*texBg.rgb;

    vec2 coordCen = coord-vec2(0.5, 0.5);

    coordCen.x += -g_posX*9.0/16.0;
    coordCen.y += -g_posY*9.0/16.0;


    coordCen.x *= g_aspect;
    coordCen *= g_scale*9.0/16.0;


    float dista = (1.0-sqrt(dot(coordCen, coordCen))/(g_radius+0.001));

    float staticOfs = (rand(coord)-0.5);


  //  if (abs(g_edgeChroma) > 0.0001) {
        float numLoops = 1.0*(1.0+10.0*abs(g_edgeChroma*3.0+g_edgeChromaDistortX+g_edgeChromaDistortY));
        //numLoops = clamp(numLoops, 1.0, 64.0);
        numLoops = clamp(numLoops, 1.0, 64.0*1.5);
        color.rgb = vec3(0.0);
        float fi=0.0;
        for (fi=0.0; fi<numLoops; fi+=1.0) {
            float sp = fi/numLoops+1.0/numLoops*staticOfs;

            float edgeChromaAmount = sp*g_edgeChroma;
            vec2 dir = -coordCen;
            float distToCen = length(dir)/(g_radius+0.001);

            dir.x = sin(dir.x*g_edgeChromaDistortFreqX+g_edgeChromaDistortOfsX)*g_edgeChromaDistortX+smoothstep(1.0, 0.0, g_edgeChromaDistortX)*dir.x;
            dir.y = sin(dir.y*g_edgeChromaDistortFreqY+g_edgeChromaDistortOfsY)*g_edgeChromaDistortY+smoothstep(1.0, 0.0, g_edgeChromaDistortY)*dir.y;

            edgeChromaAmount *= clamp(distToCen-g_edgeChromaClearRadius, 0.0, 100000.0);

            dir = coord+dir*edgeChromaAmount;

            vec3 colTemp = texture2D(srcBg, dir).rgb;
          //  vec3 colTemp = vec3(0.1, 0.0, 0.0);
            colTemp *= colTemp;

            color.rgb += (g_specWeight*spreadSpec3(colTemp, sp*g_edgeChromaHueFreq+g_edgeChromaHueOfs)+colTemp*g_origWeight)/numLoops;
         //   color.rgb += colTemp.rgb/numLoops;
        }
  //  }

    coordCen.x *= 16.0/9.0;
    dista = (1.0-sqrt(dot(coordCen, coordCen))/(g_radius*1.0+0.001));

    color *= g_vignette;

    float vignette = clamp(dista, 0.0, 1.0)+rand(coord)*0.02*g_noise;
    vignette *= vignette;
    color *= vignette;


    color = pow(color, vec3(0.5));

    //color.r = 1.0;

    frag = vec4(color, 1.0);
    frag2 = vec4(0.0, 0.0, 0.0, 0.0);

//    gl_FragColor = vec4(color, 1.0);
}
