#version 330 core

uniform sampler2D color_buffer;
/*
uniform sampler2D gb_diffuse;
uniform sampler2D gb_specular;
uniform sampler2D gb_normal;
uniform sampler2D gb_depth;
uniform sampler2D gb_light;
uniform sampler2D debug_buffer;
uniform sampler2D ssao_buffer;
*/
uniform sampler2DArray debug_shadowmap;
uniform sampler2D gb_normal;
uniform sampler2D gb_diffuse;

in vec2 uv;

layout (location = 0) out vec4 frag_color;

#include <post/blit_include.frag>

float linearizeDepth(in float z)
{
	const float n = 1.0; // camera z near
	const float f = 1024.0; // camera z far
	return (2.0 * n) / (f + n - z * (f - n));
}

float linearizeCascadeDepth(in float z, in float n, in float f)
{
	return (2.0 * n) / (f + n - z * (f - n));
}


//const float sensitivity = 0.398; // how sensitive the blurring should be to per pixel variance
vec4 smartBlur(in sampler2D tex)
{
	const int blurSize = 5; // 3
	const int origTexelIndex = (blurSize*blurSize - 1) / 2;
	vec2 TexelSize = vec2(1.0/1280.0, 1.0/720.0);
	vec4 texels[blurSize*blurSize];

	int idx = 0;
	for(int i=-(blurSize/2); i <= (blurSize/2); i++)
	{
		for(int j=-(blurSize/2); j <= (blurSize/2); j++)
		{
			vec2 coord = uv + TexelSize*vec2(float(i), float(j));
			vec2 noiseUV = (gl_FragCoord.xy + vec2(float(i), float(j))) * invViewport;
			float n = (texture(noise_lut, noiseUV + noiseParams.xy).x*2.0 - 1.0)*noiseParams.z;

			texels[idx] = texture(tex, coord) + vec4(n,n,n,1.0);
			idx++;
		}
	}

	// get avg pixel value
	vec4 avg = vec4(0.0);
	for(int i=0; i < blurSize*blurSize; i++)
	{
		avg += texels[i];
	}
	avg /= float(blurSize*blurSize);

	// calculate variance 
	vec4 accum = vec4(0.0);
	for(int i=0; i < blurSize; i++)
	{
		vec4 diff = texels[i] - avg;
		diff *= diff;
		accum += diff;
	}
	float rms = sqrt(max(max(accum.x, accum.y), accum.z) / float(blurSize*blurSize));

	float sensitivity = distortParams.x;
	if ( rms > sensitivity )
	{
		// variance to large, keep the original texel
		return texels[origTexelIndex];
	}
	else
	{
		return mix(avg, texels[origTexelIndex], rms/sensitivity);
	}
}


void main()
{
#if 0
	vec2 uv2 = distort_uv(uv);
	//vec4 color = texture(color_buffer, uv2);
	vec4 color = smartBlur(color_buffer);
	frag_color = color_lookup(color, uv);
#else
#if 0
	vec4 cascadeColor = vec4(0.5, 0.5, 0.5, 1.0);
	vec3 uvw;
	vec2 zPlane = vec2(0.5, 1024.0);
	if ( uv.x < 0.5 )
	{
		uvw.x = uv.x*2.0;
		if ( uv.y < 0.5 )
		{
			// lower left corner (blue) 3rd cascade
			uvw.y = uv.y*2.0;
			uvw.z = 2.0;
			cascadeColor.b = 1.0;
			zPlane = vec2(145.0, 307.0);
		}
		else
		{
			// upper left corner (red) 1st cascade
			uvw.y = (uv.y - 0.5)*2.0;
			uvw.z = 0.0;
			cascadeColor.r = 1.0;
			zPlane = vec2(0.5, 66.0);
		}
	}
	else
	{
		uvw.x = (uv.x - 0.5)*2.0;
		if ( uv.y < 0.5 )
		{
			// lower right corner (gray) 4th cascade
			uvw.y = uv.y*2.0;
			uvw.z = 3.0;
			cascadeColor.rgb = vec3(0.5);
			zPlane = vec2(307.0, 1024.0);
		}
		else
		{
			// upper right corner (green) 2nd cascade 
			uvw.y = (uv.y - 0.5)*2.0;
			uvw.z = 1.0;
			cascadeColor.g = 1.0;
			zPlane = vec2(66.0, 145.0);
		}
	}
	frag_color = cascadeColor * linearizeCascadeDepth(texture(debug_shadowmap, uvw).x, zPlane.x, zPlane.y);
	frag_color.a = 1.0;
#else
	//frag_color.rgb = texture(gb_normal, uv).xyz*0.5 + vec3(0.5);
	frag_color.rgb = texture(gb_diffuse, uv).rgb;
	//frag_color.rgb = texture(gb_specular, uv).rgb;
	//frag_color.rgb = texture(gb_specular, uv).aaa;
	//frag_color.rgb = texture(gb_light, uv).rgb;
	//frag_color.rgb = texture(debug_buffer, uv).rgb;
	frag_color.a = 1.0;
	//frag_color = smartBlur(color_buffer);
	//frag_color.a = 1.0;
#endif
#endif
}
