Open GL Super Bible

Previous Table of Contents Next


Creating a Spotlight

Creating a spotlight is no different from creating any other directional light source. The code in Listing 9-8 shows the SetupRC() function from the SPOT example program. This program places a blue sphere in the center of the window. A spotlight is created that can be moved vertically with the up and down arrow keys, and horizontally with the left and right arrow keys. As the spotlight moves over the surface of the sphere, a specular highlight follows it on the surface.

Listing 9-8 Lighting setup for the SPOT sample program

// Light values and coordinates
GLfloat  lightPos[] = { 0.0f, 0.0f, 75.0f, 1.0f };
GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
GLfloat  specref[] =  { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat  ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f};
GLfloat  spotDir[] = { 0.0f, 0.0f, -1.0f };

// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
        {
        glEnable(GL_DEPTH_TEST);   // Hidden surface removal
        glFrontFace(GL_CCW);       // Counterclockwise polygons face out
        glEnable(GL_CULL_FACE);    // Do not try to display the back sides

        // Enable lighting
        glEnable(GL_LIGHTING);

        // Set up and enable light 0
        // Supply a slight ambient light so the objects can be seen
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);

        // The light is composed of just diffuse and specular components
        glLightfv(GL_LIGHT0,GL_DIFFUSE,ambientLight);
        glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);

        // Specific spot effects
        // Cut off angle is 60 degrees
        glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);

        // Fairly shiny spot
        glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,100.0f);

        // Enable this light in particular
        glEnable(GL_LIGHT0);

        // Enable color tracking
        glEnable(GL_COLOR_MATERIAL);

        // Set Material properties to follow glColor values
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

        // All materials hereafter have full specular reflectivity
        // with a high shine
        glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
        glMateriali(GL_FRONT, GL_SHININESS,128);

        // Black background
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
        }

The following lines are actually what make a positional light source into a spotlight:

// Specific spot effects
// Cut off angle is 60 degrees
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);

// Fairly shiny spot
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,100.0f);

The GL_SPOT_CUTOFF value specifies the radial angle of the cone of light emanating from the spotlight. For a normal positional light, this is 180? so that the light is not confined to a cone. Spotlights emit a cone of light, and objects outside this cone are not illuminated. Figure 9-22 shows how this angle translates to the cone width.


Figure 9-22  The angle of the spotlight’s cone

Drawing a Spotlight

When you place a spotlight in a scene, the light must come from somewhere. Just because you have a source of light at some location doesn’t mean that you will see a bright spot there. For our SPOT example program, we placed a red cone at the spotlight source to show where the light was coming from. Inside the end of this cone, we placed a bright yellow sphere to simulate a light bulb. Listing 9-9 shows the complete code to render the scene.

Make special note of the statement

glPushAttrib(GL_LIGHTING_BIT);

Just following this statement, we disable lighting and render a bright yellow sphere. Then we make a call to

glPopAttrib();

The first statement saves the state of all the lighting state variables. Then we can just disable lighting long enough to draw a yellow light bulb and put the lighting system back the way it was. See the Chapter 14 Reference Section entries for glPushAttrib and glPopAttrib for more information on saving and restoring state variables. A sample screen from our SPOT example program is shown in Figure 9-23.


Figure 9-23  Output of the SPOT program demonstrating spotlights

Listing 9-9 The rendering function for SPOT, showing how the spotlight is moved

// Called to draw scene
void RenderScene(void)
        {
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Set material color and draw a sphere in the middle
        glRGB(0, 0, 255);
        auxSolidSphere(30.0f);

// Now place the light 
// Save the coordinate transformation
glPushMatrix();
        // Rotate coordinate system
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);

        // Specify new position and direction in rotated coords.
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
        glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);

        // Draw a red cone to enclose the light source
        glRGB(255,0,0);

        // Translate origin to move the cone out to where the light
        // is positioned.
        glTranslatef(lightPos[0],lightPos[1],lightPos[2]);
        auxSolidCone(4.0f,6.0f);

        // Draw a smaller displaced sphere to denote the light bulb
        // Save the lighting state variables
        glPushAttrib(GL_LIGHTING_BIT);

                // Turn off lighting and specify a bright yellow sphere
                glDisable(GL_LIGHTING);
                glRGB(255,255,0);
                auxSolidSphere(3.0f);

        // Restore lighting state variables
        glPopAttrib();

// Restore coordinate transformations
glPopMatrix();

// Flush drawing commands
glFlush();
}


Previous Table of Contents Next