Open GL Super Bible

Previous Table of Contents Next


This leads us to the second and preferred way of setting material properties, called color tracking. With color tracking you can tell OpenGL to set material properties by only calling glColor. To enable color tracking, call glEnable() with the GL_COLOR_MATERIAL parameter:

glEnable(GL_COLOR_MATERIAL);

Then the function glColorMaterial specifies the material parameters that will follow the values set by glColor.

For example, to set the ambient and diffuse properties of the fronts of polygons to track the colors set by glColor, call

glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

The earlier code fragment setting material properties would then be as follows. This looks like more code, but it will actually save many lines of code and execute faster as the number of polygons grows.

// Enable color tracking
glEnable(GL_COLOR_MATERIAL);

// Front material ambient and diffuse colors track glColor
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);

Ö
Ö
glcolor3f(0.75f, 0.75f, 0.75f);
glBegin(GL_TRIANGLES);
        glVertex3f(-15.0f,0.0f,30.0f);
        glVertex3f(0.0f, 15.0f, 30.0f);
        glVertex3f(0.0f, 0.0f, -56.0f);
glEnd();

Listing 9-1 contains the code we add with the SetupRC function to our JET example, to set up a bright ambient light source, and to set the material properties that allow the object to reflect light and be seen. We have also changed the colors of the jet so that each section is a different color rather than each polygon. Notice in the final output (Figure 9-7) that itís not much different from the image before we had lighting. However, if we reduce the ambient light by half, we get the image shown in Figure 9-8. This is accomplished by setting the ambient light RGBA values to the following:

GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };


Figure 9-7  Output from completed AMBIENT example program


Figure 9-8  Output from AMBIENT when the light source is cut in half

You can see how we might reduce the ambient light in a scene to produce a dimmer image. This is useful for simulations in which dusk approaches gradually or when a more direct light source is blocked, as when an object is in the shadow of another, larger object.

Listing 9-1 Set up for ambient lighting conditions

// This function does any needed initialization on the rendering
// context.  Here it sets up and initializes the lighting for
// the scene.
void SetupRC()
        {
        // Light values
        // Bright white light
        GLfloat ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };

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

        // Lighting stuff
        glEnable(GL_LIGHTING);      // Enable lighting 
   
        // Set light model to use ambient light specified by ambientLight[]
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);

        glEnable(GL_COLOR_MATERIAL);   // Enable Material color tracking

        // Front material ambient and diffuse colors track glColor
        glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

        // Nice light blue background
        glClearColor(0.0f, 0.0f, 05.f,1.0f);
        }

Using a Light Source

Manipulating the ambient light has its uses, but for most applications attempting to model the real world, one or more specific sources of light must be specified. In addition to their intensities and colors, these sources will have a location and a direction. The placement of these lights can dramatically affect the appearance of your scene.

OpenGL supports up to eight independent light sources located anywhere in your scene or out of the viewing volume. You can locate a light source an infinite distance away and make its light rays parallel, or make it a nearby light source radiating outward. You can also specify a spotlight with a specific cone of light radiating from it, as well as manipulate its characteristics.

Which Way Is Up?

When you specify a light source, you tell OpenGL where it is and in which direction itís shining. Often the light source will be shining in all directions, or it may be directional. Either way, for any object you draw, the rays of light from any source (other than a pure ambient source) will strike the surface of the polygons that make up the object at an angle. Of course, in the case of a directional light, the surface of all polygons may not necessarily be illuminated. To calculate the shading effects across the surface of the polygons, OpenGL must be able to calculate this angle.

In Figure 9-9, a polygon (a square) is being struck by a ray of light from some source. The ray makes an angle (A) with the plane as it strikes the surface. The light is then reflected at an angle (B) toward the viewer (or you wouldnít see it). These angles are used in conjunction with the lighting and material properties we have discussed thus far to calculate the apparent color of that location. It happens by design that the locations used by OpenGL are the vertices of the polygon. By calculating the apparent colors for each vertex and then doing smooth shading between them (explained in Chapter 8), the illusion of lighting is created. Magic!


Figure 9-9  Light is reflected off objects at specific angles

From a programming standpoint, this presents a slight conceptual difficulty. Each polygon is created as a set of vertices, which are nothing more than points. Each vertex is then struck by a ray of light at some angle. How then do you (or OpenGL) calculate the angle between a point and a line (the ray of light)? Of course you canít geometrically find the angle between a single point and a line in 3D space, because there are an infinite number of possibilities. Therefore, you must associate with each vertex some piece of information that denotes a direction upward from the vertex and away from the surface of the primitive.


Previous Table of Contents Next