Buffers and Their Uses (The Framebuffer) (OpenGL Programming)

An OpenGL system can manipulate the  following buffers:

•  Color buffers: front-left,  front-right,  back-left, back-right, and any number of auxiliary color buffers

•    Depth buffer

•    Stencil buffer

•    Accumulation buffer

Your particular OpenGL implementation determines which buffers are available and how many bits per pixel each buffer holds. Additionally, you can have multiple visuals, or window types, that have different buffers available. Table 10-1 lists the parameters to use with glGetIntegerv() to query your OpenGL system about per-pixel buffer storage for a particular visual.

Note: If you’re using the X Window System, you’re guaranteed, at a minimum, to have a visual with one color buffer for use in RGBA mode, with associated stencil, depth, and accumulation buffers that have color components of nonzero size. Also, if your X Window System implementation supports a Pseudo-Color visual, you are also guaranteed to have one OpenGL visual that has a color buffer for use in color-index mode, with associated depth and stencil buffers.

Parameter

Meaning

GL_RED_BITS, GL_GREEN_BITS, GL_BLUE_BITS, GL_ALPHA_BITS


number of bits per R, G, B, or A component in the color buffers

GL_INDEX_BITS

number of bits per index in the color buffers

GL_DEPTH_BITS

number of bits per pixel in the depth buffer

GL_STENCIL_BITS

number of bits per pixel in the stencil buffer

GL_ACCUM_RED_BITS,

GL_ACCUM_GREEN_BITS,

GL_ACCUM_BLUE_BITS,

GL_ACCUM_ALPHA_BITS

number of bits per R, G, B, or A component in the accumulation buffer

Table 10-1 Query Parameters for Per-Pixel Buffer Storage

Color Buffers

The color buffers are the ones to which you usually draw. They contain either color-index or RGB color data and may also contain alpha values. An OpenGL implementation that supports stereoscopic viewing has left and right color buffers for the left and right stereo images. If stereo isn’t supported, only the left buffers are used. Similarly, double-buffered systems have front and back buffers, and a single-buffered system has the front buffers only. Every OpenGL implementation must provide a front-left color buffer.

Optional, nondisplayable auxiliary color buffers may also be supported. OpenGL doesn’t specify any particular uses for these buffers, so you can define and use them however you please. For example, you might use them for saving an image that you use repeatedly. Then, rather than redrawing the image, you can just copy it from an auxiliary buffer into the usual color buffers.

You can use GL_STEREO or GL_DOUBLEBUFFER with glGetBooleanv() to find out if your system supports stereo (that is, has left and right buffers) or double-buffering (front and back buffers). To find out how many, if any, auxiliary buffers are present, use glGetIntegerv() with GL_AUX_BUFFERS.

Depth Buffer

The depth buffer stores a depth value for each pixel.The depth buffer is sometimes called the z buffer (the z comes from the fact that x- and y-values measure horizontal and vertical displacement on the screen, and the z-value measures distance perpendicular to the screen).

Stencil Buffer

One use for the stencil buffer is to restrict drawing to certain portions of the screen, just as a cardboard stencil can be used with a can of spray paint to make fairly precise painted images. For example, if you want to draw an image as it would appear through an odd-shaped windshield, you can store an image of the windshield’s shape in the stencil buffer, and then draw the entire scene. The stencil buffer prevents anything that wouldn’t be visible through the windshield from being drawn. Thus, if your application is a driving simulation, you can draw all the instruments and other items inside the automobile once, and as the car moves, only the outside scene need be updated.

Accumulation Buffer

The accumulation buffer holds RGBA color data just as the color buffers do in RGBA mode. (The results of using the accumulation buffer in color-index mode are undefined.) It’s typically used for accumulating a series of images into a final, composite image. With this method, you can perform operations such as scene antialiasing by supersampling an image and then averaging the samples to produce the values that are finally painted into the pixels of the color buffers. You don’t draw directly into the accumulation buffer; accumulation operations are always performed in rectangular blocks, which are usually transfers of data to or from a color buffer.

