#version 400

// Information from the vertex shader about the eye-space location
//    of this fragment we're working on
in vec4 esFragPos;
in vec4 esFragNormal;
in float fragMatlID;

// Where to store the color we compute
out vec4 result;

uniform float useLambertian;  // Asked to use a Lambertian shading scheme?
uniform vec4 esLightPos;      // Location of the light, relative to the eye

uniform mat4 shadMapMatrix;   // A matrix: eye-space position -> shadow map texture coordinate

// Our shadow map texture.  
uniform sampler2DShadow shadowTex;  

// The buffer containing our material information
uniform samplerBuffer  matlInfoTex;


// This is the actual code that is executed.
void main( void )
{	
	// Look up data about this particular fragment's material
	int matlIdx     = 4 * int(fragMatlID+0.5);
	vec4 matlInfo   = texelFetch( matlInfoTex, matlIdx+1 );  // Get diffuse color

	// Transform from eye-space to shadow map texture coordinates
	vec4 smTexCoord = shadMapMatrix * esFragPos;
	smTexCoord /= smTexCoord.w;
	
	// Query depth from texture.  The x/y coordinates are used to select the pixel, the
	//    z-coordinate is used as the comparison reference to decide if the pixel is in
	//    shadow.  Basically, shadowTex(x,y) is queried, which returns a float 'val'.  'val'
	//    is compared to smTexCoord.z, and isLit is 1 or 0 depending on the result.
	// Basically: isLit = texture(shadowTex, smTexCoord.xy) < smTexCoord.z ? 1 : 0;
	//    if we were using normal textures, rather than a shadow sampler
	
	float isLit     = texture(shadowTex, smTexCoord.xyz);
	if ( clamp(smTexCoord.z,0,1) != smTexCoord.z ) isLit=0; 
	
	// Find simple vectors for basic shading
	vec3 toLight = normalize( esLightPos.xyz - esFragPos.xyz);
	vec3 toEye   = normalize( -esFragPos.xyz );
	
	// Figure out the Lambertian color (if shadowed, set to 0)
	vec3 lambert = isLit * useLambertian * max( 0.0f, dot( normalize(esFragNormal.xyz), toLight ) ) * matlInfo.xyz;
	
	// Figure out the ambient color (if shadowed, set to 0)
	vec3 ambient = isLit * (1.0-useLambertian) * matlInfo.xyz;
	
	// The ambient & lambertian terms we computed above are mutually
	//    independent, so we simply add them together, giving us a correct
	//    answer, no matter which display approach the user has chosen.
	result = vec4( lambert + ambient, 1.0f );
}