#version 110

uniform bool lights_active[MAX_LIGHTS];
uniform vec3 lights_ambient[MAX_LIGHTS];
uniform vec3 lights_diffuse[MAX_LIGHTS];
uniform vec3 lights_specular[MAX_LIGHTS];
uniform vec3 lights_spotdir[MAX_LIGHTS];
uniform float lights_spotexp[MAX_LIGHTS];
uniform float lights_spotcutoff[MAX_LIGHTS];
uniform vec3 lights_att[MAX_LIGHTS];

struct material
{
	bool active;
	vec3 emission;
	vec3 diffuse;
	vec3 specular;
	float shininess;
};

uniform material current_material;

uniform int vertextype;

uniform sampler2D tex;
uniform sampler2D nmap;
uniform sampler2D smap;
uniform bool normal_map;
uniform bool specular_map;
uniform bool texture;
uniform bool fb_texture;

varying vec3 eye_vector;

varying vec4 normal_light_vector[MAX_LIGHTS];
varying vec3 light_reflection[MAX_LIGHTS];

varying mat3 tbn_matrix;

void main()
{
	vec4 color = gl_Color;
	vec4 texture_color;
	vec3 normal;
	
	if(normal_map)
	{
		vec3 tex_normal = vec3(texture2D(nmap, gl_TexCoord[0].st)) * 2.0 - 1.0;
		normal = normalize(tbn_matrix * tex_normal);
	}
	else normal = normalize(tbn_matrix[2]);
	
	if(texture)
	{
		texture_color = texture2D(tex, gl_TexCoord[0].st);
	
		if(fb_texture && texture_color.rgb == vec3(0.0, 0.0, 0.0)) discard;
		
		if(texture_color.a == 0.0) discard;
		
		color *= texture_color;
	}
	
	if(vertextype == 1)
	{
		int i;
		vec3 mat_emission;
		vec3 mat_diffuse;
		vec3 mat_specular;
		float mat_shininess;
		
		if(current_material.active)
		{
			mat_emission = current_material.emission;
			mat_diffuse = current_material.diffuse;
			mat_specular = current_material.specular;
			mat_shininess = current_material.shininess;
		}
		else
		{
			mat_emission = vec3(0.0, 0.0, 0.0);
			mat_diffuse = gl_Color.rgb;
			mat_specular = vec3(0.4, 0.4, 0.4);
			mat_shininess = 8.0;
		}
		
		if(texture) mat_diffuse *= texture_color.rgb;
		
		if(specular_map) mat_specular = vec3(texture2D(smap, gl_TexCoord[0].st));
		
		color.rgb = mat_emission;
		
		for(i = 0; i < MAX_LIGHTS; i++)
		{
			if(lights_active[i])
			{
				vec3 light_vector = normalize(normal_light_vector[i].xyz);
				
				float dist = normal_light_vector[i].w;
				float att = 1.0 / (lights_att[i].x + lights_att[i].y * dist + lights_att[i].z * dist * dist);;
				vec3 ambient = lights_ambient[i] * mat_diffuse;
				
				float lambert_term = clamp(dot(normal, light_vector), 0.0, 1.0);
				vec3 diffuse = lambert_term * lights_diffuse[i] * mat_diffuse;
				
				vec3 reflection = normal_map ? reflect(light_vector, normal) : normalize(light_reflection[i]);
				
				float rdoteye = clamp(dot(reflection, normalize(eye_vector)), 0.0, 1.0);
				vec3 specular = lights_specular[i] * mat_specular * pow(rdoteye, mat_shininess);
				
				color.rgb += att * (ambient + diffuse + specular);
			}
		}
	}
	
	gl_FragColor = color;
}
