#ifdef FLAG_LIGHT
uniform int n_lights;
#endif

#ifdef FLAG_DIFFUSE_MAP
uniform sampler2D sBasemap;
#endif

#ifdef FLAG_GLOW_MAP
uniform sampler2D sGlowmap;
#endif

#ifdef FLAG_SPEC_MAP
uniform sampler2D sSpecmap;
#endif

#ifdef FLAG_ENV_MAP
uniform samplerCube sEnvmap;
uniform bool alpha_spec;
varying vec3 envReflect;
#endif

#ifdef FLAG_NORMAL_MAP
uniform sampler2D sNormalmap;
varying mat3 tbnMatrix;
#endif

#ifdef FLAG_FOG
varying float fogDist;
#endif

varying vec4 position;
varying vec3 lNormal;

#if SHADER_MODEL == 2
  #define MAX_LIGHTS 2
#else
  #define MAX_LIGHTS 8
#endif

#define SPEC_INTENSITY_POINT 		5.3 // Point light
#define SPEC_INTENSITY_DIRECTIONAL 	3.0 // Directional light
#define SPECULAR_FACTOR 			1.75
#define SPECULAR_ALPHA 				0.1
#define SPEC_FACTOR_NO_SPEC_MAP 	0.6
#define ENV_ALPHA_FACTOR			0.3
#define GLOW_MAP_INTENSITY 			1.5
#define AMBIENT_LIGHT_BOOST 		1.0

void main()
{
	vec3 eyeDir = vec3(normalize(-position).xyz); // Camera is at (0,0,0) in ModelView space
	vec4 lightAmbientDiffuse = vec4(0.0, 0.0, 0.0, 1.0);
	vec4 lightDiffuse = vec4(0.0, 0.0, 0.0, 1.0);
	vec4 lightAmbient = vec4(0.0, 0.0, 0.0, 1.0); 
	vec4 lightSpecular = vec4(0.0, 0.0, 0.0, 1.0);
	vec2 texCoord = gl_TexCoord[0].xy;

 #ifdef FLAG_LIGHT
  #ifdef FLAG_NORMAL_MAP
	// Normal map - convert from DXT5nm
	vec3 normal;

	normal.rg = (texture2D(sNormalmap, texCoord).ag * 2.0) - 1.0;
  #ifdef FLAG_ENV_MAP	
	vec3 envOffset = vec3(0.0);
	envOffset.xy = normal.xy;
  #endif
	normal.b = sqrt(1.0 - dot(normal.rg, normal.rg));
	normal = normalize(tbnMatrix * normal);
  #else
	vec3 normal = lNormal;
  #endif
	
	vec3 lightDir;
	lightAmbient = gl_FrontMaterial.emission + (gl_LightModel.ambient * gl_FrontMaterial.ambient);

	#pragma optionNV unroll all
	for (int i = 0; i < MAX_LIGHTS; ++i) {
	  #if SHADER_MODEL > 2
		if (i > n_lights)
			break;
	  #endif
		float specularIntensity = 1.0;
		float attenuation = 1.0;

		// Attenuation and light direction
	  #if SHADER_MODEL > 2
		if (gl_LightSource[i].position.w == 1.0) {
	  #else
		if (gl_LightSource[i].position.w == 1.0 && i != 0) {
	  #endif
			// Positional light source
			float dist = distance(gl_LightSource[i].position.xyz, position.xyz);

			float spotEffect = 1.0;

		  #if SHADER_MODEL > 2
			if (gl_LightSource[i].spotCutoff < 91.0) {
				spotEffect = dot(normalize(gl_LightSource[i].spotDirection), normalize(-position.xyz));

				if (spotEffect < gl_LightSource[i].spotCosCutoff) {
					spotEffect = 0.0;
				}
			}
		  #endif

			attenuation = spotEffect / (gl_LightSource[i].constantAttenuation + (gl_LightSource[i].linearAttenuation * dist) + (gl_LightSource[i].quadraticAttenuation * dist * dist));

			lightDir = normalize(gl_LightSource[i].position.xyz - position.xyz);

			specularIntensity = SPEC_INTENSITY_POINT; // Point light
		} else {
			// Directional light source
			lightDir = normalize(gl_LightSource[i].position.xyz);

			specularIntensity = SPEC_INTENSITY_DIRECTIONAL; // Directional light
		}

		// Ambient and Diffuse
		lightAmbient += (gl_FrontLightProduct[i].ambient * attenuation);
		lightDiffuse += ((gl_FrontLightProduct[i].diffuse * max(dot(normal, lightDir), 0.0)) * attenuation);

		// Specular
		float NdotHV = clamp(dot(normal, normalize(eyeDir + lightDir)), 0.0, 1.0);
		lightSpecular += ((gl_FrontLightProduct[i].specular * pow(max(0.0, NdotHV), gl_FrontMaterial.shininess)) * attenuation) * specularIntensity;
	}

	lightAmbientDiffuse = lightAmbient + lightDiffuse;
 #else
	lightAmbientDiffuse = gl_Color;
	lightSpecular = gl_SecondaryColor;
 #endif

 #ifdef FLAG_DIFFUSE_MAP
 // Base color
	vec4 baseColor = texture2D(sBasemap, texCoord);
 #else
	vec4 baseColor = gl_Color;
 #endif
 
	vec4 fragmentColor;
	fragmentColor.rgb = baseColor.rgb * max(lightAmbientDiffuse.rgb * AMBIENT_LIGHT_BOOST, gl_LightModel.ambient.rgb - 0.425);
	fragmentColor.a = baseColor.a;

 #ifdef FLAG_SPEC_MAP
 // Spec color
	fragmentColor.rgb += lightSpecular.rgb * (texture2D(sSpecmap, texCoord).rgb * SPECULAR_FACTOR);
	fragmentColor.a += (dot(lightSpecular.a, lightSpecular.a) * SPECULAR_ALPHA);
 #else
	fragmentColor.rgb += lightSpecular.rgb * (baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP);
 #endif

 #ifdef FLAG_ENV_MAP
 // Env color
  #ifdef FLAG_NORMAL_MAP
	vec3 envReflectNM = envReflect + envOffset;
	vec3 envIntensity = (alpha_spec) ? vec3(texture2D(sSpecmap, texCoord).a) : texture2D(sSpecmap, texCoord).rgb;
	fragmentColor.a += (dot(textureCube(sEnvmap, envReflectNM).rgb, textureCube(sEnvmap, envReflectNM).rgb) * ENV_ALPHA_FACTOR);
	fragmentColor.rgb += textureCube(sEnvmap, envReflectNM).rgb * envIntensity;
  #else
	vec3 envIntensity = (alpha_spec) ? vec3(texture2D(sSpecmap, texCoord).a) : texture2D(sSpecmap, texCoord).rgb;
	fragmentColor.a += (dot(textureCube(sEnvmap, envReflect).rgb, textureCube(sEnvmap, envReflect).rgb) * ENV_ALPHA_FACTOR);
	fragmentColor.rgb += textureCube(sEnvmap, envReflect).rgb * envIntensity;
  #endif
 #endif

 #ifdef FLAG_GLOW_MAP
 // Glow color
	fragmentColor.rgb += texture2D(sGlowmap, texCoord).rgb * GLOW_MAP_INTENSITY;
 #endif

 #ifdef FLAG_FOG
	fragmentColor.rgb = mix(fragmentColor.rgb, gl_Fog.color.rgb, fogDist);
 #endif

	gl_FragColor = fragmentColor;
}