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.
We could have corrected this by changing the winding rule, by calling
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.
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.
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.
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.
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.
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.
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
and then call
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.
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.