Our previous working definition for glColor was that this function set the current drawing color, and all objects drawn after this command would have the last color specified. Now that we have discussed the OpenGL drawing primitives (Chapter 6), we can expand this definition to this: The glColor function sets the current color that is used for all vertices drawn after the command. So far, all of our examples have drawn wireframe objects, or solid objects with each face a different but solid color. If we specify a different color for each vertex of a primitive (either point, line, or polygon), what color is the interior?
Let’s answer this question first regarding points. A point has only one vertex, and whatever color you specify for that vertex will be the resulting color for that point.
A line, however, has two vertices and each can be set to a different color. The color of the line depends on the shading model. Shading is simply defined as the smooth transition from one color to the next. Any two points in our RGB color space (Figure 8-7) can be connected by a straight line.Smooth shading causes the colors along the line to vary as they do through the color cube from one color point to the other. In Figure 8-9, the color cube is shown with the black and white corners pointed out. Below it is a line with two vertices, one black and one white. The colors selected along the length of the line match the colors along the straight line in the color cube, from the black to the white corners. This results in a line that progresses from black through lighter and lighter shades of gray and eventually to white.
You can do shading mathematically by finding the equation of the line connecting two points in the three-dimensional RGB color space. Then simply loop through from one end of the line to the other, retrieving coordinates along the way to provide the color of each pixel on the screen. Many good books on computer graphics will explain the algorithm to accomplish this and scale your color line to the physical line on the screen, etc. Fortunately, OpenGL will do all this for you!
The shading exercise becomes slightly more complex for polygons. A triangle, for instance, can also be represented as a plane within the color cube. Figure 8-10 shows a triangle with each vertex at full saturation for the red, green, and blue color components. The code to display this triangle is in Listing 8-1, and in the example program TRIANGLES on the CD.
Listing 8-1 Drawing a smooth-shaded triangle with red, green, and blue corners
// Enable smooth shading glShadeModel(GL_SMOOTH); // Draw the triangle glBegin(GL_TRIANGLES); // Red Apex glColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0); glVertex3f(0.0f,200.0f,0.0f); // Green on the right bottom corner glColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0); glVertex3f(200.0f,-70.0f,0.0f); // Blue on the left bottom corner glColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255); glVertex3f(-200.0f, -70.0f, 0.0f); glEnd();
The first line of Listing 8-1 actually sets the shading model OpenGL uses to do smooth shading—the model we have been discussing. This is the default shading model, but it’s a good idea to call this function anyway to ensure that your program is operating the way you intended.
(The other shading model that can be specified with glShadeModel is GL_FLAT for flat shading. Flat shading means that no shading calculations are performed on the interior of primitives. Generally, with flat shading the color of the primitive’s interior is the color that was specified for the last vertex. The only exception is for a GL_POLYGON primitive, in which case the color is that of the first vertex.)
Then the code in Listing 8-1 sets the top of the triangle to be pure red, the lower-right corner to be green, and the remaining bottom-left corner to be blue. Because smooth shading is specified, the interior of the triangle is shaded to provide a smooth transition between each corner.
The output from the TRIANGLE program is shown in Figure 8-11. This represents the plane shown graphically in Figure 8-10.
Polygons, more complex than triangles, can also have different colors specified for each vertex. In these instances, the underlying logic for shading can become more intricate. Fortunately, you never have to worry about it with OpenGL. No matter how complex your polygon, OpenGL will successfully shade the interior points between each vertex.
Note that you will rarely wish to do this type of shading yourself, anyway. This is primarily used to produce lighting effects, and OpenGL once again comes to the rescue. We’ll cover lighting in the Chapter 9.
The TRIANGLE and CCUBE example programs work reasonably well regardless of how many colors are available. If you can change the color depth of your system, try running these programs at the various color depths, starting at 16 colors and going up to 16 million if possible. You’ll notice that the colors make a smooth transition regardless of color depth, but the higher color depths provide a smoother and more appealing image. Figures 8-12a and 8-12b show the output of the TRIANGLES sample with 16 colors and 16 million colors, respectively. Even though these pictures are not in color, you can see how much smoother the second triangle appears.