Clearing Buffers

In graphics programs, clearing the screen (or any of the buffers) is typically one of the most expensive operations you can perform—on a 1280 χ 1024 monitor, it requires touching well over a million pixels. For simple graphics applications, the clear operation can take more time than the rest of the drawing. If you need to clear not only the color buffer but also the depth and stencil buffers, the clear operation can be three times as expensive.

To address this problem, some machines have hardware that can clear more than one buffer at once. The OpenGL clearing commands are structured to take advantage of such architectures. First, you specify the values to be written into each buffer to be cleared. Then you issue a single command to perform the clear operation, passing in a list of all the buffers to be cleared. If the hardware is capable of simultaneous clears, they all occur at once; otherwise, the buffers are cleared sequentially.

The following commands set the clearing values for each buffer:

void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); void glClearlndex(GLfloat index); void glClearDepth(GLclampd depth); void glClearStencil(GLint 5);

void glClearAccum(GLfloat red, GLfloat green, GLfloat blue,GLfloat alpha);

Specifies the current clearing values for the color buffer (in RGBA mode), the color buffer (in color-index mode), the depth buffer, the stencil buffer, and the accumulation buffer. The GLclampf and GLclampd types (clamped GLfloat and clamped GLdouble) are clamped to be between 0.0 and 1.0. The default depth-clearing value is 1.0; all the other default clearing values are 0. The values set with the clear commands remain in effect until they’re changed by another call to the same command.

After you’ve selected your clearing values and you’re ready to clear the buffers, use glClearQ:

void glClear(GLbitfield mask);

Clears the specified buffers. The value of mask is the bitwise logical OR of some combination of GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_ BIT, GL_STENCIL_BUFFER_BIT, and GL_ACCUM_BUFFER_BIT to identify which buffers are to be cleared. GL_COLOR_BLTFFER_BIT clears either the RGBA color buffer or the color-index buffer, depending on the mode of the system at the time. When you clear the color or color-index buffer, all the color buffers that are enabled for writing (see the next section) are cleared. The pixel ownership test, scissor test, and dithering, if enabled, are applied to the clearing operation. Masking operations, such as glColorMask() and glIndexMask(), are also effective. The alpha test, stencil test, and depth test do not affect the operation of glClear().

Selecting Color Buffers for Writing and Reading

The results of a drawing or reading operation can go into or come from any of the color buffers: front, back, front-left, back-left, front-right, back-right, or any of the auxiliary buffers. You can choose an individual buffer to be the drawing or reading target. For drawing, you can also set the target to draw into more than one buffer at the same time. You use glDrawBuffer() to select the buffers to be written and glReadBufferQ to select the buffer as the source for glReadPixels(), glCopyPixels(), glCopyTexImage*(), and glCopyTexSublmage* ().

If you are using double-buffering, you usually want to draw only in the back buffer (and swap the buffers when you’re finished drawing). In some situations, you might want to treat a double-buffered window as though it were single-buffered by calling glDrawBuffer() to enable you to draw to both front and back buffers at the same time.

glDrawBuffer() is also used to select buffers to render stereo images (GL*LEFT and GL*RIGHT) and to render into auxiliary buffers (GL_AUXi).

void gIDrawBuffer(GLenum mode);

void glDrawBuffers(GLsizei n. const GLenum * buffers);

Selects the color buffers enabled for writing or clearing and disables buffers enabled by previous calls to glDrawBufferQ. More than one buffer may be enabled at one time. The value of mode can be one of the following:

GL_FRONT

GL_FRONT_LEFT

GL_AUX/

GL_BACK

gl_front_right

GL_FRONT_AND_BACK

GLJEFT

GL_BACK_LEFT

GL_NONE

GL.RIGHT

Gl._BACK_RK.THr

