Name: GLQuake stencil shadows - the z-fail method Author: Rich Whitehouse E-mail: thefatal@telefragged.com Homepage: http://www.telefragged.com/thefatal/ ----------------------------------------------------------------------- This is a follow-up to my stencil shadows tutorial, in which I will explain how to use the "z-fail" stencil shadow method. Basically, this method reverses the face culling of the shadow volume, and increments/decrements the stencil buffer on each pass if the depth test fails, as opposed to passes. The main advantage of using this method is that we no longer get unfortunate depth issues when the view point gets within a shadow volume. The disadvantage is that it is slower and requires us to do more rendering because with this method we must put caps on our shadow volumes, because we aren't relying on depth testing. In this case, however, adding volume caps is going to be relatively trivial. First open up gl_rmain.c and go to the GL_ShadowPass function that you have already added from the last tutorial. Below this check: if (GL_TriFacingLight(tri, verts, lightPosition)) After the for loop and whatnot, we want to add this: //draw the front cap for the shadow volume glBegin(GL_TRIANGLES); for ( j = 0; j < 3; j++ ) { v1 = &verts[tri->vertindex[j]].v[0]; glVertex3f(v1[0], v1[1], v1[2]); } glEnd(); //Now the back cap. We draw it backwards to assure it is drawn //facing outward from the shadow volume. glBegin(GL_TRIANGLES); for (j = 0; j < 3; j++ ) { v1 = &verts[tri->vertindex[2-j]].v[0]; v3[0] = ( v1[0]-lightPosition[0] )*PROJECTION_DISTANCE; v3[1] = ( v1[1]-lightPosition[1] )*PROJECTION_DISTANCE; v3[2] = ( v1[2]-lightPosition[2] )*PROJECTION_DISTANCE; glVertex3f( v1[0]+v3[0], v1[1]+v3[1], v1[2]+v3[2] ); } glEnd(); As I said, it is rather trivial. This is all we had to do for our caps. Now go down to the GL_DrawAliasStencilShadow function right below the one you're in. We want to change the contents to this: { glCullFace(GL_FRONT); glStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); GL_ShadowPass( paliashdr, posenum, lightPosition ); glCullFace(GL_BACK); glStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); GL_ShadowPass( paliashdr, posenum, lightPosition ); } As I described above, this is reversing the face culling from the standard method and changing the increment/decerement to when the depth test fails, and simply keeping the value otherwise. Next go down to the function GL_StencilShadowing. After this chunk of code: while (g_numStencilEnts > 0) { //go through the list and do all the shadows g_numStencilEnts--; GL_StencilShadowModel(g_stencilEnts[g_numStencilEnts]); } We want to add: glCullFace(GL_FRONT); glDepthFunc(GL_LEQUAL); And above that same chunk of code (the while (g_numStencil.. etc. line) we want to add this: glDepthFunc(GL_LESS); Since GLQuake has the cvar gl_ztrick enabled by default, we want to disable that now as well, because it conflicts with our depth settings. Just open gl_vidnt.c (assuming you intend to make a Windows build) and find this line: cvar_t gl_ztrick = {"gl_ztrick","1"}; Change that "1" to "0" and you're done. Now start the game, set r_shadows to 2, and notice that when your view enters a shadow volume everything looks as it should. -Rich