uniform float dMaxSqr;
uniform float rMax;
uniform float r;
uniform vec2  offsets[4];
uniform vec2 TexelSize;

void computeOcclusion(in sampler2D normal_depth, in vec2 uv, in vec3 currPos, in vec3 currNorm, inout float occlusion, inout float sampleCount)
{
	vec4 nd = texture(normal_depth, uv);
	vec3 pos = calc_position(uv, nd.w);
	float d = distance(pos.xyz, currPos.xyz);
	float t = 1.0 - min(1.0, d*d / dMaxSqr);
	vec3 diff = normalize(pos.xyz - currPos.xyz);
	float cosTheta = max( dot(currNorm, diff), 0.0);
	occlusion += t * cosTheta * sign(-pos.z);
	sampleCount += 1.0;
}

vec3 upsampleAO(in sampler2D lowres_normal_depth, in sampler2D lowres_mssao, in vec2 uv, in vec3 currPos, in vec3 currNorm)
{
	float totalWeight = 0.0;
	vec3 combinedAO = vec3(0.0);
	for (int i=0; i < 4; ++i)
	{
		vec2 loResCoord = uv + offsets[i]*TexelSize*2.0 + TexelSize;
		vec4 nd = texture(lowres_normal_depth, loResCoord);
		vec3 norm = nd.xyz;
		float depth = calc_position(loResCoord, nd.w).z;
		vec3 ao = texture(lowres_mssao, loResCoord).xyz;

		float normWeight = (dot(norm, currNorm) + 1.1) / 2.1;
		normWeight = pow(normWeight, 8.0);

		float depthWeight = 1.0 / (1.0 + abs(currPos.z - depth) * 0.2);
		depthWeight = pow(depthWeight, 16.0);

		float weight = normWeight * depthWeight * (9.0 / 16.0) /
			(abs((uv.x - loResCoord.x*2.0) * (uv.y - loResCoord.y*2.0)) * 4.0);
		totalWeight += weight;
		combinedAO += ao * weight;
	}

	combinedAO /= totalWeight > 0.0 ? totalWeight : 1.0;
	return combinedAO;
}
