uniform float time;

uniform sampler2D map_diffuse;
uniform sampler2D texRamp;
uniform sampler2D texDepth;
uniform sampler2D texAquarell;

uniform float aquaScroll;
uniform float fadeBlack;
uniform float doSSAO;
uniform float doRamp;
uniform float fft;
uniform float doRedBlur;
uniform float doGlow;
uniform float doVignette;
uniform float doAquarell;

float doColor=1.0;
float doFXAA=1.0;

float map_diffuseWidth=1.0;
float map_diffuseHeight=1.0;
#define PI    3.14159265

float width = map_diffuseWidth; //texture width
float height = map_diffuseHeight; //texture height

float near = 0.1; 
float far = 1000.0; 

float samples = 8.0;
float rings = 4.0;

varying vec2 texcoord;
float pixel,pixelh;



float readDepth(in vec2 coord)
{
    return (2.0 * near) / (far + near - texture2D(texDepth, coord ).x * (far-near));
}

float compareDepths( in float depth1, in float depth2 )
{
    float aoCap = 1.9;
    float aoMultiplier =40.0;
    float depthTolerance = 0.001;
    float aorange = 100.0;// units in space the AO effect extends to (this gets divided by the camera far range
    float diff = sqrt(clamp(1.0-(depth1-depth2) / (aorange/(far-near)),0.0,1.0));
    float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff;
    return ao;
}

vec4 getColorFXAA(vec2 coord)
{
    // The parameters are hardcoded for now, but could be
    // made into uniforms to control fromt he program.

    vec2 invtexsize=vec2(1.0/1024.0,1.0/1024.0);

    float FXAA_SPAN_MAX = 8.0;
    float FXAA_REDUCE_MUL = 1.0/8.0;
    float FXAA_REDUCE_MIN = (1.0/128.0);

    float step=1.0;

    vec3 rgbNW = texture2D(map_diffuse, coord.xy + (vec2(-step, -step)*invtexsize )).xyz;
    vec3 rgbNE = texture2D(map_diffuse, coord.xy + (vec2(+step, -step)*invtexsize )).xyz;
    vec3 rgbSW = texture2D(map_diffuse, coord.xy + (vec2(-step, +step)*invtexsize )).xyz;
    vec3 rgbSE = texture2D(map_diffuse, coord.xy + (vec2(+step, +step)*invtexsize )).xyz;
    vec3 rgbM  = texture2D(map_diffuse, coord.xy).xyz;

    vec3 luma = vec3(0.299, 0.587, 0.114);
    float lumaNW = dot(rgbNW, luma);
    float lumaNE = dot(rgbNE, luma);
    float lumaSW = dot(rgbSW, luma);
    float lumaSE = dot(rgbSE, luma);
    float lumaM  = dot( rgbM, luma);

    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));

    vec2 dir;
    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));

    float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

    float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);

    dir = min(vec2(FXAA_SPAN_MAX,  FXAA_SPAN_MAX),
          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin))*invtexsize ;

    vec3 rgbA = (1.0/2.0) * (
                texture2D(map_diffuse, coord.xy + dir * (1.0/3.0 - 0.5)).xyz +
                texture2D(map_diffuse, coord.xy + dir * (2.0/3.0 - 0.5)).xyz);
    vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
                texture2D(map_diffuse, coord.xy + dir * (0.0/3.0 - 0.5)).xyz +
                texture2D(map_diffuse, coord.xy + dir * (3.0/3.0 - 0.5)).xyz);
    float lumaB = dot(rgbB, luma);


    vec4 color=texture2D(map_diffuse,coord).rgba;

    if((lumaB < lumaMin) || (lumaB > lumaMax)){
      color.xyz=rgbA;
    } else {
      color.xyz=rgbB;
    }
    //color.a = 1.0;
    //color *= color;
    return color;
}


vec3 glow(vec3 color)
{
    //float sum=0.0;
        vec4 sum = vec4(0);

    
    float i,j;
    float count=0.0;

    for( i= -5.0 ;i < 5.0; i++)
    {
        for (j = -5.0; j < 5.0; j++)
        {
            sum += texture2D(map_diffuse,clamp(texcoord+vec2(j*pixel*1.9,i*pixelh*1.9),0.0,1.0));
            count++;
        }
    }

    sum/=count;
    vec3 ncolor=max(sum.xyz,color.xyz);
    return ncolor;
}



vec3 blur(float offsetmul)
{
    vec3 color=vec3(0,0,0);
    //vec4 col=vec4(color.xyz,1.0);
    float count=0.0;
    for (int i=1; i<3; i++)
    {
        float weight=0.2270270270;
        float offset=0.0;
        if(i==1)offset=1.3846153846;
        if(i==2)offset=3.2307692308;

        offset*=offsetmul;

        if(i==1) weight = 0.3162162162;
        if(i==2) weight = 0.0702702703;

        color += texture2D( map_diffuse, ( vec2(gl_FragCoord)+vec2(0.0, offset) )).xyz* weight;
        color += texture2D( map_diffuse, ( vec2(gl_FragCoord)+vec2( offset,0.0) )).xyz* weight;
        color += texture2D( map_diffuse, ( vec2(gl_FragCoord)+vec2(0.0, -offset) )).xyz* weight;
        color += texture2D( map_diffuse, ( vec2(gl_FragCoord)+vec2( -offset,0.0) )).xyz* weight;
    }
    return color*0.4;
}



