PDA

View Full Version : Some Stencil Shadow Problems



Sorin G
04-10-2007, 11:43 AM
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.

GuentherKrass
04-11-2007, 12:17 AM
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

k_szczech
04-11-2007, 04:19 AM
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 :)

Sorin G
04-17-2007, 01:39 AM
Thanks everyone!
I solved it with _WRAP.