// -*- c++ -*-
/**
  @file SS_Light.pix
  @author Morgan McGuire morgan@cs.williams.edu

  For use with G3D::SuperShader.
  This file is included into NonShadowedPass.pix and 
  ShadowMappedLightPass.pix.

  @edited  2009-03-24
  @created 2007-12-18
 */

// 1.0 / 8.0; used for normalizing the specular lobe
#define inv8 (0.125)
 
/**
 @param lightAttenuation OpenGL distance attenuation polynomial coefficients
 @param lightDirection   OpenGL spotlight direction
 */
void addLightContribution(in vec3 wsN, in vec3 wsE, in vec3 wsPosition, in float specularExponent, 
                          in vec4 lightPosition, in vec4 lightAttenuation, in vec3 lightDirection,
                          in vec3 lightColor, inout vec3 I_lambertian, inout vec3 I_specular, out vec3 wsL) {
    
    // Light vector
    wsL = lightPosition.xyz - wsPosition.xyz * lightPosition.w;
    float lightDistance = length(wsL);
    wsL = wsL / lightDistance;

    float attenuation =
        // Spotlight cone (lightAttenuation.w = -1 for other lights)
        (-dot(lightDirection, wsL) >= lightAttenuation.w) ? 

          // Within spotlight cone
          (1.0 / dot( vec3(1.0, lightDistance, lightDistance * lightDistance), lightAttenuation.xyz)) : 

          // Outside spotlight cone
          0.0;

#   ifdef NORMALBUMPMAP
        // For a bump mapped surface, do not allow illumination on the back side even if the
        // displacement creates a light-facing surface, since it should be self-shadowed for any 
        // large polygon.
        attenuation *= float(dot(tan_Z.xyz, wsL) * backside > 0.0);
#   endif

    // Attenuation is modulated by the cosine of the angle of incidence
    attenuation *= max(dot(wsL, wsN), 0.0);

    vec3 attLightColor = attenuation * lightColor;

#   if defined(LAMBERTIANCONSTANT) || defined(LAMBERTIANMAP)
        I_lambertian += attLightColor;
#   endif

#   if defined(SPECULARCONSTANT) || defined(SPECULARMAP)
        if (specularExponent > 0.0) {
            // cosine of the angle between the normal and the half-vector
            vec3 wsH = normalize(wsL + wsE);
            float cos_h = max(dot(wsH, wsN), 0.0);
            I_specular += attLightColor * (pow(cos_h, specularExponent) * (specularExponent + 8.0) * inv8);
        }
#   endif
}
