Sign in to follow this  

Stencil Shadow Volume Problems

This topic is 3594 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been looking at various shadowing techniques for a project I'm doing and am finding a lot of difficultly with the two main ones (Shadow Mapping and Stencil Shadow Volumes). Today, I am having problems with the implementation based on Mark Kilgard's "Robust Stencil Shadow Volumes" paper. The effect I'm getting is that the stencil seems to be moving/disappearing or doesn't exist where it should: For example: Planar Projected Shadow: http://img216.imageshack.us/img216/880/planarprojectionrf3.jpg ZFail Attempt: http://img216.imageshack.us/img216/7859/sv1ao6.jpg http://img240.imageshack.us/img240/1291/sv2wr3.jpg I've looked into my siloheutte generation and my extrusion function is pretty much standard ((Pos - lightPos) * extrusionDist) or (Pos - lightPos, 0 for w) if using Infinite Projection Matrix), so is there anything that can be causing it. I'm using the standard ZFail approach mentioned in the MJK paper, so I'll post the code if someone wants to spot a mistake in the implementation. I'm just wondering what could cause the moving stenciling and why the shadow might not be correct. Thanks neutrinohunter

Share this post


Link to post
Share on other sites
Quote:
Original post by vrihai
Using the ZFail method requires you to cap both ends of the extrusion. If you're already doing this, then there could be a problem in your cube mesh.


Well if you mean i'm extruding the possible siloheuttes to an extrusion point, then render the back faces and then the front faces with respect to light, I think I am *shrugs*. :)

void renderShadowVolume(JVector3D lightPos, float extrusionFactor) {

//if (dl == -1) {

//dl = glGenLists(1);
//glNewList(dl, GL_COMPILE);



glPushMatrix();
glPushAttrib(GL_CURRENT_BIT);
for(int siloheutteEdge = 0; siloheutteEdge < setList->getNumberOfEdges();
siloheutteEdge++) {
JEdge edge = setList->getEdge(siloheutteEdge);
JVector3D v = edge.getVertex(0);
JVector3D v1 = edge.getVertex(1);
JVector3D extrudePos = v - lightPos;
JVector3D extrudePos1 = v1 - lightPos;
//glColor4f(shadowColour.getRed(), shadowColour.getGreen(), shadowColour.getGreen(), 0.2);
glColor4f(1.0, 1.0,1.0,1.0);
glBegin(GL_QUADS);
renderVertexv(v1);
renderVertexv(v);
renderVertexv(v + (extrudePos * extrusionFactor));
renderVertexv(v1 + (extrudePos1 * extrusionFactor));
glEnd();
}


glBegin(GL_TRIANGLES);
for(int i = 0; i < triangles.size(); i++) {
JVector3D incidentLightDir = triangles[i]->getAveragePlanePosition() - lightPos;
JVector3D planeNormal = triangles[i]->getNormal();

float val = planeNormal.DotProduct(incidentLightDir);
JPositionList posList = *(triangles[i]->getPositionList());
if (val >= 0.00000001f) {
for(int j = 0; j < 3; j++)
renderVertex(posList[j].x - lightPos.x, posList[j].y - lightPos.y,
posList[j].z - lightPos.z, 0);
} else {
for(int j = 0; j < 3; j++)
renderVertex(posList[j].x - lightPos.x, posList[j].y - lightPos.y,
posList[j].z - lightPos.z, 0);
}
}
glEnd();



glPopAttrib();
glPopMatrix();
}



This is the function which renders the shadow volume, probably the most likely place for an error, can you see anything wrong?

Neutrinohunter

Share this post


Link to post
Share on other sites
Capping is a expansive and fragile process. Using the infinite shadow volume presented in the paper "Practical and Robust Shadow Volumes"
http://developer.nvidia.com/object/robust_shadow_volumes.html
is a far better option which requires no capping at all.

And, a demo program of the paper is available for download at
http://developer.nvidia.com/object/inf_shadow_volumes.html .

Please start with the demo program. It should make your development alot easier.

Share this post


Link to post
Share on other sites
Okay, so your saying Infinite Projection Matrix and w=0 coordinates would be a better idea?

Any ideas on what the problems with the stencil could be?

