Http://www.cnblogs.com/mikewolf2002/archive/2013/01/26/2877509.html
Original address: http://ogldev.atspace.co.uk/www/tutorial21/tutorial21.html
In this tutorial, we learn the lighting effects of spotlights, where the spotlight has a light source, and it decays as the propagation distance increases, as well as the direction of illumination, and the additional spotlight is that its exposure is within a cone, similar to the effect of a searchlight.
The following illustration shows the effect of a spotlight:
The direction of the spotlight is indicated by the Black Arrow L, and our lighting effect is limited to two red lines. We can define the illumination range by the direction of the light and the angle of the red line, for the point of view Vector V, we can use L and V to dot product, if the result is less than cone angle, there will be no spotlight effect.
Main code:
Lighting_technique.h
struct Spotlight:public pointlight
{
vector3f Direction;
float Cutoff;
SpotLight ()
{
Direction = vector3f (0.0f, 0.0f, 0.0f);
Cutoff = 0.0f;
}
};
In the spotlight class, we define 2 new properties, illumination direction, and light cone angle.
Lighting_technique.cpp
struct SpotLight
{
struct Pointlight Base;
VEC3 Direction;
float Cutoff;
};
...
uniform int gnumspotlights;
...
Uniform SpotLight gspotlights[max_spot_lights];
Define multiple Spotlight lights.
Vec4 calcpointlight (struct pointlight l, vec3 Normal)
{
VEC3 lightdirection = worldpos0-l.position;
float Distance = Length (lightdirection);
Lightdirection = normalize (lightdirection);
VEC4 Color = calclightinternal (L.base, lightdirection, Normal);
float attenuation = l.atten.constant +
L.atten.linear * Distance +
L.ATTEN.EXP * Distance * Distance;
return color/attenuation;
}
Modify the point light shader code, using the structure as a parameter.
Vec4 calcspotlight (struct SpotLight l, vec3 Normal)
{
VEC3 Lighttopixel = normalize (worldpos0-l.base.position);
float spotfactor = dot (lighttopixel, l.direction);
if (Spotfactor > L.cutoff) {
VEC4 Color = Calcpointlight (L.base, Normal);
Return Color * (1.0-(1.0-spotfactor) * 1.0/(1.0-l.cutoff));
}
else {
Return Vec4 (0,0,0,0);
}
}
Above is the function for calculating the spotlight effect.
...
for (int i = 0; i < gnumspotlights; i++) {
Totallight + = Calcspotlight (Gspotlights[i], Normal);
}
...
and the lighting of the point light is calculated the same way, for multi-source, we can accumulate the effect of the spotlight, so as to get the final pixel illumination color.
Lighting_technique.cpp
void lightingtechnique::setspotlights (unsigned int numlights, const spotlight* plights)
{
Gluniform1i (M_numspotlightslocation, numlights);
for (unsigned int i = 0; i < numlights; i++) {
gluniform3f (M_spotlightslocation[i]. Color, Plights[i]. Color.x, Plights[i]. Color.y, Plights[i]. COLOR.Z);
GLUNIFORM1F (M_spotlightslocation[i]. Ambientintensity, Plights[i]. ambientintensity);
GLUNIFORM1F (M_spotlightslocation[i]. Diffuseintensity, Plights[i]. diffuseintensity);
gluniform3f (M_spotlightslocation[i]. Position, Plights[i]. Position.x, Plights[i]. POSITION.Y, Plights[i]. POSITION.Z);
vector3f Direction = plights[i]. Direction;
Direction.normalize ();
gluniform3f (M_spotlightslocation[i]. Direction, direction.x, DIRECTION.Y, direction.z);
GLUNIFORM1F (M_spotlightslocation[i]. Cutoff, COSF (Toradian (plights[i). (Cutoff)));
GLUNIFORM1F (M_spotlightslocation[i]. Atten.constant, Plights[i]. Attenuation.constant);
GLUNIFORM1F (M_spotlightslocation[i]. Atten.linear, Plights[i]. Attenuation.linear);
GLUNIFORM1F (M_spotlightslocation[i]. Atten.exp, Plights[i]. ATTENUATION.EXP);
}
}
Above is the assignment to the uniform variable.
After the program executes the following effect: