#version 330 core

uniform mat4 PreviousMatrix;
uniform mat4 ProjectionMatrix;

uniform sampler2D color_buffer;
uniform sampler2D normal_depth;
uniform sampler2D lowres_normal_depth;
uniform sampler2D lowres_mssao;

uniform sampler2D last_normal_depth;
uniform sampler2D last_ssao;

uniform vec2 poissonDisk[16];
uniform float aoPower;

in vec2 uv;

layout (location = 0) out vec4 frag_color;

#include <deferred/gbuffer_include.frag>

#include <post/mssao_include.frag>


void main()
{
	vec4 nd = texture(normal_depth, uv);
	vec3 currPos = calc_position(uv, nd.w);
	float occlusion = 0.0;
	float sampleCount = 0.0001;
	float rangeMax = min(r / abs(currPos.z), rMax);
	for (int i=0; i < 16; ++i)
	{
		vec2 offs = uv + poissonDisk[i]*TexelSize*rangeMax;
		computeOcclusion(normal_depth, offs, currPos, nd.xyz, occlusion, sampleCount);
	}

	vec3 smp = upsampleAO(lowres_normal_depth, lowres_mssao, uv, currPos, nd.xyz);
	float aoMax = max(smp.x, occlusion / sampleCount);  
	float aoAverage = (smp.y + occlusion) / (smp.z + sampleCount);
	float currentFrameAO = (1.0 - aoMax) * (1.0 - aoAverage);

	vec4 eyePos = PreviousMatrix * vec4(currPos, 1.0);
	vec4 screenPos = ProjectionMatrix * eyePos;
	vec2 lastUV = screenPos.xy / screenPos.w;
	float lastZ = calc_position(lastUV, texture(last_normal_depth, lastUV).w).z;
	float lastWeight = 0.0;
	if ( abs(1.0 - (lastZ/eyePos.z)) < 0.01)
	{
		lastWeight = 0.6;
	}
	if ( lastUV.x < 0.0 || lastUV.x > 1.0 ||
	     lastUV.y < 0.0 || lastUV.y > 1.0 )
	{
		lastWeight = 0.0;
	}

	float lastAO = texture(last_ssao, lastUV).x;
	//float ao = pow(lastAO*lastWeight + currentFrameAO*(1.0 - lastWeight), aoPower);
	float ao = pow(currentFrameAO, aoPower);
	frag_color.rgb = texture(color_buffer, uv).rgb * ao;
	frag_color.a = ao;
}
