#version 120
#extension GL_EXT_gpu_shader4 : require

uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D posMap;
uniform sampler2D SSAOMap; 
uniform float mapResX; // input texture resolution
uniform float mapResY;
uniform float onlySSAO;
uniform float xDirection;

float falloff(in float x, in float sigma_sqr)
{
   float g = max(0.001, 1.0 - x*x / sigma_sqr);
   return g*g*g;
}

void main()
{	
   if(texture2D(SSAOMap, gl_TexCoord[0].xy).r < 0.0)
   {
      gl_FragColor = texture2D(colorMap, gl_TexCoord[0].xy);
   }
   else
   {
      if(onlySSAO > 0.9)
      {
         gl_FragColor = texture2D(SSAOMap, gl_TexCoord[0].xy);

         vec3 posLeft   = texelFetch2D(posMap, ivec2(gl_FragCoord.xy)-ivec2(1,0), 0).rgb; 
         vec3 posRight  = texelFetch2D(posMap, ivec2(gl_FragCoord.xy)+ivec2(1,0), 0).rgb; 
         vec3 posTop    = texelFetch2D(posMap, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0).rgb; 
         vec3 posBottom = texelFetch2D(posMap, ivec2(gl_FragCoord.xy)-ivec2(0,1), 0).rgb; 
         vec3 thisPos   = texelFetch2D(posMap, ivec2(gl_FragCoord.xy), 0).rgb; 

         float eps = 1.0;
         if(distance(thisPos.rgb, posLeft) > eps
            || distance(thisPos.rgb, posRight) > eps
            || distance(thisPos.rgb, posTop) > eps
            || distance(thisPos.rgb, posBottom) > eps
            )
            gl_FragColor *= 0.7;
      }
      else
      {
         vec2 texCoord = gl_TexCoord[0].xy;
         int filterRadius = 8;
         vec4 weightedResult = vec4(0.0);
         float weightSum = 0.0;
         vec2 dir;
         if(xDirection > 0.9)
            dir = vec2(1.0 / mapResX, 0);
         else
            dir = vec2(0, 1.0 / mapResY);

         vec3 thisPos = texture2D(posMap, texCoord).rgb;
         vec3 thisNormal = texture2D(normalMap, texCoord).rgb;

         for(int j = -filterRadius; j <= filterRadius; j++) {

            vec2 sampleTexCoord = texCoord + float(j) * dir;
            vec4 sample         = texture2D(SSAOMap, sampleTexCoord).rgba;
            vec3 samplePosition = texture2D(posMap, sampleTexCoord).rgb;
            vec3 sampleNormal   = texture2D(normalMap, sampleTexCoord).rgb;

            float weight = falloff(max(0.0, 1.0 - dot(thisNormal, sampleNormal)), 0.3)
               * falloff(distance(thisPos, samplePosition), 0.49);

            weightSum += weight;
            weightedResult += weight * sample;

         }

         vec4 result = weightedResult / weightSum;         // average of valid pixels	
         if(xDirection < 0.9)
         {
            gl_FragColor = result * texture2D (colorMap, gl_TexCoord[0].xy);
            gl_FragColor = mix(gl_FragColor, vec4(0.6, 0.6, 0.6, 1.0) * result, 0.8);
			gl_FragColor = mix(gl_FragColor, texture2D (posMap, gl_TexCoord[0].xy)/3.0, 0.03);
            gl_FragColor *= 1.2;
            //gl_FragColor.rgb -= vec3(0.2);
			//if(thisPos.z < -27.0)
		 //   gl_FragColor += vec4(0, 0, max(0, gl_FragCoord.y-300) / 300.0, 0);
         }
         else
            gl_FragColor = result;

      }
   }
   gl_FragColor.a = 0.0;
}