uniform sampler2D Normal;     // light first's gbuffer
uniform sampler2D Reflection; // for reflection
uniform sampler2D Color0;

uniform float ScreenWidth;
uniform float ScreenHeight;

varying vec3 eyeToScreen;

vec2 resolution  = vec2( ScreenWidth / 4.0, ScreenHeight / 4.0 );

// Constants
float SAMPLE_AREA = 20.0 / ScreenWidth;
float DIRECTIONALITY = 20.0 / ScreenWidth;
float BIAS_MAX = 10.0;
float INV_FAR_DISTANCE = 1.0 / 2000.0; // Scales attenuation

void main()
{
  // Our pixel
  vec4 p = texture2D(Normal, gl_TexCoord[0].st);
  // Unpack
  p.xyz = 2.0 * p.xyz - 1.0;

  // Construct reflection plane from Reflection, shift texels so 1 to 1
  vec3 plane = texture2D( Reflection, gl_TexCoord[0].st * resolution ).xyz;
  plane = 2.0 * plane - 1.0;

  vec4 occlusion, bias, geometricFactor;

  float attenuation = p.w / 200.0;//(p.w + 1.0);//1.0 - attenuation;

  float totalOcclusion = 0.0;

  if(attenuation < 1.0)
  {
    attenuation = 1.0 - attenuation;

    // Project normal into 2d, scale
    vec2 n2d = (attenuation * DIRECTIONALITY) * p.xy / p.z;
    n2d += gl_TexCoord[0].st;

    // Compute offsets
    vec4 o01, o23;
    //o01.xy = reflect(offsets01.xy, plane);
    //o01.zw = reflect(offsets01.zw, plane);
    //o23.xy = reflect(offsets23.xy, plane);
    //o23.zw = reflect(offsets23.zw, plane);
    o01 = plane.xyyz;
    o23 = plane.zyyx;
    float radius = attenuation * SAMPLE_AREA;
    o01 *= radius;
    o23 *= radius;
    o01 += n2d.xyxy;
    o23 += n2d.xyxy;

    // Take samples
    vec4 o0 = texture2D(Normal, o01.xy);
    vec4 o1 = texture2D(Normal, o01.zw);
    vec4 o2 = texture2D(Normal, o23.xy);
    vec4 o3 = texture2D(Normal, o23.zw);
    // Unpack
    o0.xyz = 2.0 * o0.xyz - 1.0;
    o1.xyz = 2.0 * o1.xyz - 1.0;
    o2.xyz = 2.0 * o2.xyz - 1.0;
    o3.xyz = 2.0 * o3.xyz - 1.0;

    
    occlusion = vec4(o0.w, o1.w, o2.w, o3.w);//(1.0 / 2000.0) * 
    occlusion = p.wwww - occlusion;//(p.w / 2000.0) - attenuation;//
    bias = min(occlusion, BIAS_MAX); // Clamp to BIAS_MAX
    bias *= 1.0 / BIAS_MAX;
    bias = 1.0 - bias;
    //occlusion *= 100000.0;
    //occlusion = min(occlusion, vec4(1.0,1.0,1.0,1.0));
    //occlusion = max(vec4(0.0, 0.0, 0.0, 0.0), occlusion); // Clamp to zero
    occlusion = clamp( occlusion, 0.0, 1.0);

    geometricFactor = vec4(dot(p.xyz, o0.xyz),
                           dot(p.xyz, o1.xyz),
                           dot(p.xyz, o2.xyz),
                           dot(p.xyz, o3.xyz));
    geometricFactor = 1.0 - geometricFactor;
    //attenuation = p.wwww / 200.0;//(p.w + 1.0);//1.0 - attenuation;
    //attenuation = min(attenuation, 1.0);
    //attenuation = 1.0 - attenuation;
   
    occlusion *= bias;
    occlusion *= geometricFactor;
    occlusion *= attenuation;

    //totalOcclusion = dot(occlusion, vec4(1.0, 1.0, 1.0, 1.0));
    totalOcclusion = dot(occlusion, vec4(0.5, 0.5, 0.5, 0.5));

    totalOcclusion = min(totalOcclusion, 0.6);
    //totalOcclusion = dot(occlusion, vec4(0.25, 0.25, 0.25, 0.25));
    //totalOcclusion = dot(occlusion, vec4(0.1, 0.1, 0.1, 0.1));
    //totalOcclusion = dot(occlusion, vec4(0.03, 0.03, 0.03, 0.03));
  }
  vec4 color = texture2D(Color0, gl_TexCoord[0].st);

  gl_FragColor = (1.0 - totalOcclusion) * color;
}
