Open GL Super Bible

Previous Table of Contents Next


Note that we first changed the definition of front-facing polygons to be those with clockwise winding (because our triangle fans are all wound clockwise).

Figure 6-20 demonstrates that the bottom of the cone is gone when culling is enabled. This is because we didnít follow our own rule about all the surface polygons having the same winding. The triangle fan that makes up the bottom of the cone is wound clockwise, like the fan that makes up the sides of the cone, but the front side of the coneís bottom section is facing the inside. See Figure 6-21.


Figure 6-20  The bottom of the cone is culled because the front-facing triangles are inside


Figure 6-21  How the cone was assembled from two triangle fans

We could have corrected this by changing the winding rule, by calling

glFrontFace(GL_CCW);

just before we drew the second triangle fan. But in this example we wanted to make it easy for you to see culling in action, as well as get set up for our next demonstration of polygon tweaking.

Polygon Modes

Polygons donít have to be filled with the current color. By default, polygons are drawn solid, but you can change this behavior by specifying that polygons are to be drawn as outlines or just points (only the vertices are plotted). The function glPolygonMode() allows polygons to be rendered filled, as outlines, or as points only. In addition, this rendering mode can be applied to both sides of the polygons or to just the front or back. The following code from Listing 6-8 shows the polygon mode being set to outlines or solid, depending on the state of the Boolean variable bOutline:

// Draw back side as a polygon only, if flag is set
if(bOutline)
        glPolygonMode(GL_BACK,GL_LINE);
else
        glPolygonMode(GL_BACK,GL_FILL);

Figure 6-22 shows the back sides of all polygons rendered as outlines. (We had to disable culling to produce this image; otherwise, the inside would be eliminated and youíd get no outlines.) Notice that the bottom of the cone is now wireframe instead of solid, and you can see up inside the cone where the inside walls are also drawn as wireframe triangles.


Figure 6-22  Using glPolygonMode() to render one side of the triangles as outlines

Other Primitives

Triangles are the preferred primitive for object composition since most OpenGL hardware specifically accelerates triangles, but they are not the only primitives available. Some hardware will provide for acceleration of other shapes as well, and programmatically it may be simpler to use a general-purpose graphics primitive. The remaining OpenGL primitives provide for rapid specification of a quadrilateral or quadrilateral strip, as well as a general-purpose polygon. If you know your code is going to be run in an environment that accelerates general-purpose polygons, these may be your best bet in terms of performance.

Four-Sided Polygons: Quads

The next most complex shape from a triangle is a quadrilateral, or a four-sided figure. OpenGLís GL_QUADS primitive draws a four-sided polygon. In Figure 6-23 a quad is drawn from four vertices. Note also that quads have clockwise winding.


Figure 6-23  An example of GL_QUAD

Quad Strips

Just as you can for triangles, you can specify a strip of connected quadrilaterals with the GL_QUAD_STRIP primitive. Figure 6-24 shows the progression of a quad strip specified by six vertices. Quad strips, like single GL_QUADS, maintain a clockwise winding.


Figure 6-24  Progression of GL_QUAD_STRIP

General Polygons

The final OpenGL primitive is the GL_POLYGON, which can be used to draw a polygon having any number of sides. Figure 6-25 shows a polygon consisting of five vertices. Polygons created with GL_POLYGON have clockwise winding, as well.


Figure 6-25  Progression of GL_POLYGON


What About Rectangles?
All ten of the OpenGL primitives are used with glBegin/glEnd to draw general-purpose polygonal shapes. One shape is so common, it has a special function instead of being a primitive; that shape is the rectangle. It was actually the first shape you learned to draw back in Chapter 3. The function glRect() provides an easy and convenient mechanism for specifying rectangles without having to resort to GL_QUAD.

Filling Polygons, or Stippling Revisited

There are two methods of applying a pattern to solid polygons. The customary method is texture mapping, where a bitmap is mapped to the surface of a polygon, and this is covered in Chapter 11. Another way is to specify a stippling pattern, as we did for lines. A polygon stipple pattern is nothing more than a 32 x 32 monochrome bitmap that is used for the fill pattern.

To enable polygon stippling, call

glEnable(GL_POLYGON_STIPPLE);

and then call

glPolygonStipple(pBitmap);

where pBitmap is a pointer to a data area containing the stipple pattern. Hereafter, all polygons will be filled using the pattern specified by pBitmap (GLubyte *). This pattern is similar to that used by line stippling, except the buffer is large enough to hold a 32 x 32-bit pattern. Also, the bits are read with the MSB (Most Significant Bit) first, which is just the opposite of line stipple patterns. Figure 6-26 shows a bit pattern for a campfire that we will use for a stipple pattern.


Figure 6-26  Building a polygon stipple pattern


Pixel Storage
As you will learn in Chapter 11, you can modify the way pixels for stipple patterns are interpreted, with the glPixelStore() function. For now, though, we will stick to simple polygon stippling.

To construct a mask to represent this pattern, we store one row at a time from the bottom up. Fortunately, unlike line-stipple patterns, the data is by default interpreted just as it is stored, with the most significant bit read first. Each byte can then be read from left to right and stored in an array of GLubyte large enough to hold 32 rows of 4 bytes apiece.


Previous Table of Contents Next