Arguments that omit LEFT or RIGHT refer to both the left and right stereo buffers; similarly, arguments that omit FRONT or BACK refer to both . The i in GL_AUXi is a digit identifying a particular auxiliary buffer.

By default, mode is GL_FRONT for single-buffered contexts and GL_BACK for double-buffered contexts.

OpenGL 2.0 added the glDrawBuffersQ routine, which specifies multiple color buffers capable of recieving color values buffers is an array of buffer enumerates. Only GL_NONE, GL_FRONT_LEFT, GL_FRONT_RlGHT, GL_BACK_LF,FT, GL_BACK_R1GHT, and GL_AUX; are accepted.

If the fixed-function OpenGL pipeline is utilized tor generating fragment colors, each of the specified buffers recieves the same color vauie. If a fragment shader is employed and specifies output to multiple buffers, then each buffer will be written with the color specified in the shader’s output.

Note: You can enable drawing to nonexistent buffers as long as you enable drawing to at least one buffer that does exist. If none of the specified buffers exists, an error results.

void glReadBuffer(GLenum mode);

Selects the color buffer enabled as the source for reading pixels for subsequent calls to glReadPixels(), glCopyPixels(), gICopyTexImage*(), glCopyTexSubImage*(), and glCopyConvolutionFilter*(), and disables buffers enabled by previous calls to glReadBuffer(). The value of mode can be one of the following:

GL_FRONT

GL_FRONT_LEFT

GL_AUXi

GL BACK

GL_FRONT_RIGHT

GL_LEFT

GL_BACK_LEFT

GL_RIGHT

gl_back_right

The buffers for glReadBuffer() are the same as those described for gIDrawBuffer(). By default, mode is GL_FRONT for single-buffered contexts and GL_BACK for double-buffered contexts.

Note: You must enable reading from a buffer that exists or an error results. Masking Buffers

Before OpenGL writes data into the enabled color, depth, or stencil buffers, a masking operation is applied to the data, as specified with one of the following commands. A bitwise logical AND is performed with each mask and the corresponding data to be written.

Sets the masks used to control writing into the indicated buffers. The mask set by glIndexMask() applies only in color-index mode. If a 1 appears in mask, the corresponding bit in the color-index buffer is written; if a 0 appears, the bit isn’t written. Similarly, glColorMask() affects drawing m RGBA mode only. The red, green, blue, and alpha values control whether the corresponding component is written. (GL_TRUE means it is written.)

If flag is GL_TRUE for glDepthMask(), the depth buffer is enabled for writing; otherwise, it’s disabled. The mask for glStencilMask() is used for stencil data in the same way as the mask is used for color-index data in gllndexMaskQ. The default values of all the GLboolean masks are GL_TRUE, and the default values for the two GLuint masks are all l’s.

OpenGL 2.0 includes the glStencilMaskSeparate() function that allows separate mask values for front- and back-facing polygons.

You can do plenty of tricks with color masking in color-index mode. For example, you can use each bit in the index as a different layer and set up interactions between arbitrary layers with appropriate settings of the color map. You can create overlays and underlays, and do so-called color-map animations.

Disabling the depth buffer for writing can also be useful if a common background is desired for a series of frames, and you want to add some features that may be obscured by parts of the background. For example, suppose your background is a forest, and you would like to draw repeated frames with the same trees, but with objects moving among them. After the trees are drawn and their depths recorded in the depth buffer, the image of the trees is saved, and the new items are drawn with the depth buffer disabled for writing. As long as the new items don’t overlap each other, the picture is correct. To draw the next frame, restore the image of the trees and continue. You don’t need to restore the values in the depth buffer. This trick is most useful if the background is extremely complex—so complex that it’s much faster just to recopy the image into the color buffer than to recompute it from the geometry.

Note: The mask specified by glStencilMask() controls which stencil bit-planes are written. This mask isn’t related to the mask that’s specified as the third parameter of glStencilFunc(), which specifies which bit-planes are considered by the stencil function.

Next post:

Previous post: