still problems with z-Fail for stencil shadow volumes

Started by
14 comments, last by metalcrusader 17 years, 9 months ago
Hello! I still have problems changing from z-pass to z-fail. With z-pass, everything is ok but when I change to z-fail, I get a second "ghost-shadow" overlapping the scene. I've uploaded a screenshot for better understanding: ghost3bj.jpg or: [img=http://img216.imageshack.us/img216/2305/ghost3bj.jpg] or: http://img216.imageshack.us/my.php?image=ghost3bj.jpg I stricktly follow the instructions from the paper "Practical and Robust Stenciled Shadow Volumes for Hardware-Accelerated Rendering" from Everitt and Kilgard and also read l lot of other papers ( incl. "Theory of stencil shadows (Hun Yen Kwoon) and "The Mechanics of Robust Stencil Shadows" (Eric Lengyel)) , but I can not find out why I get that second shadow. By the way, I don't use an infinit projection matrix because I am using GL_DEPTH_CLAMP_NV so the shadow volume should not be cut by the far-plane. The important part of "my" code:

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawRoom();	
	
glEnable( GL_DEPTH_CLAMP_NV);
glDepthMask(0);
glEnable( GL_BLEND);
glBlendFunc( GL_ONE, GL_ONE);
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, zero);
	
glClear( GL_STENCIL_BUFFER_BIT);
	
// 2) 	first Stencil Test - increment
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(  GL_ALWAYS, 0, ~0);
glStencilMask(~0);	
glCullFace( GL_FRONT);
glStencilOp( GL_KEEP, GL_INCR_WRAP, GL_KEEP);
shadowObj->drawShadowVol();
	
// 3) second Stencil Test - decrement
glCullFace( GL_BACK);
glStencilOp(GL_KEEP, GL_DECR_WRAP, GL_KEEP);
shadowObj->drawShadowVol();

glEnable( GL_LIGHT0);
glLightfv( GL_LIGHT0, GL_POSITION, lightPosition);
glEnable( GL_COLOR_MATERIAL);
	
glStencilFunc(GL_EQUAL, 0, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glDepthFunc(GL_EQUAL);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	
glDisable( GL_DEPTH_CLAMP_NV);
	
// full light pass:	
drawRoom();	
	
glDepthFunc( GL_LESS);
glDisable( GL_BLEND);
glDisable( GL_STENCIL_TEST);
glDepthMask(1);


If anybody ever had the same problem, or knows how to get rid of it: please answer!!! Thanks! PS: My shadow volume is closed ( there is a frontcap and a backcap!) [Edited by - metalcrusader on June 26, 2006 7:18:08 AM]
Advertisement
i mostly think that your volume may intersect your near plane and not your far plane...
Thank you for answering!!!
- but I use z-Fail for which a near-plane intersection is no problem. In addition I can make the volume visible and I can see that the volume isn't cut by that plane. More ideas?
Quote:Original post by metalcrusader
Thank you for answering!!!
- but I use z-Fail for which a near-plane intersection is no problem. In addition I can make the volume visible and I can see that the volume isn't cut by that plane. More ideas?


i have implemented shadow volume , and effectively i was having this ghost shadow , it seems to be the intersection with your far plane , i insist on that , that's why you must compute a perspective projection matrix that simulate infinity...

if you try to think about , your ghost shadow is very large so it is projected from a very far distance , that's why i think about the intersection with your far plane....
I'm using GL_DEPTH_CLAMP for drawing the shadow volume, so the volume should not be clipped by the front&far planes. But at the moment, I try to limit the shadowvolume so that it could not be clipped by a far plane lying at for example 2000. I do that, because I don´t know how to create an infinit projection matrix. Can you post your code of doing that? I think that would be very helpful for me.

[Edited by - metalcrusader on June 26, 2006 12:49:27 PM]
Now I've tried both: first, limit the shadow volume and then I used an infinite projection matrix which I found at another tutorial. The code is
float vpratio = 1.0f;float fov    = 90;//CameraFOV[id];float nearp  = 0.1f;float aspect = 4.0f / 3.0f * vpratio;float pinf[4][4] = {	{ 0, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } };pinf[0][0] = (float) atan(fov) / aspect;pinf[1][1] = (float) atan(fov);pinf[3][2] = -2.0f * nearp;pinf[2][2] = -1.0f;pinf[2][3] = -1.0f;glLoadIdentity();glLoadMatrixf(&pinf[0][0]);

...but both approaches did't work. I always got this ugly ghost shadow...
take a look at nvidia paper i think they give this projection matrix
if you want to find it yourself , you simply calculate the limit of the matrix where f tend to be infinite...

Let's have a convention for naming member of a matrix : row,col (33 means third row and third column)

l = left plane
t = top plane
r = right plane
b = bottom plane
n = near plane
f = far plane

The normal projection matrix for a homogenous coordinate -1<w <1 is

2n/r-l 0 r+l/r-l 0

0 2n/t-b t+b/t-b 0

0 0 -f+n/f-n -2nf/f-n

0 0 -1 0

so only the 33 member of the matrix and the 34 member will change when you tend f to infinity... :

the 34 member become -2n , the 33 -1

hope this help.

I never build up the projection martix like this. I always used gluPerspective - which is much easier to use! Now I build up the matrix like you advised me to do - but I'm not sure how to choose the left, right, bottom and top values. I thought left must be -1, right 1, top 1 and bottom -1 so that the matrix looks like this:
{{0.1, 0, 0, 0 },{ 0, 0.1,0, 0},{ 0, 0, -1.0, -0.2},{0, 0, -1.0, 0}};
but now the view is very strange. What are the right values and how will the matrix then looks like?
the right values are :

e = focal length = tan(fov/2)
n = distance from center projection to near plane

right n/e
left -n/e

depending on your aspect ratio you can find your top and bottom value like this
t = aspectRatio*right;
b = -t;

try it and show some screens if you have resolved your ghost pbm

I don't think that your matrix is right, because I only get a white screen. I used it like this:
float aspectRatio = width / height;float near = 0.1;float fov = 45.0;float focalLength = tan( fov/2);float right = near / focalLength;float left = -near / focalLength;float top = aspectRatio * right;float bot = -top;   GLfloat Pinf[4][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}};   Pinf[0][0] = 2*near / (right-left);Pinf[0][2] = (right+left)/(right-left); // 0;Pinf[1][1] = 2*near / (top - bot);Pinf[1][2] = (top+bot)/(top-bot); // 0;Pinf[2][2] = -1;Pinf[2][3] = -2 * near;Pinf[3][3] = -1;

... but as I said: it doesn't work.
Then I look again at the nVidia-Paper and used that projection matrix. Now I could see my scene again - incl shadow - but unfortunately the ghost shadow is still visible...

Btw, I implemented a cpu-Version and a gpu version.
For the cpu version, I calculate the silhouette and extrude it. The front cap consists of the lightfacing triangles and the back cap of the non-lightfacing triangles extruded.
For the gpu version, i extend the model with quads and extrude all non-lightfacing surfaces.
But both version have this ghost shadow and it doesn't want to disappear also if I'm using that infinite projection matrix!!!
Because of that and the fact that it doesn't disappear if I'm using a limited volume together with a normal frustum I think that the projection matrix is not the guilty one. Could it be that we are searching at the wrong place?
[/source]

This topic is closed to new replies.

Advertisement