I modified some code so I could render the siloheuttes of the box (to make sure the winding was correct). I've implemented the Infinite Projection Matrix, homogeneous coordinates for extrusion and made GL_DEPTH_CLAMP_NV toggable.

www.jmecoding.com/Images/siloheuttebox.jpg

Maybe its me misunderstanding but the general algorithm is

ClearBuffers()
SetInfiniteProjectionMatrix();

drawSceneWithOnlyAmbience();

for each lightSource {
clearStencil();

SetStencil();

for each occluder {
createShadowVolume();

//INCR PASS
renderShadowVolumeForOccluder();
//DECR PASS
renderShadowVolumeForOccluder();

}

SetStencilEqual(0,~0)
//INCR PASS
renderScene();
}

I don't see anything wrong with what I've wrote and I doubt the paper I have in front of me is wrong, what could be the cause?

neutrinohunter

[Edited by - Neutrinohunter on February 11, 2008 6:40:02 PM]

Share this post


Link to post
Share on other sites
GL_DEPTH_CLAMP_NV and Infinite Projection Matrix both serve the same propose. You can either use GL_DEPTH_CLAMP_NV or Infinite Projection Matrix, but not both. In general, GL_DEPTH_CLAMP_NV will give you better result. However, it requires hardware support (probably a NVidia display card).

By the way, there is a demo program (with source code) available. It should be a lot easier for you to start with the demo program.

Share this post


Link to post
Share on other sites
Quote:
Original post by ma_hty
GL_DEPTH_CLAMP_NV and Infinite Projection Matrix both serve the same propose. You can either use GL_DEPTH_CLAMP_NV or Infinite Projection Matrix, but not both. In general, GL_DEPTH_CLAMP_NV will give you better result. However, it requires hardware support (probably a NVidia display card).

By the way, there is a demo program (with source code) available. It should be a lot easier for you to start with the demo program.


Sorry I wasn't clear with that, I had the option to interchange between the two.
I have been thinking ive looked at the example a thousand times, understood pretty much most of the code and didn't thing it would get me anywhere. But I was indeed mistaken, It seems I had a stencil counting problem, because if I clear to 128 and use that (which isn't specified in the paper) I get something. For some reason its light rather than darker (probably blending function or something) or something else, but its a start.

http://img228.imageshack.us/img228/5964/stencilshadowbutgetsligck6.jpg

Okay, I have it working now but I've had to change the algorithm quite a bit to get the code to work, even the code that they have for the demo doesn't match the algorithm description in the paper.

http://img147.imageshack.us/img147/8827/boxstencilshadowsxt3.jpg

Thank you very much for all your help, I have learnt quite a lot doing this extension to my project :)

Neutrinohunter

[Edited by - Neutrinohunter on February 12, 2008 1:00:29 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Neutrinohunter
...
Okay, I have it working now but I've had to change the algorithm quite a bit to get the code to work, even the code that they have for the demo doesn't match the algorithm description in the paper.
...


The differences you found (so as using 128 as stencil clear value) are intended for reduce the artifact of shadow volume.

The following figure shows the artifact of shadow volume.

Share this post


Link to post
Share on other sites
Quote:
Original post by ma_hty
Quote:
Original post by Neutrinohunter
...
Okay, I have it working now but I've had to change the algorithm quite a bit to get the code to work, even the code that they have for the demo doesn't match the algorithm description in the paper.
...


The differences you found (so as using 128 as stencil clear value) are intended for reduce the artifact of shadow volume.

The following figure shows the artifact of shadow volume.


Well its not just that though, in the paper they have something like that, yet the code they have, makes front facing polygons go into the colour buffer, something which is quite fundamental to the algorithm yet isn't mentioned.

glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 128, ~0);
glStencilMask(~0);

[b]//glColorMask(0,0,0,0);[/b]

JVector3D lightPos = scene->getLight(i)->getPosition();
for (int j = 0; j < numObjects; j++) {
getPolygon(j)->createShadowVolume(lightPos);

glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
renderShadowVolume(lightPos);

//glColorMask(0,0,0,0);

glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
renderShadowVolume(lightPos);
}

glColorMask(1,1,1,1);



As an example.

Neutrinohunter

Share this post


Link to post
Share on other sites

This topic is 3594 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this