493 497














Open GL Super Bible:Buffers: Not Just for Animation















To access the contents, click the chapter and section titles.


Open GL Super Bible


(Publisher: Macmillan Computer Publishing)

Author(s): Waite group Press

ISBN: 1571690735

Publication Date: 08/01/96

 




Previous
Table of Contents
Next




The Accumulation Buffer
The accumulation buffer provides support for many special effects such as motion blur and depth of field. It also supports full-screen anti-aliasing, although other methods (such as multisampling) are better suited to this task.

The accumulation buffer is considerably less complex than the other buffers discussed so far. It has a single function, glAccum, that manages all accumulation buffer actions. The actions that can be performed are in Table 15-9.
Table 15-9 Accumulation Operations



Operation
Description



GL_ACCUM
Add scaled color-buffer values to the accumulation buffer.

GL_LOAD
Load scaled color-buffer values into the accumulation buffer, replacing whatever had been there before.

GL_ADD
Add a constant color to the accumulation bufferłs values.

GL_MULT
Multiply color values in the accumulation buffer by a constant color (filtering effects).

GL_RETURN
Copy the accumulation buffer into the main color buffer.



The normal way you use the accumulation buffer is to render multiple views into it and display the final composite scene with glAccum(GL_RETURN, 1.0).

Using the Accumulation Buffer for Motion Blur
As a coworker of ours once said, “ItÅ‚s easy to make any application of the accumulation buffer look like motion blur!" The problem is akin to what happens when your hands shake as you take a picture with a cameratoo much jitter will blur the image.
YouÅ‚ll find that rendering motion blur is a little more complicated than just drawing a sequence of frames with the camera moving between each frame. We perceive motion blur when an object moves faster than our eyes can track it. In essence, the picture changes as the brain is “processing" the image, but the focus on the moving target is never lost. In a camera, light entering the lens exposes the film for a finite amount of time. Depending on the camera and photographer, the amount of blur seen may be small around the edges, or it could streak across the image.
When you simulate motion blur with computer graphics, it is important to remember that the current (or final) position of the object you are blurring must look more solid (or focused) than the rest of the frames. The easiest way to accomplish this is to use a larger color scaling factor when accumulating the current frame so that more of the color values from the final frame used will stand out from the rest. A typical implementation looks something like this:

/* Draw the current frame */
draw_frame(0);
/* Load the accumulation buffer with 50% of the current frame */
glAccum(GL_LOAD, 0.5);

/* Draw the last 10 frames and accumulate 5% for each */
for (i = 1; i <= 10; i ++)
{
draw_frame(-i);
glAccum(GL_ACCUM, 0.05);
};

/* Display the final scene */
glAccum(GL_RETURN, 1.0);

Notice that you donłt have to use glClear to initialize the accumulation buffer contents, as you do with the color, depth, and stencil buffers. Instead, most often youłll use glAccum(GL_LOAD, s) on the first frame of the scene. The program in Listing 15-4 demonstrates motion blur on the cube and sphere.

Listing 15-4 MOTION.C:
Motion blur using the accumulation buffer

/*
* "motion.c" - A test program demonstrating the use of glAccum() for
* motion blur.
*/

#include <GL/glaux.h>

/*
* These #define constants are provided for compatibility between MS
* Windows and the rest of the world.
*
* CALLBACK and APIENTRY are function modifiers under MS Windows.
*/

#ifndef WIN32
# define CALLBACK
# define APIENTRY
#endif /* !WIN32 */

GLfloat rotation = 0.0;

/*
* 'reshape_scene()' - Change the size of the scene...
*/

void CALLBACK
reshape_scene(GLsizei width, /* I - Width of the window in pixels */
GLsizei height) /* I - Height of the window in pixels */
{
/*
* Reset the current viewport and perspective transformation...
*/

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(22.5, (float)width / (float)height, 0.1, 1000.0);

glMatrixMode(GL_MODELVIEW);
}

/*
* 'draw_scene()' - Draw a scene containing a cube with a sphere in
* front of it.
*/

void CALLBACK
draw_scene(void)
{
GLfloat frame;
static float red_light[4] = { 1.0, 0.0, 0.0, 1.0 };
static float red_pos[4] = { 1.0, 1.0, 1.0, 0.0 };
static float
blue_light[4] = { 0.0, 0.0, 1.0, 1.0 };
static float blue_pos[4] = { -1.0, -1.0, -1.0, 0.0 };

/*
* Enable drawing features that we need...
*/

glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);

glShadeModel(GL_SMOOTH);

/*
* Clear the color and depth buffers...
*/

glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/*
* Draw the cube and sphere in different colors...
*
* We have positioned two lights in this scene. The first is red and
* located above, to the right, and behind the viewer. The second
* is blue and located below, to the left, and in front of the viewer.
*/

glLightfv(GL_LIGHT0, GL_DIFFUSE, red_light);
glLightfv(GL_LIGHT0, GL_POSITION, red_pos);

glLightfv(GL_LIGHT1, GL_DIFFUSE, blue_light);
glLightfv(GL_LIGHT1, GL_POSITION, blue_pos);

/*
* Draw the objects 11 times starting at the current rotation...
*/

for (frame = 0.0; frame <= 11.0; frame ++)
{
glPushMatrix();
glTranslatef(0.0, 0.0, -20.0);
glRotatef(rotation - frame, 0.0, 1.0, 0.0);

glPushMatrix();
glTranslatef(-1.0, 0.0, 0.0);
auxSolidSphere(1.0);
glPopMatrix();

glPushMatrix();
glTranslatef(1.0, 0.0, 0.0);
glRotatef(15.0, 0.0, 1.0, 0.0);
glRotatef(15.0, 0.0, 0.0, 1.0);
auxSolidCube(2.0);
glPopMatrix();
glPopMatrix();

/*
* Accumulate 50% the first time, 5% every other time...
*/

if (frame == 0.0)
glAccum(GL_LOAD, 0.5);
else
glAccum(GL_ACCUM, 0.05);
};

/*
* Copy the accumulated results back to the color buffer...
*/

glAccum(GL_RETURN, 1.0);

auxSwapBuffers();
}

/*
* 'rotate_objects()' - Rotate while we are idle...
*/

void CALLBACK
rotate_objects(void)
{
rotation += 2.0;
if (rotation >= 360.0)
rotation -= 360.0;

draw_scene();
}

/*
* 'main()' - Initialize the window and display the scene until the user
* presses the ESCape key.
*/

int APIENTRY
WinMain(HINSTANCE hInstance,
HINSTANCE hPrev,
LPSTR lpCmdLine,
int nCmdShow)
{
auxInitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH | AUX_ACCUM);
auxInitWindow("Motion Blur");

auxReshapeFunc(reshape_scene);
auxIdleFunc(rotate_objects);

auxMainLoop(draw_scene);
}

/*
* End of "motion.c".
*/





Previous
Table of Contents
Next














 


Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.












Wyszukiwarka