#include "uniforms.glsl"
#include "utils.glsl"
#line 3

uniform mat4 shadowTransform;

#ifdef VERT_SHADER
#line 9
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
// normal
layout(location=3) in vec2 in_UV;
out vec4 ex_Color;
out vec2 ex_UV;

void main()
{
	ex_Color = in_Color;
	ex_UV = in_UV;
	gl_Position = in_Position;
}

#endif

#ifdef FRAG_SHADER

in vec4 ex_Color;
in vec2 ex_UV;

layout(location=0) out vec4 out_Color;

#include "buffers.glsl"
#line 34

//uniform sampler2DShadow shadowbuffer;
uniform sampler2D shadowbuffer;
uniform sampler2D logo;

uniform float p_fullbright;


// currently not used, we just sample the position buffer
vec4 getViewPos(float depth, vec2 uv) {
	float z = depth;
	float x = uv.x * 2.0 - 1.0;
	float y = (1.0 - uv.y) * 2 - 1;
	vec4 projPos = vec4(x, y, z, 1.0);
	vec4 viewPos = inverseProjectionMatrix*projPos;
	return vec4(viewPos.xyz / viewPos.w, 1.0);
}

vec3 getViewpos() {
	return texture(positionbuffer, ex_UV).xyz;
}



float inShadow(vec3 lightclip, float bias)
{	

	vec2 add = vec2(
	noise(vec3(lightclip.x, lightclip.y, p_beat)), 
	noise(vec3(p_beat, lightclip.x, p_beat))
	);
	
	lightclip.xy += add * 0.001;

	
	float val = 0.0f;
	val += (textureOffset(shadowbuffer, lightclip.xy, ivec2(-1, 0)).x - lightclip.z - bias) > 0.0 ? 1.0 : 0.0;
	val += (textureOffset(shadowbuffer, lightclip.xy, ivec2( 1, 0)).x - lightclip.z - bias) > 0.0 ? 1.0 : 0.0;
	val += (textureOffset(shadowbuffer, lightclip.xy, ivec2( 0, 1)).x - lightclip.z - bias) > 0.0 ? 1.0 : 0.0;
	val += (textureOffset(shadowbuffer, lightclip.xy, ivec2( 0,-1)).x - lightclip.z - bias) > 0.0 ? 1.0 : 0.0;
	
	return val / 4.0;
}


vec3 accumulate_light(vec4 worldpos, vec3 lightclip, vec3 normal)
{
	vec3 accum = vec3(0.0);

	for (int i=0;i<MAX_LIGHTS;i++) {
		if (!lights.spot[i].enabled)
			continue;
		//if (lights.spot[i].intensity == vec3(0.0, 0.0, 0.0))
		//	continue; 
		
		//accum += hsv2rgb(vec3(i/8.0, 1.0, 1.0));
		//accum += lights.spot[i].intensity;
		
		vec3 point_to_lamp = worldpos.xyz - lights.spot[i].pos;
		vec3 light_dir = normalize(point_to_lamp);
		float diffuse = max(0.0, dot(normal, -light_dir));
		
		float cone = max(0.0, pow((dot(light_dir, -normalize(lights.spot[i].pos)) - 0.85)*10.0, 1.0));
		vec3 raito = lights.spot[i].intensity * diffuse * cone; 
		raito *= (1.0/pow(length(point_to_lamp), 2.0)) * 75.0;
		
		if (i == SHADOW_SPOT_INDEX && !(lightclip.x > 1 || lightclip.x < 0 || lightclip.y < 0 || lightclip.y > 1)) {
				raito *= inShadow(lightclip, -0.0002);
		}
			
		accum += raito;
		
	}


	return accum;
}

void main()
{
	float depth = texture(depthbuffer, ex_UV).x;
	vec3 viewpos = getViewpos();
	
	vec4 albedo = texture(albedobuffer, ex_UV);
	vec4 col = albedo;
	
	vec4 material = texture(materialbuffer, ex_UV);
	
	col.r += lights.spot[0].intensity.r;
	

	// the normal components are stored in range [0, 1]
	vec3 normal = normalize(decompressv3(texture(normalbuffer, ex_UV).rgb));
	vec3 light = normalize(vec3(-0.6, 0.2, 0.0));
	
	col.rgb = albedo.rgb;
	
	vec3 lamppos = (viewMatrix*vec4(lights.spot[0].pos, 1.0)).xyz;
	vec4 worldpos = (inverseViewMatrix*vec4(viewpos, 1.0)).xyzw;
	vec4 lightview = shadowTransform * worldpos; // light position in lamp view space
	vec3 lightclip = (lightview / lightview.w).xyz; // perform w division, now we've got clip space stuff
	
	lightclip.xyz = lightclip.xyz * 0.5 + vec3(0.5); // map from [-1,1] range to [0,1]
	
	vec3 point_to_lamp = normalize(worldpos.xyz - lights.spot[0].pos);

	vec3 lamplight = accumulate_light(worldpos, lightclip, normal);
	
	if (p_fullbright == 0.0) {
		vec3 illum = vec3(0.1) + lamplight;
		col.rgb *= illum;	// show the diffuse color
	}
	
	col.rgb = mix(col.rgb, albedo.rgb, material.r);
	
	col.rgb *= 1.0 + 0.05*noise(vec3(ex_UV.x, ex_UV.y, p_time));

	out_Color = col; 
} 

#endif