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

## 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 on other sites
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.

##### Share on other sites
Quote:
 Original post by vrihaiUsing 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->getAveragePlanePosition() - lightPos;         JVector3D planeNormal = triangles->getNormal();          float val = planeNormal.DotProduct(incidentLightDir);         JPositionList posList = *(triangles->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 on other sites
Capping is a expansive and fragile process. Using the infinite shadow volume presented in the paper "Practical and Robust Shadow Volumes"
is a far better option which requires no capping at all.

And, a demo program of the paper is available for download at

##### 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 {

//INCR PASS
//DECR PASS

}

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 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 on other sites
Quote:
 Original post by ma_htyGL_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.

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.

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 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 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);            //glColorMask(0,0,0,0);            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

1. 1
2. 2
3. 3
frob
20
4. 4
Rutin
19
5. 5

• 32
• 13
• 10
• 9
• 18
• ### Forum Statistics

• Total Topics
632555
• Total Posts
3007063

×