Open GL Super Bible

Previous Table of Contents Next

Listing 9-11 Setting up the shadow projection matrix

GLfloat lightPos[] = { -75.0f, 150.0f, -50.0f, 0.0f };

// Transformation matrix to project shadow
GLfloat shadowMat[4][4];

// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
            // Any three points on the ground (counterclockwise order)
            GLfloat points[3][3] = {{ -30.0f, -149.0f, -20.0f },
                                   { -30.0f, -149.0f, 20.0f },
                                   {40.0f, -149.0f, 20.0f }};

            glEnable(GL_DEPTH_TEST);   // Hidden surface removal
            glFrontFace(GL_CCW);       // Counterclockwise polygons
                                           face out
            glEnable(GL_CULL_FACE);    // Do not calculate inside of jet

            // Enable lighting

            // Code to setup lighting, etc.

            // Light blue background
            glClearColor(0.0f, 0.0f, 1.0f, 1.0f );

            // Calculate projection matrix to draw shadow on the ground
            MakeShadowMatrix(points, lightPos, shadowMat);

Listing 9-12 shows the rendering code for the SHADOW example. We first draw the jet as we normally would; then we restore the Modelview matrix and multiply it by the shadow matrix. This creates our squish Projection matrix. Then we draw the jet again (we’ve modified our code to accept a flag telling the DrawJet function to render in color or black). After restoring the Modelview matrix once again, we draw a small yellow sphere to approximate the position of the light, and then draw a plane below the jet to indicate the ground. This rectangle lies in the same plane in which our shadow will be drawn.

Listing 9-12 Render the jet and its shadow

// Called to draw scene
void RenderScene(void)
        // Clear the window with current clearing color

        // Save the matrix state and do the rotations

        // Draw jet at new orientation, put light in correct position
        // before rotating the jet
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);


        // Restore original matrix state

        // Get ready to draw the shadow and the ground
        // First disable lighting and save the projection state

        // Multiply by shadow projection matrix
        glMultMatrixf((GLfloat *)shadowMat);

        // Now rotate the jet around in the new flattened space
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);

        // Pass true to indicate drawing shadow

        // Restore the projection to normal

        // Draw the light source
        glTranslatef(lightPos[0],lightPos[1], lightPos[2]);

        // Draw the ground; we do manual shading to a darker green
        // in the background to give the illusion of depth
                glVertex3f(400.0f, -150.0f, -200.0f);
                glVertex3f(-400.0f, -150.0f, -200.0f);
                glVertex3f(-400.0f, -150.0f, 200.0f);
                glVertex3f(400.0f, -150.0f, 200.0f);

        // Restore lighting state variables

        // Flush drawing commands

Lighting and Color Index Mode

In Chapter 8, you learned that in color index mode, color is specified as an index into a palette rather than as components of red, green, and blue light. This has some obvious implications for lighting effects. Most of the lighting functions expect light and material properties to be specified in terms of these RGBA components.

Some consideration is made for color index mode by OpenGL, but in color index mode your lights may only contain diffuse and specular components. Material properties can include shininess, ambient, diffuse, and specular light, and although this may be enough to do some lighting, it is questionable whether it’s actually worth the effort.

In order to do lighting, your palette must contain three color ramps for ambient, diffuse, and specular colorings. To achieve satisfactory results, your ramps will usually progress from black to shades of a single color and finally to white. It’s possible to define these such that you produce a smoothly shaded object in a single color, but this has few if any practical applications.

Generally, most recognized OpenGL texts recommend that you avoid color index mode for lighting effects. Still, if you must use it, the CD contains a supplementary example called ILIGHT that shows how to use color index mode to illuminate a scene with some objects. However, all these objects are the same color!


In this chapter you have been introduced to some of the more magical and powerful capabilities of OpenGL. You’ve seen how to specify one or more light sources and define their lighting characteristics in terms of ambient, diffuse, and specular components. We explained how the corresponding material properties interact with these light sources, and demonstrated some special effects such as adding specular highlights and softening sharp edges.

Also covered were lighting positions, and creation and manipulation of spotlights. The high-level matrix munching function presented here will make shadow generation as easy as it gets. Finally, we explained why you should avoid color index mode for lighting effects. The demonstration programs in this chapter are fairly simple, but you’ll find more samples on the CD in the subdirectory for this chapter. The programs on the CD further demonstrate all of these effects, including scenes with more than one light source.

Previous Table of Contents Next