Hi,
I’ve been working on a CAD program for lego bricks and I have a
problem with the stencil buffer on the TNT2. I don’t really know
what I’m doing, so it could be me, but it does work with MESA and
the Microsoft Generic drivers.
I’m trying to XOR a moving wireframe lego brick sprite on top of a
static rendered model. The problem is: when viewed head on, the front
and back edges cancel each other out and there isn’t much to look at.
I thought I solved this problem by setting a bit in the stencil buffer
the first time a bit is XORed, so future XORed lines can’t cancel it
out. This works in Mesa and Microsoft Generic OpenGL but maybe that’s
just dumb luck? On the TNT the I get a sloppy looking wireframe
sprite that leaves bits behind when I XOR it a 2nd time to move the
sprite. Are there some other fns that affect this?
You can see a picture here of the XORed sprite before I added the
stencil buffer test. The sprite used to disappear when viewed head
on.
http://www.brickshelf.com/cgi-bin/gallery.cgi?i=44638
Here’s the code if that helps any. I call this once to draw the sprite, and then again to erase it when the user indicates a move with the arrow keys.
/***************************************************************/
int XORcurPiece()
{
int retval = 0;
int drawmode = ldraw_commandline_opts.F;
int savewire = zWire;
int saveshade = zShading;
//ldraw_commandline_opts.F |= STUDLESS_MODE;
//ldraw_commandline_opts.F = (WIREFRAME_MODE | STUDLESS_MODE);
ldraw_commandline_opts.F = WIREFRAME_MODE;
zWire = 1;
zShading = 0;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
rendersetup();
#ifdef USE_OPENGL_STENCIL
if (use_stencil_for_XOR)
{
// Too many lines cancel out in wireframe mode when viewed head on.
// I could make sure I only XOR each pixel once by setting
// the stencil buffer at each write but only passing when it’s zero.
glStencilMask(GL_TRUE); // Enable stencil buffer writes.
glClearStencil(0x0); // Set stencil clear color
glClear(GL_STENCIL_BUFFER_BIT); // Perhaps just clear the bbox?
glEnable(GL_STENCIL_TEST); // Enable the stencil Test.
glStencilFunc(GL_EQUAL, 0x0, 0x1); // Stencil test(fn, refbits, bitmask)
glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // S-Buf write fns(sf, zf, zp)
}
#endif
glDisable(GL_LIGHTING); // No need for lighting
if (movingpiece == curpiece)
{
z_line_offset += 1.0;
glDepthMask(GL_FALSE); // keep depth test, just disable depth writes
}
else
glDisable( GL_DEPTH_TEST ); // don’t test for depth – just put in front
glEnable( GL_COLOR_LOGIC_OP );
glLogicOp(GL_XOR);
glColor3f(1.0, 1.0, 1.0); // white
glCurColorIndex = -2;
retval = Draw1Part(curpiece, 15);
glLogicOp(GL_COPY);
if (movingpiece == curpiece)
{
z_line_offset -= 1.0;
}
#ifdef USE_OPENGL_STENCIL
glDisable(GL_STENCIL_TEST);
glStencilMask(GL_FALSE);
#endif
glDepthMask(GL_TRUE); // keep depth test, just disable depth writes
glEnable( GL_DEPTH_TEST );
glDisable( GL_COLOR_LOGIC_OP );
glCurColorIndex = -1;
glFlush();
glPopMatrix();
zShading = saveshade;
zWire = savewire;
ldraw_commandline_opts.F = drawmode;
return retval;
}