I'm trying to achieve the following effect in OpenGL as depicted in the given link http://commons.wikimedia.org/wiki/File:OpenGL_Tutorial_Stencil.png, code snippet is also below, this is the official openGL wikipedia tutorial.
Although it has code and comment out explanations I still find it hard to understand the logic of stencil buffer operation in openGL. I kindly remind that before starting to stenciling I read most of the instructions in the red book, so I know and I'm familiar with, how glStencilFunc, glStencilOp and glStencilMask etc.. works, but there are still some obscure and unclarified things in my mind related to the stenciling.
Here is my walkthrough on how I interpret the code :
With
glStencilFunc(GL_NEVER, 1, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
I believe that stencil test will always pass and failing the stencil test will result in 1s filled in stencil buffer due to the instructions set inglStencilOp
If the previous code blocks (#1) sets the all pixels in stencil buffer what we achieve with
glStencilMask(0xFF);
procedure call. Do we guarantee that all the 1s are written into stencil buffer successfully or what actually?We draw the circle then switch on the masks but this time
glStencilMask(0x00)
, here is one of the confusion, I think this deals with preventing stencil buffer values to be overriden by new values but code comments says that this simply fills the stencil buffer with 0s.Finally, if you we don't change any value (due to
glStencilMask(0x00)
) in stencil buffer what is the sense of having the// fill 0s glStencilFunc(GL_EQUAL, 0, 0xFF); /* (nothing to draw) */ // fill 1s glStencilFunc(GL_EQUAL, 1, 0xFF);
Main program body :
void onDisplay() {
glClearColor(0.1, 0.1, 0.1, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glStencilFunc(GL_NEVER, 1, 0xFF);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); // draw 1s on test fail (always)
// draw stencil pattern
glStencilMask(0xFF);
glClear(GL_STENCIL_BUFFER_BIT); // needs mask=0xFF
draw_circle();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glStencilMask(0x00);
// fill 0s
glStencilFunc(GL_EQUAL, 0, 0xFF);
/* (nothing to draw) */
// fill 1s
glStencilFunc(GL_EQUAL, 1, 0xFF);
draw_scene();
glDisable(GL_STENCIL_TEST);
glutSwapBuffers();
}