#version 330 core

uniform sampler2D normal_depth;
uniform sampler2D light_accumulation;

uniform vec2 gi_radius;
uniform vec2 ao_radius;

in vec2 texCoord;

layout (location = 0) out vec4 frag_color;

#define LOD_LEVEL 0.0
#define MAX_SAMPLES 8
#define USE_SSGI

float rand(in vec2 co)
{
        return 0.5 + (fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453))*0.5;
}

float conv_depth(in float d)
{
	return d*0.5 + 0.5;
}

void main()
{
	// light_accumulation mipmap level to sample from
	const float PI = 3.1415926;
	const float color_threshold = 0.3;
	const float depth_threshold = 0.0;

	vec4 nd = texture2D(normal_depth, texCoord);

	int samples = int( floor( (float(MAX_SAMPLES) / (nd.w*0.5 + 1.0)) + 0.5) );
	if ( samples > MAX_SAMPLES ) samples = MAX_SAMPLES;
	
	int hf = samples/2;
	//float inv_prof = float(samples) / float(MAX_SAMPLES);
	//float inv_prof = float(MAX_SAMPLES) / float(samples);

	float rnd = rand(texCoord);
	float z_div = (1.0 + (nd.w*0.5 + 0.5))*float(hf);
	vec2 gi_mult = clamp(gi_radius/z_div, -gi_radius, gi_radius) * rnd;
	vec2 ao_mult = clamp(ao_radius/z_div, -ao_radius, ao_radius) * rnd;

	float ao_sum = 0.0;
	vec3 gi_color = vec3(0.0);

	for(int i=-hf; i < hf; i++)
	{
		for(int j=-hf; j < hf; j++)
		{
			if ( i != 0 || j != 0 )
			{
				vec2 coords = vec2(float(i), float(j)) * gi_mult; // * inv_prof;
				vec2 coords2 = vec2(float(i), float(j)) * ao_mult; // * inv_prof;
				vec2 uv = texCoord + coords;
				vec2 uv2 = texCoord + coords2;

				vec4 nd2 = texture(normal_depth, uv);
				vec4 nd2g = texture(normal_depth, uv2);
				vec3 dc = textureLod(light_accumulation, uv, LOD_LEVEL).xyz;

				float depth_coherence = dot(-coords2, nd2g.xy);
				if ( depth_coherence > depth_threshold )
				{
					//vec3 dist2 = vec3(coords2, (conv_depth(nd.w) - conv_depth(nd2g.w)));
					vec3 dist2 = vec3(coords2, nd.w - nd2g.w);
					float pformfactor = 0.5*((1.0 - dot(nd.xyz, nd2g.xyz))) / (PI*pow(length(dist2*2.0), 2.0) + 0.5);
					ao_sum += clamp(pformfactor*0.2, 0.0, 1.0);
				}
#ifdef USE_SSGI
				if ( length(dc) > color_threshold )
				{
					//depth_coherence = dot(-coords, normalize(nd2.xy));
					depth_coherence = dot(-coords, nd2.xy);
					if ( depth_coherence > depth_threshold )
					{
						//vec3 dist = vec3(coords, (conv_depth(nd.w) - conv_depth(nd2.w)));
						vec3 dist = vec3(coords, nd.w - nd2.w);
						float pformfactor = ((1.0 - dot(nd.xyz,nd2.xyz))) / (PI*pow(length(dist*2.0), 2.0) + 0.5);
						gi_color += dc*clamp(pformfactor, 0.0, 1.0);
					}
				}
#endif // USE_SSGI
			}
		}
	}

	vec3 bleeding = (gi_color / float(samples))*(1.0/4.0);
	float occlusion = 1.0 - (ao_sum / float(samples));
	//bleeding.b = float(samples) / float(NUM_SAMPLES);
	frag_color = vec4(bleeding, occlusion);
}
