#version 330 core

uniform sampler2D depth_buffer;
uniform sampler2D rotate;

uniform vec4 CameraRange; // near, far, (far - near), far*near
uniform vec2 ScreenSize;
//uniform float radius;
uniform float attBias;
//uniform float attScale;
uniform float attPower;
uniform float depthScale;

// units in space the AO effect extends to (this gets divided by the camera far range)
#define aorange depthScale

#define depthTolerance attBias

in vec2 uv;

layout (location = 0) out vec4 frag_color;

float readDepth(in vec2 coord)
{
	return (2.0*CameraRange.x) / (CameraRange.y + CameraRange.x - texture(depth_buffer, coord).x * (CameraRange.y - CameraRange.x));
}

float compareDepths(in float depth1, in float depth2, in float aoMultiplier)
{
	float diff = sqrt( clamp(1.0 - (depth1 - depth2) / (aorange/CameraRange.z), 0.0, 1.0) );
	float ao = min( max(depth1 - depth2 - depthTolerance, 0.0)*aoMultiplier, 1.0) * diff;
	return ao;
}

void main()
{
	float od = readDepth(uv);
	
	float pw = (1.0 / ScreenSize.x)*2.0;
	float ph = (1.0 / ScreenSize.y)*2.0;

	float ao = 0.0;
	float aoMultiplier = 10000.0;
	float aoscale = 1.0;

	float d = readDepth( vec2(uv.x+pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x+pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	pw *= 2.0;
	ph *= 2.0;
	aoMultiplier /= 2.0;
	aoscale *= 1.2;

	d = readDepth( vec2(uv.x+pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x+pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	pw *= 2.0;
	ph *= 2.0;
	aoMultiplier /= 2.0;
	aoscale *= 1.2;

	d = readDepth( vec2(uv.x+pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x+pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	pw *= 2.0;
	ph *= 2.0;
	aoMultiplier /= 2.0;
	aoscale *= 1.2;

	d = readDepth( vec2(uv.x+pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x-pw,uv.y+ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x+pw,uv.y-ph));
	ao += compareDepths(od,d,aoMultiplier) / aoscale;

	d = readDepth( vec2(uv.x - pw, uv.y - ph) );
	ao += compareDepths(od,d,aoMultiplier)/aoscale;

	ao /= 16.0;

	frag_color = vec4(0.0, 0.0, 0.0, pow(1.0 - ao, attPower));
}
