#version 120
//#extension GL_EXT_gpu_shader4 : require

#pragma optimize(on)

uniform sampler2D map_accumulation;
uniform sampler2D map_modifier;
uniform sampler2D map_depth;

//uniform float brightness;

uniform float contextWidth;
uniform float contextHeight;
uniform float contextX;
uniform float contextY;

uniform vec2 cameraClip;

// http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/

#define GammaCorrection(color, gamma) pow(color, 1.0 / gamma)

// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
vec3 ContrastSaturationBrightness(vec3 color, float brt, float con, float sat) {
  // Increase or decrease theese values to adjust r, g and b color channels seperately
  const float AvgLumR = 0.5;
  const float AvgLumG = 0.5;
  const float AvgLumB = 0.5;

  const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);

  vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
  vec3 brtColor = color * brt;
  vec3 intensity = vec3(dot(brtColor, LumCoeff));
  vec3 satColor = mix(intensity, brtColor, sat);
  vec3 conColor = mix(AvgLumin, satColor, con);

  return conColor;
}


void main(void) {
  vec2 texCoord = gl_FragCoord.xy;
  texCoord.x -= contextX;
  texCoord.y -= contextY;
  texCoord.x /= contextWidth;
  texCoord.y /= contextHeight;

  vec4 accum = texture2D(map_accumulation, texCoord);
//  gl_FragColor = accum;
//  return;
  vec3 base = accum.rgb;
  
  vec4 modifier = texture2D(map_modifier, texCoord);
  
  // edge blur
  if (modifier.r > 0.0) {
    vec3 smoothPixel = vec3(0);
    smoothPixel += texture2D(map_accumulation, texCoord + vec2(0, 1 / contextHeight)).xyz;
    smoothPixel += texture2D(map_accumulation, texCoord + vec2(1 / contextWidth, 0)).xyz;
    smoothPixel += texture2D(map_accumulation, texCoord + vec2(0, -1 / contextHeight)).xyz;
    smoothPixel += texture2D(map_accumulation, texCoord + vec2(-1 / contextWidth, 0)).xyz;
    smoothPixel *= 0.25;
    base = base * (1.0 - modifier.r) + smoothPixel * modifier.r;
    //base = base * (1.0 - modifier.r) + vec3(0, 0, 0) * modifier.r * 0.3 + smoothPixel * modifier.r * 0.7; // cartooney effect
    //base = base * (1.0 - modifier.r) + vec3(0, 0, 0) * modifier.r * 0.8 + smoothPixel * modifier.r * 0.2; // cartooney effect
  }

  // blur SSAO
  //float SSAO = modifier.g;
  
/*
  SSAO += texture2D(map_modifier, texCoord + vec2(0, 1 / contextWidth)).g;
  SSAO += texture2D(map_modifier, texCoord + vec2(1 / contextWidth, 0)).g;
  SSAO += texture2D(map_modifier, texCoord + vec2(0, -1 / contextWidth)).g;
  SSAO += texture2D(map_modifier, texCoord + vec2(-1 / contextWidth, 0)).g;
  SSAO /= 5.0;
*/

  float pi = 3.14159265358979;
  

  // fake convolution, because i'm a cheap bastard
  
  int SSAOBlurRes = 3;

  float resultX;
  for (float x = -SSAOBlurRes; x < SSAOBlurRes + 1; x++) {
    float falloff = pow(1 - abs(x) / (SSAOBlurRes * 1.0), 1.6);//cos(abs(x) / (SSAOBlurRes * 1.0) * pi) * 0.5 + 0.5;
    resultX += clamp(texture2D(map_modifier, texCoord + vec2(x / contextWidth, 0)).g * falloff - 0.001, 0, 1);
  }
  resultX /= float(SSAOBlurRes) * 2.0 - 1.0;

  float resultY;
  for (float y = -SSAOBlurRes; y < SSAOBlurRes + 1; y++) {
    float falloff = pow(1 - abs(y) / (SSAOBlurRes * 1.0), 1.6);//cos(abs(y) / (SSAOBlurRes * 1.0) * pi) * 0.5 + 0.5;
    resultY += clamp(texture2D(map_modifier, texCoord + vec2(0, y / contextHeight)).g * falloff - 0.001, 0, 1);
  }
  resultY /= float(SSAOBlurRes) * 2.0 - 1.0;
  
  float SSAO = clamp(sqrt((resultX + resultY) * 4.0) * 1.0 - 0.1, 0, 1);

  //base = vec3(accum.a);
  
  SSAO *= 0.6;
  //SSAO *= 2.0;

  vec3 fragColor = base * (1 - SSAO); // SSAO


  // fog
  
  float depth = texture2D(map_depth, texCoord).x;
  //float depth = texelFetch(map_depth, texCoordi, 2).x;

  // convert from non-linear to linear
  float fragDepth = -cameraClip.y / (depth - cameraClip.x);

//  vec3 fogColor = vec3(0.84, 0.98, 1.0);
  vec3 fogColor = vec3(1.0, 0.9, 0.86);
  //float fogFactor = clamp(-fragDepth * 0.003 - 0.12, 0.03, 0.1);
  float fogFactor = clamp(-fragDepth * 0.002 - 0.10, 0.03, 0.07);
  //float fogFactor = clamp(-fragDepth * 0.0006 - 0.05, 0.0, 1.0);
  //float fogFactor = clamp(-fragDepth * 0.0018 - 0.14, 0.0, 0.08);
  //float fogFactor = clamp(-fragDepth * 0.002 - 0.14, 0.0, 0.1);
  fragColor = fragColor * (1 - fogFactor) + fogColor * fogFactor;
  if (depth > 0.999) fragColor = fogColor;

  /*
  float brightness = 0;
  for (int x = 0; x < 4; x++) {
    for (int y = 0; y < 4; y++) {
      brightness += texture2D(map_accumulation, vec2(((x + 0.5) / 4) / contextWidth, ((y + 0.5) / 4) / contextHeight)).y;
    }
  }
  brightness /= 4 * 4;
  */
  
  float finalBrightness = 1.26;// * (1.5 - brightness);
  float contrast = 1.2;//1.35;
  float saturation = 1.0;//0.95;//1.06;
  float gamma = 1.8;

  finalBrightness = 1.2;// * (1.5 - brightness);
  contrast = 1.28;
  saturation = 0.95;

  finalBrightness = 1.85;// + clamp(-brightness + 0.5, -0.5, 0.5);// / clamp(brightness * 8.0 - 3.0, 0.2, 1.8);// clamp((3.0 - brightness * 4.0), 0.5, 1.5);
  contrast = 1.4;
  
  fragColor = ContrastSaturationBrightness(fragColor, finalBrightness, contrast, saturation);

  /*
  fragColor.r *= 1.1;
  fragColor.g *= 1.0;
  fragColor.b *= 0.9;
  */
  
  //fragColor = vec3(SSAO);

  fragColor.r = GammaCorrection(fragColor.r, gamma);
  fragColor.g = GammaCorrection(fragColor.g, gamma);
  fragColor.b = GammaCorrection(fragColor.b, gamma);

  fragColor = clamp(fragColor, 0, 1);

  gl_FragColor = vec4(fragColor, 0);
}
