Each light source may contribute to a vertex's color, and these contributions are added together. The equation for computing each light source's contribution is as follows:
contribution = attenuation factor * spotlight effect *
(ambient term + diffuse term + specular term)
The attenuation factor was described in "Position and Attenuation" :
attenuation factor =
![[IMAGE]](figures/eq602.gif)
where
d = distance between the light's position and the vertex
kc = GL_CONSTANT_ATTENUATION
kl = GL_LINEAR_ATTENUATION
kq = GL_QUADRATIC_ATTENUATION
If the light is a directional one, the attenuation factor is 1.
The spotlight effect evaluates to one of three possible values, depending on whether the light is actually a spotlight and whether the vertex lies inside or outside the cone of illumination produced by the spotlight:
1 if the light isn't a spotlight (GL_SPOT_CUTOFF is 180.0).
0 if the light is a spotlight but the vertex lies outside the cone of illumination produced by the spotlight.
(max {v x d, 0 } )GL_SPOT_EXPONENT where:
v = (vx, vy, vz) is the unit vector that points from the spotlight (GL_POSITION) to the vertex.
d = (dx, dy, dz) is the spotlight's direction (GL_SPOT_DIRECTION), assuming the light is a spotlight and the vertex lies inside the cone of illumination produced by the spotlight.
The dot product of the two vectors v and d varies as the cosine of the angle between them; hence, objects directly in line get maximum illumination, and objects off the axis have their illumination drop as the cosine of the angle.
To determine whether a particular vertex lies within the cone of illumination, OpenGL evaluates (max { v x d , 0 } ) where v and d are as defined above. If this value is less than the cosine of the spotlight's cutoff angle (GL_SPOT_CUTOFF), then the vertex lies outside the cone; otherwise, it's inside the cone.
The ambient term is simply the ambient color of the light scaled by the ambient material property:
ambientlight *ambientmaterial
The diffuse term needs to take into account whether light falls directly on the vertex, the diffuse color of the light, and the diffuse material property:
(max { l · n , 0 } ) * diffuselight * diffusematerial where:
l = (lx, ly, lz) is the unit vector that points from the vertex to the light position (GL_POSITION).
n = (nx, ny, nz) is the unit normal vector at the vertex.
The specular term also depends on whether light falls directly on the vertex. If l · n is less than or equal to zero, there is no specular component at the vertex. (If it's less than zero, the light is on the wrong side of the surface.) If there's a specular component, it depends on the following:
The unit normal vector at the vertex (nx, ny, nz).
The sum of the two unit vectors that point between (1) the vertex and the light position and (2) the vertex and the viewpoint (assuming that GL_LIGHT_MODEL_LOCAL_VIEWER is true; if it's not true, the vector (0, 0, 1) is used as the second vector in the sum). This vector sum is normalized (by dividing each component by the magnitude of the vector) to yield s = (sx, sy, sz).
The specular exponent (GL_SHININESS).
The specular color of the light (GL_SPECULARlight).
The specular property of the material (GL_SPECULARmaterial).
Using these definitions, here's how OpenGL calculates the specular term:
(max { s x n , 0} )shininess * specularlight * specularmaterial
However, if 1 x n = 0, the specular term is 0.
OpenGL Programming Guide