#version 330 core

uniform sampler2D diffuse_specular;
uniform sampler2D normal_depth;
uniform vec2 viewport;

in vec4 light_pos;
in vec3 color;

layout (location = 0) out vec4 frag_color;

#include <gbuffer_include.frag>

#if 0

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

float point_light_vol(in vec3 camera_dir, in vec3 epos, in vec3 light_pos, in float light_radius)
{
	vec3 dir = vec3(0.0) - light_pos;
	float light_rad_sqr = light_radius*light_radius;
	float b = dot(dir, camera_dir);
	float c = dot(dir, dir) - light_rad_sqr;
	float d = b*b - c;
	if ( d > 0.0 )
	{
		vec3 pt0 = dir*(-b - sqrt(d));
		vec3 pt1 = dir*(-b + sqrt(d));
		float d = distance(epos, light_pos);
#if 1
		float noise = abs(rand(pt0.xy)*rand(pt0.yz));
		// check if epos is inside the sphere
		if ( d < light_radius )
		{
			return noise*(distance(pt0, epos) / light_rad_sqr);
			//return d / light_rad_sqr;
		}
		else
		{
			return noise*(distance(pt0, pt1) / light_rad_sqr);
		}
#else
		float noise = abs(rand(pt0.xy)*rand(pt0.yz));
		d = (d < light_radius ? d : 0.0);
		return noise*max(distance(pt0, pt1) - d, 0.0) / light_rad_sqr;
#endif
	}
	else
	{
		// no light "volume" if there was no intersection
		return 0.0;
	}
}

void main()
{
	const float SPECULAR_POWER = 8.0;

	vec2 uv_pos = gl_FragCoord.xy * viewport;
	vec4 ds = texture(diffuse_specular, uv_pos);
	vec4 nd = texture(normal_depth, uv_pos);

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

	vec3 camera_dir = normalize(pos);
	//vec3 camera_dir = normalize(cam_dir);
	float vol = pow( point_light_vol(camera_dir, pos, light_pos.xyz, light_pos.w*0.5), 0.125) * (1.0/2.0);

	vec3 light_dir = light_pos.xyz - pos;
	float len = length(light_dir);
	float light_mul = (len > light_pos.w ? 0.0 : 1.0);

	light_dir = normalize( light_dir );

	vec3 normal = normalize(nd.xyz);
	float NdotL = dot(normal, light_dir);
	light_mul *= (NdotL <= 0.0 ? 0.0 : 1.0);
	//vol *= max(NdotL, 0.0);

	float atten = 1.0 - (len / light_pos.w);
	vec3 half_vector = normalize(reflect(normalize(pos), light_dir));
	float NdotHV = max(dot(normal, half_vector), 0.0)*NdotL;

	vec3 lit = color*ds.rgb*NdotL + color*ds.a*pow(NdotHV, SPECULAR_POWER);
	//frag_color = vec4(lit*atten, NdotL*atten);

	// should we add some noise to the "volume"
	//frag_color = vec4(mix(lit, color, vol)*atten, NdotL*atten);
	//frag_color = vec4(color*vol, NdotL*atten);
	//frag_color = vec4(lit*atten*light_mul + color*vol, NdotL*atten);
	frag_color = vec4(mix(lit*light_mul, color, vol)*atten, NdotL*atten);
}

#else

void main()
{
	const float SPECULAR_POWER = 8.0;

	vec2 uv_pos = gl_FragCoord.xy * viewport;
	vec4 ds = texture(diffuse_specular, uv_pos);
	vec4 nd = texture(normal_depth, uv_pos);

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

	vec3 light_dir = light_pos.xyz - pos;
	float len = length(light_dir);
	if ( len > light_pos.w ) discard;

	light_dir = normalize( light_dir );

	vec3 normal = normalize(nd.xyz);
	float NdotL = dot(normal, light_dir);
	if ( NdotL <= 0.0 ) discard;

	float atten = 1.0 - (len / light_pos.w);
	vec3 half_vector = normalize(reflect(normalize(pos), light_dir));
	float NdotHV = max(dot(normal, half_vector), 0.0)*NdotL;

	vec3 lit = color*ds.rgb*NdotL + color*ds.a*pow(NdotHV, SPECULAR_POWER);
	frag_color = vec4(lit*atten, NdotL*atten);
}

#endif
