#version 330 core

uniform sampler2D diffuse_specular;
uniform sampler2D normal_depth;
uniform sampler2D shadowmap;
uniform vec2 viewport;
uniform mat4 ShadowMatrix;

in vec3 spot_pos;
in vec3 spot_dir;
in vec3 spot_params; // cone_angle, cone_cutoff_angle, radius
in vec3 color;       // rgb*intensity

layout (location = 0) out vec4 frag_color;

#include <deferred/gbuffer_read_include.frag>

#if 0
#include <shading_model/blinn_phong_model_include.frag>
#endif

#include <shading_model/strauss_model_include.frag>

float calculate_shadow(in vec4 pos)
{
	const float samples = 3.0;
	const float filterWidth = samples / 1024.0;
	const float stepSize = 2.0*filterWidth / samples;
	float count = 0.0;

	for (float i=-filterWidth; i < filterWidth; i+=stepSize)
	{
		for (float j=-filterWidth; j < filterWidth; j+=stepSize)
		{
			count += float(pos.z < texture(shadowmap, pos.xy + vec2(i,j)).x);
		}
	}
	//return (count / (samples*samples))*0.5 + 0.5;
	return count / (samples*samples);
}


void main()
{
	vec2 uv = gl_FragCoord.xy * viewport;
	vec4 ds = texture(diffuse_specular, uv);
	vec4 nd = texture(normal_depth, uv);

	vec3 pos = calc_position(uv, nd.w);

	vec3 ld = spot_pos - pos;
	float len = length(ld);
	if ( len > spot_params.z ) discard;

	vec4 lpos = ShadowMatrix * vec4(pos, 1.0);
	lpos /= lpos.w;
	float shadow_term = calculate_shadow(lpos);

	ld = normalize(ld);
	vec3 n = normalize(nd.xyz);
	vec3 ed = normalize(-pos);
	vec3 hv = normalize(ld + ed);

	float atten = 1.0 - pow(len / spot_params.z, 2.0);
	atten *= clamp( (dot(-ld, spot_dir) - spot_params.x) / (spot_params.y - spot_params.x), 0.0, 1.0 );
	shadow_term = mix(shadow_term, 1.0, smoothstep(0.0, 1.0, 1.0 - atten));

	//vec3 terms = calculate_blinn_phong_model(n, ld, ed, 8.0) * atten * shadow_term;
	vec3 terms = calculate_strauss_model(n, ld, ed, 0.1, 0.9, 0.0) * atten * shadow_term;

	frag_color.rgb = color*ds.rgb*terms.x + color*ds.a*(terms.y + terms.z);
	frag_color.a = terms.x;
}
