// thanks to "http://www.clockworkcoders.com/oglsl/tutorial5.htm"
// also "http://pages.cpsc.ucalgary.ca/~brosz/wiki/pmwiki.php/CSharp/08022008"
// also "http://www.ozone3d.net/tutorials/glsl_lighting_phong_p2.php"

uniform sampler2D tex;

varying vec3 v_normal;
varying vec3 v_pos;
varying vec4 v_color;
varying vec2 v_uv;

vec4 finalColor = vec4(0,0,0,0);

vec3 lightToVert;
float lightDistance;
float spotCosCutoff = -1.0;

void directionalLight( in float intensity )
{
	// get component strengths
	vec4 texColor = texture2D(tex,v_uv) * intensity;
	float gloss = gl_FrontMaterial.shininess*0.3;
	
	// ambient component
	finalColor += gl_LightSource[0].ambient * gl_FrontMaterial.ambient * texColor;
	
	// if we have any reflectance
	float NdotL, NdotHV;
	NdotL = max( dot(v_normal, lightToVert), 0.0 );
	if( NdotL > 0.0 )
	{
		// diffuse component
		finalColor += (gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * texColor) * NdotL;
	
		// specular component
		vec3 reflection = normalize(reflect(lightToVert, v_normal));
		NdotHV = max(dot(normalize(v_pos), reflection),0.0);
		if( NdotHV > 0.0 )
		{
			finalColor += (gl_LightSource[0].specular * gl_FrontMaterial.specular * texColor) * pow(NdotHV,gloss);
		}
	}
}

float get_light_intensity( in float spotlightDotProduct )
{
	float result = 1.0;
	float percent = 1.0;
	if( spotCosCutoff != -1.0 )
		percent = (spotlightDotProduct - spotCosCutoff) / (1.0 - spotCosCutoff);
	
	// this somewhat more closely emulates regular openGL - still not quite
	float innerPercent = gl_LightSource[0].spotExponent * gl_LightSource[0].spotExponent;
	if( innerPercent > 0.0 && percent < innerPercent ) result = percent / innerPercent;
	
	// adjust intensity by attenuation
	if( lightDistance > 0.0 && result > 0.0 )
	{
		float attenuationDenominator = (gl_LightSource[0].constantAttenuation +
										gl_LightSource[0].linearAttenuation * lightDistance +
										gl_LightSource[0].quadraticAttenuation * lightDistance * lightDistance);
	
		if( attenuationDenominator != 0.0 ) 
			result /= attenuationDenominator;
	}
	return result;
}

void main() 
{
	// get light properties
	if( gl_LightSource[0].position.w == 0.0 ) lightToVert = gl_LightSource[0].position.xyz;
	else lightToVert = normalize(gl_LightSource[0].position.xyz - v_pos);
	
	lightDistance = length(lightToVert);
	
	// calc the spotlight properties
	if( gl_LightSource[0].spotCutoff != 0.0 && gl_LightSource[0].spotCutoff != 180.0 )
		spotCosCutoff = cos(gl_LightSource[0].spotCutoff * 0.0174532925); // from deg to rad

	float spotDotProd = dot(-lightToVert, gl_LightSource[0].spotDirection);
	if ( spotCosCutoff == -1.0 || spotDotProd > spotCosCutoff )
	{
		float intensity = get_light_intensity(spotDotProd);
		
		if( intensity > 0.0 ) 
			directionalLight( intensity );
	}
	
	// ambient & emission
	vec4 emission = gl_FrontMaterial.emission;
	vec4 ambient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
	finalColor += v_color * (ambient * texture2D(tex,v_uv) + emission);
	
	// get fog and color fragment
	float fog = clamp((gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0);
	gl_FragColor = mix(gl_Fog.color, v_color * finalColor, fog);
}


