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
Drawing into the Stencil Buffer
Once you have enabled the GL_STENCIL_TEST attribute with glEnable, youłll still need to set up how the stencil buffer operates. By default, it does nothing, allowing drawing to occur anywhere on the screen without updating the stencil buffer. To make stenciling work effectively, however, we need to put values into the stencil buffer. The glStencilFunc and glStencilOp functions handle this interaction.
The glStencilFunc function defines a comparison function, reference value, and mask for all stencil buffer operations. The valid functions are in Table 15-7.
Table 15-7 Stenciling Functions
Function
Description
GL_NEVER
The stencil test always fails (no drawing occurs).
GL_LESS
Passes if the reference value is less than the stencil value.
GL_LEQUAL
Passes if the reference value is less than or equal to the stencil value.
GL_GREATER
Passes if the reference value is greater than the stencil value.
GL_GEQUAL
Passes if the reference value is greater than or equal to the stencil value.
GL_EQUAL
Passes if the reference value is equal to the stencil value.
GL_NOTEQUAL
Passes if the reference value is not equal to the stencil value.
GL_ALWAYS
The default; stencil test always passes (drawing always occurs).
Coupled with the stencil function is the stencil operation, defined with glStencilOp. Valid operations are in Table 15-8.
Table 15-8 Stenciling Operations
Operation
Description
GL_KEEP
Keep the current stencil buffer contents.
GL_ZERO
Set the stencil buffer value to 0.
GL_REPLACE
Set the stencil buffer value to the function reference value.
GL_INCR
Increment the current stencil buffer value.
GL_DECR
Decrement the current stencil buffer value.
GL_INVERT
Bitwise invert the current stencil buffer value.
Normally a mask image is used to outline the area in which drawing is to take place. Here is an example of drawing a mask image into the stencil buffer:
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
Then you would issue drawing commands that store a value of 1 in the stencil buffer. To draw using the stencil buffer mask, do the following prior to drawing the scene:
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Because this operates with all OpenGL drawing functions including glBitmap, you can use the stencil buffer to create many special “hole" effects for animations! Listing 15-3 contains a version of DEPTHCUT.C called STENCILCT.C that uses the stencil buffer instead of the depth buffer to cut away the middle of the cube.
Following is the heart of this program, which uses the functions described above:
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glPushMatrix();
glTranslatef(-1.0, 0.0, -20.0);
auxSolidSphere(1.0);
glPopMatrix();
Once the stencil image is drawn, we draw the cube wherever the sphere was not drawn:
glStencilFunc(GL_NOTEQUAL, 1, 1); /* Draw where sphere isnłt */
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
...
glPushMatrix();
glTranslatef(1.0, 0.0, -20.0);
glRotatef(15.0, 0.0, 1.0, 0.0);
glRotatef(15.0, 0.0, 0.0, 1.0);
auxSolidCube(2.0);
glPopMatrix();
Listing 15-3
STENCILCT.C, a stencil buffer example
/*
* "stencilct.c" - A test program demonstrating the use of glStencilFunc()
* and glStencilOp() to cut away the middle of a cube.
*/
#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 */
/*
* '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)
{
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_STENCIL_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glShadeModel(GL_SMOOTH);
/*
* Clear the color, depth, and stencil buffers...
*/
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
/*
* Draw the sphere that will be cutting away parts of the cube...
*/
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glPushMatrix();
glTranslatef(-1.0, 0.0, -20.0);
auxSolidSphere(1.0);
glPopMatrix();
/*
* Clear the color and depth buffers once again...
*/
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*
* Draw the cube...
*
* 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.
*/
glStencilFunc(GL_NOTEQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
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);
glPushMatrix();
glTranslatef(1.0, 0.0, -20.0);
glRotatef(15.0, 0.0, 1.0, 0.0);
glRotatef(15.0, 0.0, 0.0, 1.0);
auxSolidCube(2.0);
glPopMatrix();
auxSwapBuffers();
}
/*
* '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_STENCIL);
auxInitWindow("Stenciling");
auxReshapeFunc(reshape_scene);
auxMainLoop(draw_scene);
}
/*
* End of "stencilct.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
Podobne podstrony:
489 493489 Polska reklamaq51 874 4485 489411 489489 Jaką metodę amortyzacji środków trwałych wybraćWBI FR 493 87Beschreibung 20061219 3493 49405 (489)więcej podobnych podstron