#version 430

layout(binding=0) uniform sampler2D srcBg;
layout(binding=1) uniform sampler2D src;

in vec2 uv;

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 rayX=0.5;
uniform float rayY=0.5;

uniform float lightZ = 2.0;
uniform float g_intensity = 1.0;
uniform float g_specRounds = 2.0;
uniform float g_specWeight = 1.5;
uniform float g_length = 1.0;

uniform float g_vignette = 1.0;

uniform float g_vignRad = 0.70;
uniform float g_preBright = 3.50;
uniform float g_postBright = 1.50;
uniform float g_exp = 2.0;

uniform float g_rotateAmp = 1.0;
uniform float g_rotatePrim = 0.45;
uniform float g_rotateSinAmp = 3.2;
uniform float g_rotateSinFreq = 10.0;

uniform float g_rotCenterX = 0.0;
uniform float g_rotCenterY = 0.0;

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;
}

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;
}


vec4 rotateXY(vec4 p, float a) {
    vec4 r = p;
    r.x = cos(a)*p.x - sin(a)*p.y;
    r.y = sin(a)*p.x + cos(a)*p.y;
    return r;
}

vec3 tonemap(vec3 color, float brightness) {
    color.xyz = pow(color.xyz, vec3(1.0))*brightness;
    color = color*(1.0+color/4.0)/(1.0+color);
    return color;
}
float aTanSafe(float y, float x) {
    float ret;
    if (x!=0.0) {
        if (x>0.0) {
            ret=atan(y/x);
        } else	{
            ret=atan(y/x)+3.141592;
        }
    } else	{
        if (y>=0.0) {
            ret=0.5*3.141592;
        } else {
            ret=-0.5*3.141592;
        }
    }
    return ret;
}

// 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);
}

void main() {
    vec4 tex = texture2D(src, coord);
    vec4 texBg = texture2D(srcBg, coord);
    vec3 bright = vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156)));
    vec4 color = pow(tex,vec4(1.0))*0.0;
    //lowp vec2 center = vec2(0.5, 0.5);
    vec2 center = vec2(rayX*1.0+0.5, rayY*1.0+0.5);
    //float intens = clamp(g_length, 0.0, 1.0);
    float maxLoops = 48.0*2.0;
    float loops=maxLoops; //clamp(abs(maxLoops*g_length), 2.0, maxLoops);
    float loopsSub=4.0;

    //raymarch version
    float eyeZ = 0.02;
    vec2 coordCen = coord-vec2(0.5, 0.5);
    vec3 eyeDir = vec3((coord-vec2(0.5, 0.5))*eyeZ*1.0, eyeZ);
    vec3 ray=eyeDir;
    vec3 image=vec3(coord-vec2(0.5, 0.5), 1.0);
    vec3 lightPos=vec3((center-vec2(0.5, 0.5)), image.z+lightZ);

    //float radial=tan(lightPosC.y/lightPosC.x);
    float radial=1.0;
    vec4 colorPiste = vec4(0.0);
    float staticOfs = 1.0*(rand(coord+vec2(0.3,0.476)*(0.0)+vec2(0.123,0.172)*g_time*0.0)-0.5);
    vec4 colorNow = vec4(0.0);
    vec4 colorPrev = vec4(0.0);
    vec4 colorPrev2 = vec4(0.0);
    vec3 eyeToLight;
    vec3 eyeAtImage;
    vec2 imagePos;
    float distCen = sqrt(dot(coordCen-center+vec2(0.5,0.5), coordCen-center+vec2(0.5,0.5)));

    for (float i=0.0; i<loops; i++) {
        lowp float sp = i/(loops-1.0);
        //sp = pow(sp, 0.750);
        eyeToLight = lightPos-ray;
        eyeAtImage = ray+vec3(eyeToLight.xy*(image.z-ray.z)/(lightPos.z-ray.z), image.z);
        imagePos = vec2(eyeAtImage.xy+vec2(0.50,0.50));
        //vec4 piste = texture2D(src, imagePos).r*texture2D(srcBg, imagePos)*radial;
        vec4 piste = vec4(texture2D(src, imagePos).r)*radial;

        piste = piste;
        piste = clamp(piste*g_intensity, 0.0, 100.0);

        colorNow = spreadSpec(piste, sp*g_specRounds+0.0)*g_specWeight+piste*1.0;
        color += colorNow; //*(radial2*0.05+0.95);
        ray = eyeDir+(image-eyeDir)*(sp*g_length+1.0-g_length+1.0/loops*staticOfs);

        vec4 k = vec4(ray, 0.0);
        k.x*=16.0/9.0;

        vec2 rotCen = vec2(g_rotCenterX*(1.0+0.5*sin(sp*4.1)), g_rotCenterY);

        k.xy -= rotCen;
        // k = rotateXY(k, sp*0.45+0.2*sin(2.0*sp));
        // k = rotateXY(k, sp*0.45+3.2*sin(2.0*sp));
        //k.xzyw = rotateXY(k.xzyw, (sp*g_rotatePrim+g_rotateSinAmp*sin(g_rotateSinFreq*sp))*g_rotateAmp);
        k = rotateXY(k, (sp*g_rotatePrim+g_rotateSinAmp*sin(g_rotateSinFreq*sp))*g_rotateAmp);
        k.xy += rotCen;
        //k.xzyw = rotateXY(k.xzyw, sp*0.0+0.010*tan(2.0*sp));
        //k.zyxw = rotateXY(k.zyxw, sp*0.20+0.110*cos(2.0*sp));
        k.x*=9.0/16.0;
        ray.xyz = k.xyz;
    }
    //color = spreadSpec(color, color.a*0.2);
    color *= 1.0/(loops-1.0);
    color *= color*1.5;
    color.rgb += colorPiste.rgb+(texBg.rgb*texBg.rgb)*1.0;
    vec3 colorNP = color.rgb;

    float vignette = clamp((1.0-sqrt(dot(coordCen, coordCen))*g_vignRad), 0.0, 1.0)+rand(coord)*0.021;
    vignette *= vignette;
    color *= vignette;
  //  color.r = pow(color.r, 0.9);
  //  color.g = pow(color.g, 0.95);
    //color *= 0.5;
    //color = tonemap(color, 1.5);
    //color = pow(color, 1.5)*1.20;
    color.rgb = tonemapUC2(color.rgb*g_preBright);
    color.rgb = clamp(color.rgb, 0.0, 10000000.0);
    color = pow(color, vec4(1.0*g_exp))*1.50*g_postBright;

    color.rgb = mix(colorNP, color.rgb, g_vignette);

    gl_FragColor = vec4(color.rgb, 1.0);
}