void main(void)
{
    float depth = readDepth(texcoord);
    float d;
    pixel=1.0/2048.0;
    pixelh=1.0/1024.0;

    
    float ao=1.0;

    if(doSSAO!=0.0)
    {
        float w=pixel;
        float h=pixelh;

        float pw;
        float ph;

        float s=0.0;
        float fade = 1.0;

        for (float i = 0.0 ; i < rings; i += 1.0)
        {
            fade *= 0.5;
            for (float j = 0.0 ; j < samples*i; j += 1.0)
            {
                float step = PI*2.0 / (samples*i);
                pw = (cos(j*step)*i);
                ph = (sin(j*step)*i)*2.0;

                pw*=0.8;
                ph*=0.8;

                d = readDepth( vec2(texcoord.s+pw*w,texcoord.t+ph*h));
                ao += compareDepths(depth,d)*fade;
                s += 1.0*fade*2.0;
            }
        }

        ao /= s;
        ao = 1.0-ao;

    }

    vec3 color=vec3(1,1,1);




    // vignette
    //if(doVignette==1.0) 
    {

        // rgb vignette...
        vec2 center = vec2(width / 2.0,height/2.0);
        vec2 vd = center - vec2(texcoord);
        float distSQ = vd.x*vd.x + (vd.y*vd.y*0.5);
        //color.rgb -= distSQ*0.7;//distSQ / (1500.0*1500.0);

        if(distSQ>pixel*225.0)
        {
            distSQ=distSQ-pixel*225.0;
            color.r=texture2D(map_diffuse,vec2(clamp(texcoord.s+distSQ*20.0*pixel,0.0,1.0),clamp(texcoord.t+distSQ*20.0*pixel,0.0,1.0))).r;

            color.g=texture2D(map_diffuse,vec2(clamp(texcoord.s-distSQ*20.0*pixel,0.0,1.0),clamp(texcoord.t-distSQ*20.0*pixel,0.0,1.0))).g;
            //color.g*=getColorFXAA(vec2(texcoord)).g;
            color.b=texture2D(map_diffuse,vec2(clamp(texcoord.s-distSQ*20.0*pixel,0.0,1.0),clamp(texcoord.t-distSQ*20.0*pixel,0.0,1.0))).b;
            //color.r=1.0;
        }
        else
            color=getColorFXAA(texcoord).xyz;
        

        color.x = clamp(color.x, 0.0, 1.0);
        color.y = clamp(color.y, 0.0, 1.0);
        color.z = clamp(color.z, 0.0, 1.0);
    }


    if(doColor==1.0 && doGlow!=0.0)
    {
        color=mix(glow(color),color,(1.0-(doGlow)));
    }

    if(doRedBlur>0.0)
    {
        float redGlow=doRedBlur;

        vec2 center = vec2(width / 2.0,height/2.0);
        vec2 vd = center - vec2(texcoord);
        float distSQ = vd.x*vd.x + (vd.y*vd.y*1.35);

        if(distSQ<pixel*340.0)
        {
            vec3 ncolor=max(color,glow(color));
            ncolor.r=ncolor.r*   ( ncolor.r+ncolor.g+ncolor.b)*0.99;
            ncolor.r=min(ncolor.r,1.0);
            color=mix(ncolor,color,1.0-(redGlow*(1.0-distSQ/(pixel*340.0))));
        }
    }

    // color ramp
    if(doRamp>0.0)
    {
        color.x = clamp(color.x, 0.0, 1.0);
        color.y = clamp(color.y, 0.0, 1.0);
        color.z = clamp(color.z, 0.0, 1.0);

        float stepx=1.0;//1.0/256.0;
        float rampPosY=doRamp*(1.0/32.0);
        color.r=texture2D(texRamp,vec2(0.01+(color.r*stepx)*0.98,rampPosY)).r;
        color.g=texture2D(texRamp,vec2(0.01+(color.g*stepx)*0.98,rampPosY)).g;
        color.b=texture2D(texRamp,vec2(0.01+(color.b*stepx)*0.98,rampPosY)).b;

        color.x = clamp(color.x, 0.0, 1.0);
        color.y = clamp(color.y, 0.0, 1.0);
        color.z = clamp(color.z, 0.0, 1.0);
    }

    if(doAquarell>0.0)
    {
        vec3 aqua = texture2D( texAquarell, vec2(texcoord.s,texcoord.t+aquaScroll*-0.1) ).xyz;
        color=mix(color,color*aqua,doAquarell);
    }

    if(doVignette>0.0)
    {
        vec2 center = vec2(width / 2.0,height/2.0);
        vec2 vd = center - vec2(texcoord);
        float distSQ = vd.x*vd.x + (vd.y*vd.y*1.35);

        color.rgb -= distSQ*0.7*doVignette;//distSQ / (1500.0*1500.0);
    }

    color.r+=fft*0.6;
    color.g+=fft*0.6;
    color.b+=fft*0.6;

    if(doSSAO!=0.0)
    {
        vec3 luminance=vec3(0.0);
        color=(color*(1.0-doSSAO))+( vec3(color*mix(vec3(ao),vec3(1.0),luminance)) )*doSSAO;
    }

    color.x = clamp(color.x, 0.0, 1.0);
    color.y = clamp(color.y, 0.0, 1.0);
    color.z = clamp(color.z, 0.0, 1.0);

    color*=fadeBlack;

    gl_FragColor =vec4(color,1.0);
}



