Some Stencil Shadow Problems

Hello everyone!

I’m trying to render a scene with 2 cubes and a light source. I’m using the stencil buffer to create shadow volumes… The light is above the 2 cubes and each cube creates a shadow. The problem is that when the 2 shadows fall on the same piece of surface, the scene looks like I have no shadow there:
http://geocities.com/gsmcreation/untitled.GIF

Could anyone tell me what I’m doing wrong in this code?

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	glClearStencil(0);
	glDisable(GL_LIGHT0);	
	drawScene();  
	
	glEnable(GL_STENCIL_TEST);
	glDepthMask(GL_FALSE);

	glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
	glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
	glCullFace(GL_BACK);  
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

// draw the shadow volumes pass 1
makeShadowVolume(objects[1], light_position0, 15.f,0);
makeShadowVolume(objects[0], light_position0, 15.f,0);

	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
	glCullFace(GL_FRONT);  
	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

// draw the shadow volumes pass 2:
makeShadowVolume(objects[1], light_position0, 15.f,0);
makeShadowVolume(objects[0], light_position0, 15.f,0);

	glDepthMask(GL_TRUE);
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

	glCullFace(GL_BACK);
	glDepthFunc(GL_LEQUAL);
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

	// HERE MAY BE THE PROBLEM:
	glStencilFunc( GL_GEQUAL, 0, 1);

	glEnable(GL_LIGHT0);
	drawScene();
					
	glDisable(GL_STENCIL_TEST);
	glDepthMask(GL_TRUE);
	glDepthFunc(GL_LESS);

Thank you.

Hello,

I think you mixed up the stencil funcs. The following works fine for me:

drawSceneAmbient();  // ambient and/or z-fill pass

// draw back facing geometry
glDepthMask( GL_FALSE );
glEnable( GL_CULL_FACE );
glCullFace( GL_FRONT );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable( GL_STENCIL_TEST );

if( Z_FAIL )
{
  glStencilFunc( GL_ALWAYS, 0, ~0 );
  glStencilOp( GL_KEEP, GL_INCR_WRAP, GL_KEEP );
}
else if( Z_PASS )
{
  glStencilFunc( GL_ALWAYS, 0, ~0 );
  glStencilOp( GL_KEEP, GL_KEEP, GL_DECR_WRAP );
}

// draw front facing geometry
glDepthMask( GL_FALSE );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glEnable( GL_STENCIL_TEST );

if( Z_FAIL )
{
  glStencilFunc( GL_ALWAYS, 0, ~0 );
  glStencilOp( GL_KEEP, GL_DECR_WRAP, GL_KEEP );
}
else if( Z_PASS )
{
  glStencilFunc( GL_ALWAYS, 0, ~0 );
  glStencilOp( GL_KEEP, GL_KEEP, GL_INCR_WRAP );
}

// lighting pass
glDepthMask( GL_FALSE );
glDepthFunc( GL_LEQUAL ); // GL_EQUAL is not working because of the polygon offset defined later on!
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glEnable( GL_STENCIL_TEST );
glEnable( GL_LIGHTING );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glEnable( GL_BLEND );
glBlendFunc( GL_ONE, GL_ONE );
glStencilFunc( GL_EQUAL, 0, ~0 );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glPolygonOffset( -1.0, -1.0 );
glEnable( GL_POLYGON_OFFSET_FILL );

The polygon offset is needed to avoid z-fighting of the capped shadow volume when using the z-fail algorithm (camera frustum intersecting light to object-frustum).

Hope this helps!

Cheers,

GuentherKrass

That could be the problem:

glClearStencil(0);
(...)
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
(...)
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

You start from 0 and decrease stencil in 1st pass.
Start from different value. You could also use stencil wrap. My favourite initial stencil value is 0x80, but for no reason :slight_smile:

Thanks everyone!
I solved it with _WRAP.