uniform sampler2D texture0; //DEPTH
uniform sampler2D texture1; //IMAGE
//uniform sampler2D image;
//#define texture1 image

//uniform vec2 camerarange;
uniform vec2 screensize;
uniform vec3 fogColor;
//uniform float ambient_exp;

uniform float amount;
uniform float density;
uniform float radius;

const float IaoCap = 0.99;
const float IaoMultiplier=1000.0;
//const float IaoMultiplier=1.0;
const float IdepthTolerance=0.001;
const float Iaorange = 1000.0;// units in space the AO effect extends to (this gets divided by the camera far range
const float IaoScale = 0.5;



/*
float tex2d( int x, int y ){
	return (2.0 * camerarange.x) / (camerarange.y + camerarange.x - (camerarange.y-texelFetch2D( texture0, ivec2( x,y ), 0 ).a) * (camerarange.y - camerarange.x));
}
*/
float readDepth( in vec2 coord ) {

	//return (texture2D( texture1, coord ).a / (camerarange.y - camerarange.x)); //previous and original
	//return ((texture2D( texture1, coord ).a*ambient_exp) / (camerarange.y - camerarange.x)); //previous and original
	//return (texture2D( texture1, coord ).a*100000.0)/2000.0f;
	float n = 0.1; // camera z near
	float f = 16.0; // camera z far
	float z = texture2D( texture0, coord ).x;
	return (2.0 * n) / (f + n - z * (f - n));	
	//return (texture2D( texture0, coord ).x*10.0)/15.0;
}


float compareDepths( in float depth1, in float depth2 ) {
  float ao=0.0;
	//float diff = sqrt( clamp( 1.0-(depth1-depth2) / (Iaorange/(camerarange.y-camerarange.x) ),0.0,1.0) );
	if (depth2>0.0 && depth1>0.0) 
  {
	//float diff = sqrt( clamp( 1.0-(depth1-depth2),0.0,1.0) );
	float diff = sqrt( clamp( (depth1-depth2),0.0,1.0) );
	ao = min(IaoCap,max(0.0,depth1-depth2-IdepthTolerance) * IaoMultiplier) * min(diff,0.1);
	}
	/*
	if (depth2>0.0)
	   ao = min(IaoCap,max(0.0,depth1-depth2-IdepthTolerance) * IaoMultiplier);
	*/
	return ao;
}

void main(void)
{
	vec2 texCoord = gl_FragCoord.xy/screensize;
	float frag_depth = texture2D( texture0, texCoord ).x;

	if (frag_depth==1.0)
	{
		discard;
		//gl_FragDepth =10000.0;return;
	}
	
	float depth = readDepth( texCoord );
	float d;
	/*
	float pw = 10.0 / screensize.x;
	float ph = 10.0 / screensize.y;
	*/
  
  //float radius = 5.0;
  
	float pw = radius / screensize.x;
	float ph = radius / screensize.y;

	float aoCap = IaoCap;

	float ao = 0.0;
	
	//float aoMultiplier=10000.0;
	float aoMultiplier= IaoMultiplier;
	float depthTolerance = IdepthTolerance;
	float aoscale= IaoScale;

	d=readDepth( vec2(texCoord.x+pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x+pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
    
    
	d=readDepth( vec2(texCoord.x+pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;    
        
	
	pw*=2.0;
	ph*=2.0;
	aoMultiplier/=2.0;
	aoscale*=1.2;
	
	d=readDepth( vec2(texCoord.x+pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x+pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
    
	d=readDepth( vec2(texCoord.x+pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;    
    

	pw*=2.0;
	ph*=2.0;
	aoMultiplier/=2.0;
	aoscale*=1.2;
	
	d=readDepth( vec2(texCoord.x+pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x+pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
	
  	d=readDepth( vec2(texCoord.x+pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;    

    
	pw*=2.0;
	ph*=2.0;
	aoMultiplier/=2.0;
	aoscale*=1.2;
	
	d=readDepth( vec2(texCoord.x+pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x+pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;
    
    d=readDepth( vec2(texCoord.x+pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x-pw,texCoord.y));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y+ph));
	ao+=compareDepths(depth,d)/aoscale;
	d=readDepth( vec2(texCoord.x,texCoord.y-ph));
	ao+=compareDepths(depth,d)/aoscale;


	// ao/=4.0;
    ao/=8.0;
    ao = 1.0-ao;
    //ao = 1.5*ao;

    ao = pow(ao, density);
    
    ao = clamp( ao, 0.0, 1.0 );
    //ao = ao*ao;
    
	vec4 color = texture2D(texture1,texCoord);

  //vec3 aocolor = vec3(0.1, 0.17, 0.4);  
  vec3 aocolor = vec3(0.1, 0.0, 0.2);  

  gl_FragColor = vec4( mix(color.rgb, mix(aocolor.rgb, color.rgb, ao), amount), color.a);
      
  //gl_FragColor = vec4(vec3(texture2D( texture0, texCoord ).xyz), 1.0);
  //gl_FragColor = color;
  //gl_FragColor = vec4(1,0,0,1);
  	
	//gl_FragColor = vec4( mix(fogColor, vec3(ao, ao, ao) * color.rgb, color.a), 1.0);
  //gl_FragColor = vec4(ao, ao, ao, 1.0);
}
