Open GL Super Bible

Previous Table of Contents Next


Chapter 11
Raster Graphics in OpenGL

What you’ll learn in this chapter:

How to… Functions You’ll Use

Draw bitmap images glBitmap/glRasterPos
Use bitmap fonts wglUseFontBitmaps/glGenLists/glCallLists
Draw color images glDrawPixels
Read and copy color images on the screen glCopyPixels/glReadPixels
Read and write Windows bitmap files LoadDIBitmap/SaveDIBitmap

You’ve probably heard a lot of sales hype lately about how much better it is to work with 3D graphics than with those old 2D graphics from years ago. While this is true for the most part, ultimately those 3D graphics are drawn in two dimensions on your screen. Raster graphics are two-dimensional arrays of colors and are used not only for displaying 3D graphics on the screen but also for printing images on raster printers or motion-picture film

In addition to the vector and polygon functions we’ve examined so far, OpenGL provides several functions that directly manage 2D bitmaps and images. Those functions are the subject of this chapter.

Drawing Bitmaps

Bitmaps in OpenGL are two-color images that are used to quickly draw characters or symbols (such as icons) on the screen. This diverges from the (incorrect) Microsoft Windows definition that includes multicolored images, as well. OpenGL provides a single function to draw bitmaps: glBitmap. When you draw a bitmap with glBitmap, the first color (0) is transparent. The second color (1) is drawn using the current color and lighting material attributes.

Figure 11-1 shows an OpenGL bitmap image of smiley faces. The code (Listing 11-1) to draw this window consists of the bitmap data followed by a call to glBitmap.


Figure 11-1  Output from glBitmap example

Listing 11-1 Drawing the window of smiley faces

void
RepaintWindow(RECT *rect)   /* I - Client area rectangle */
{
  int            i;         /* Looping var */
  static GLubyte smiley[] = /* 16x16 smiley face */
  {
    0x03, 0xc0, 0, 0, /*       ****       */
    0x0f, 0xf0, 0, 0, /*     ********     */
    0x1e, 0x78, 0, 0, /*    ****  ****    */
    0x39, 0x9c, 0, 0, /*   ***  **  ***   */
    0x77, 0xee, 0, 0, /*  *** ****** ***  */
    0x6f, 0xf6, 0, 0, /*  ** ******** **  */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0x73, 0xce, 0, 0, /*  ***  ****  ***  */
    0x73, 0xce, 0, 0, /*  ***  ****  ***  */
    0x3f, 0xfc, 0, 0, /*   ************   */
    0x1f, 0xf8, 0, 0, /*    **********    */
    0x0f, 0xf0, 0, 0, /*     ********     */
    0x03, 0xc0, 0, 0  /*       ****       */
  };
  glViewport(0, 0, rect->right, rect->bottom);

  glClearColor(0.0, 0.0, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, rect->right - 1.0, 0.0, rect->bottom - 1.0, -1.0, 1.0);

 /*
  * This bitmap is aligned to 4-byte boundaries…
  */

  glPixelTransferi(GL_UNPACK_ALIGNMENT, 4);

  glColor3f(1.0, 0.0, 0.0);
  for (i = 0; i < 100; i ++)
  { 
    glRasterPos2i(rand() % rect->right, rand() % rect->bottom);
    glBitmap(16, 16, 8.0, 8.0, 0.0, 0.0, smiley);
  };

  glFinish();
}

In this example, we have defined a 16 x 16-pixel bitmap image of a smiley face. The bitmap is an array of 32 unsigned bytes (GLubyte), with bit 7 of the first byte corresponding to the bottom-left corner.


Some Things to Note About Bitmaps:  
OpenGL bitmaps are usually defined “upside down.” That is, they are stored from bottom to top. (In fact, you can see that the happy face defined as “smiley” is upside down.) To define them from top to bottom, you must specify a negative height. Also, because of bugs in the Microsoft OpenGL libraries, you must align each scanline (row) of bitmap data to a 4-byte boundary. With a properly functioning OpenGL library, you could use the glPixelStore function described later in this chapter to change the bitmap alignment.

After defining a bitmap image to draw, we must specify the current raster position by calling the glRasterPos function:

glRasterPos2i(rand() % rect->right, rand() % rect->bottom);

In this example, we are positioning our smiley face randomly within the client area of our window with the bitmap offset by 8 pixels from the left and bottom. The raster position is specified in world/model coordinates, just like a glVertex position. In addition to setting the current raster position, glRasterPos also sets a raster position valid flag. This Boolean flag is True if the raster position lies inside the current viewport, and False otherwise.


A Note About Clipping:  
Polygons and other vector-drawing primitives will still be drawn if they lie partially out of the current viewport, and clipped to the edges of the viewport. Clipping for bitmaps works a little differently. If the raster position you specify lies outside of the current viewport, the bitmap will not be drawn.

To draw the bitmap, call the glBitmap function:

glBitmap(16, 16, 8.0, 8.0, 0.0, 0.0, smiley);

In this case we are drawing a 16 x 16 bitmap whose center lies at (8.0, 8.0) in the bitmap. After the bitmap is drawn, the raster position is moved (0.0, 0.0) pixels.

The prototype for this function is as follows:

glBitmap(GLsizei width, GLsizei height,
         Gfloat xorig, GLfloat yorig,
         GLfloat xmove, GLfloat ymove,
         const GLubyte *bits)


Previous Table of Contents Next