/* Universidade Federal Fluminense
 * Programa de Pós-Graduação em Computação
 *
 * Tópicos Avançados em Computação Visual e Interfaces II (Técnicas Avançadas de Rendering)
 * Professor: Leandro Augusto Frata Fernandes
 *
 * Version: 2012.05.05-001
 */

// User-defined material (from application).
uniform vec4 MaterialAmbient;
uniform vec4 MaterialDiffuse;
uniform vec4 MaterialSpecular;
uniform float MaterialShininess;

// User-defined light (from application)
uniform vec4 LightDiffuseColor;
uniform vec4 LightSpecularColor;
uniform vec4 AmbientColor;

// User-defined input variables from vertex shader.
varying vec3 Normal;         // CCS
varying vec3 ViewDirection;  // CCS
varying vec3 LightDirection; // CCS

// The main method.
void main(void)
{
   // Normalize interpolated directions.
   vec3 fvNormal = normalize(Normal);
   vec3 fvLightDirection = normalize(LightDirection);
   vec3 fvViewDirection = normalize(ViewDirection);
   
   // Compute reflection direction.
   float fLDotN = dot(fvNormal, fvLightDirection);
   vec3 fvReflection = normalize((2.0 * fLDotN * fvNormal) - fvLightDirection); 
   
   // Compute contributions.
   vec4 fvTotalAmbient = MaterialAmbient * AmbientColor;

   vec4 fvTotalDiffuse, fvTotalSpecular;
   
   if (fLDotN > 0.0)   
   {
      fvTotalDiffuse = MaterialDiffuse * fLDotN * LightDiffuseColor;
      
      float fRDotV = max(0.0, dot(fvReflection, fvViewDirection));
      fvTotalSpecular = MaterialSpecular * pow(fRDotV, MaterialShininess) * LightSpecularColor;
   }
   else
   {
      fvTotalDiffuse = fvTotalSpecular = vec4(0.0, 0.0, 0.0, 1.0);
   }
  
   // Compute final color.
   gl_FragColor = fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular;
}
