Open GL Super Bible

Previous Table of Contents Next


After calling ChoosePixelFormat, the PIXELFORMATDESCRIPTOR information is filled with the actual hardware values that were chosen. On return, the dwFlags field can contain three additional flags that require your attention; they are listed in Table 15-3.

Table 15-3 PIXELFORMATDESCRIPTOR Return Values

Return Value Description

PFD_GENERIC_FORMAT The requested format is supported by the generic implementation.
PFD_NEED_PALETTE The RGBA color buffer will be drawn on a palette-managed device and requires a logical palette.
PFD_NEED_SYSTEM_PALETTE The color values require a fixed system palette to display correctly. Call SetSystemPaletteUse() to force a one-to-one mapping of the logical palette and the system palette.

If PFD_NEED_PALETTE is set, you should define a logical palette as specified by the cRedBits, cRedShift, cGreenBits, cGreenShift, cBlueBits, and cBlueShift fields. Following is an example of a defined palette.

HDC                   hdc;
PIXELFORMATDESCRIPTOR pfd;
HPALETTE              palette;
LOGPALETTE            *pal;
int                   i,
                      pf,
                      num_colors,
                      red, num_reds,
                      blue, num_blues,
                      green, num_greens;

// Get the current pixel format information
pf = GetPixelFormat(hdc);
DescribePixelFormat(hdc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

// Check to see if we need to make a palette
if (pfd.dwFlags & PFD_NEED_PALETTE)
{
  // Yes, we do.  First, allocate logical color palette entries...
  num_colors = 1 << pfd.cColorBits;
  pal        = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
                                       num_colors * sizeof(PALETTEENTRY));
  pal->palVersion    = 0x300;
  pal->palNumEntries = num_colors;

  num_reds   = (1 << pfd.cRedBits) - 1;
  num_greens = (1 << pfd.cGreenBits) - 1;
  num_blues  = (1 << pfd.cBlueBits) - 1;

  for (blue = 0, i = 0; blue <= num_blues; blue ++)
    for (green = 0; green <= num_greens; green ++)
      for (red = 0; red <= num_reds; red ++, i ++)
      {
        pal->palPalEntry[i].peRed   = 255 * red / num_reds;
        pal->palPalEntry[i].peGreen = 255 * green / num_greens;
        pal->palPalEntry[i].peBlue  = 255 * blue / num_blues;
        pal->palPalEntry[i].peFlags = 0;
      }

  palette = CreatePalette(pal);
  SelectPalette(hdc, palette, FALSE);
  RealizePalette(hdc);

  LocalFree(pal);
}

The Color Buffer

The color buffer holds pixel color information. Each pixel can contain a color index or red/green/blue/alpha (RGBA) values that describes the appearance of that pixel. RGBA pixels are displayed directly using the closest available color(s) on the screen. The generic OpenGL implementation from Microsoft does not support alpha color values at this time.

The appearance of color index pixels is determined by looking up the index in an RGB color table. Under Windows these color tables are implemented using a logical color palette. Color index mode is very useful for displaying tabular data graphically (for example, stress or force meters), as shown in the second depth buffer example in “Another Application of the Depth Buffer.”

Double Buffering

Double buffering provides an additional off-screen color buffer that is often used for animation. With double buffering you can draw a scene off screen and quickly “swap” it onto the screen, eliminating the annoying flicker that would otherwise be present.

Double buffering only affects the color buffer and does not provide a second depth, accumulation, or stencil buffer. If you choose a pixel format with double buffering, OpenGL selects the “back” buffer for drawing. You can change this using the glDrawBuffer function to specify one of the values in Table 15-4.

Table 15-4 glDrawBuffer Values

Buffer Description

GL_FRONT Draw only to the front (visible) color buffer.
GL_BACK Draw only to the back (hidden) color buffer.
GL_FRONT_AND_BACK Draw to both the front and back color buffers.

Stereo Buffering

Stereo buffering provides an additional color buffer in single-buffered mode and two additional color buffers in double-buffered mode, to generate a left- and right-eye screen image. (See Table 15-5.) True three-dimensional images can be generated by choosing the correct viewing positions for each eye, usually offset by a few “inches” to simulate the distance between our eyes. Stereo buffering is not available on most PC graphics cards.

Table 15-5 Stereo Buffer Values

Buffer Description

GL_LEFT_FRONT Draw only to the left-front buffer.
GL_LEFT_BACK Draw only to the left-back buffer.
GL_RIGHT_FRONT Draw only to the right-front buffer.
GL_RIGHT_BACK Draw only to the right-back buffer.
GL_FRONT Draw to both the left- and right-front buffers.
GL_BACK Draw to both the left- and right-back buffers.

In addition to specifying the front or back buffer for drawing, the glDrawBuffer function can select the left- or right-eye buffers.

Swapping Buffers

Open GL does support double buffering, but there is no OpenGL function to actually swap the front and back buffers! Fortunately, every windowing system with OpenGL support has a function call to accomplish this. Under Windows, this call is

SwapBuffers(hdc);

where hdc is the device context for the window in which you are drawing. If you have chosen a stereo-buffered pixel format, both the left and right eyes are swapped by the one call.


Previous Table of Contents Next