   Z Pass to Z Fail - Capping shadow volumes
  I have been working with the Z Pass shadow volume method demonstrated at codesampler.com for some time. It has been a good solution for me up until a few days ago when I tried to move my camera through a shadow volume (Evil music plays) which resulted in inverse shadows or as Kwoon says, “All hell breaks loose.”Frantic research on Google and intense study of Hun Yen Kwoon’s Theory of Stencil Shadow Volumes has led me to understand that this is a near plane clipping problem often solved by implementing the Z Fail algorithm (Carmack’s Reverse).  This method involves capping the shadow volume.The questions I am going to ask are about a specific application. Screen shots and the source can be downloaded at:  http://www.neke.net/neke_forumfiles.html In this source code we are building a shadow volume that extends to point determined by this line of code.// CShadowVolume.cppfor( i = 0; i < dwNumEdges; ++i ){  D3DXVECTOR3 v1 = pVertices[pEdges[2*i+0]].p;   D3DXVECTOR3 v2 = pVertices[pEdges[2*i+1]].p;   D3DXVECTOR3 v3 = v1 - vLight*5;  D3DXVECTOR3 v4 = v2 - vLight*5;…}The bit that extends each edge is v1 – vLight * 5; Where *5 determines the length of the volume.So v1 and v2 are the near vertices and v3 and v4 are the far vertices of the volume. Question 1:Do I need to add a cap to the end of this volume for Z Fail even if it is finite?The answer is probably yes but I had to start with an easy one.Question 2:What is the easiest solution to capping the volume with this method? A generic algorithm would help.Question 3:Does anyone know of an implementation of the Z-Fail with DX 8 – 9?I have more questions but I will wait for these to be answered first. 
  1. yes2. you simply add the front-facing polygons non-extruded, and the back facing polygons extruded (dot product with the light vector).  you can also just extrude the front facing polygons as well (instead of the back ones), as long as it caps the volume.3. once you have the capping working correctly, if you just follow carmacks notes (there on nvidia if you dont know of them) on the stenciled shadows, its a fairly easy conversion from z-pass to z-fail shadows.  if it 'kinda' works its most likely because you dont have capping 100% correct.theres a shadow volume article on this site that may be of some very good use to you as well.regards,-Eric [edited by - Vulcan on September 11, 2003 4:51:10 PM];  Thanks Eric,Before I start hacking away at this can you please just pretend I''m an idiot (I might be anyway) and expand on your reply to Question 2?_Neil ;  when you go through the polygons of your mesh, for each face you determine whether it is a back-facing or front facing polygon to the light source (take the dot product with the surface normal to the light vector).  if its a back face, extrude the vertices to the edge of your volume and add them to your volume, if its a front face, just add them to the volume without extruding.ill also direct you here as it is one of the better articles on the subject imo.regards,-Eric;  Thanks for the clarification Eric. I am giving up for the evening so I can start again tomorrow. I''ll post again when I get the capping working correctly. Best regards,_Neil;  Here is an important link to info of Z-Fail shadow volumes: Practical and Robust Shadow Volumes;  if( D3DXVec3Dot( &vNormal, &vLight ) <= 0.0f )   {  addEdge( pEdges, dwNumEdges, wFace1, wFace0 );  addEdge( pEdges, dwNumEdges, wFace2, wFace1 );  addEdge( pEdges, dwNumEdges, wFace0, wFace2 );//add the light  facing triangles to the Shadow volume to form the front capm_pVertices[m_dwNumVertices++]=v0;m_pVertices[m_dwNumVertices++]=v1;m_pVertices[m_dwNumVertices++]=v2;/*add the light front facing triangles to the Shadow volume to form the back cap after reversing their order and extending them in light direction */m_pVertices[m_dwNumVertices++] = v2-vLight*10; m_pVertices[m_dwNumVertices++] = v1-vLight*10; m_pVertices[m_dwNumVertices++] = v0-vLight*10;   }    }    for( i = 0; i < dwNumEdges; ++i )    {   D3DXVECTOR3 v1 = pVertices[pEdges[2*i+0]].p;   D3DXVECTOR3 v2 = pVertices[pEdges[2*i+1]].p;   D3DXVECTOR3 v3 = v1 - vLight*10;   D3DXVECTOR3 v4 = v2 - vLight*10;   // Add a quad (two triangles) to the vertex list   m_pVertices[m_dwNumVertices++] = v1;   m_pVertices[m_dwNumVertices++] = v2;   m_pVertices[m_dwNumVertices++] = v3;   m_pVertices[m_dwNumVertices++] = v2;   m_pVertices[m_dwNumVertices++] = v4;   m_pVertices[m_dwNumVertices++] = v3;    }This is the method for the generation of the front cap and back cap.the problem is in the z fight between the shadow volume polygons and the model polygons.This will make the whole model to be shadowed even light facing polygons.you have one of two solutions:1-to move the vertecies of the front cap slightly inwards in the direction of the normal of the vertices and this is the most robust and efficient solutilion I think.( found in nvidia papers)2-to use the back facing polygons as the front cap after reversing their normal.this will be a good solution if you are subtracting the diffuse lighting value for the pixels in shadow but if you are using a gray square on the screen it won''t give you the right result. this can  have the following code:if( D3DXVec3Dot( &vNormal, &vLight ) >= 0.0f )   {  addEdge( pEdges, dwNumEdges, wFace0, wFace1 );  addEdge( pEdges, dwNumEdges, wFace1, wFace2 );  addEdge( pEdges, dwNumEdges, wFace2, wFace0 );/*add the light  back facing triangles to the Shadow volume to form the front cap after reversig their order*/m_pVertices[m_dwNumVertices++] = v2; m_pVertices[m_dwNumVertices++] = v1; m_pVertices[m_dwNumVertices++] = v0;/* use light back facing triangles and extend them in the light direction to form the back cap */ m_pVertices[m_dwNumVertices++] = v0-vLight*10; m_pVertices[m_dwNumVertices++] = v1-vLight*10; m_pVertices[m_dwNumVertices++] = v2-vLight*10;   }    } ;  There are a couple speedups that can be easily understood and REALLY help out your frame rate, as Carmack''s Reverse isn''t [nearly] as fast as the Z-Pass method as you have roughly triple the number of polygons in Z-Fail as Z-Pass.  Therefore, you want to use Z-Pass whenever possible, or at least reduce the # of polygons when using Z-Fail.  The first trick, determining when to use Z-Pass or -Fail.1) When I render my shadow volumes, I always perform a simple test.  If a ray (a vector with an origin) can pass from the camera''s current position to the light without passing through the shadowing objects bounding box, then you''re DEFINATELY not ''in'' the shadow.  If it DOES pass through the bounding box, then you MIGHT be in the shadow (considering the case of a large bounding box when the object is small).  You can take the next part as far as you like.  You can intersect directly with the mesh to see if you DEFINATELY are in the shadow, or you can use a bounding box heirarchy to reduce the possible error of being in the shadow.  In any case, if you determine you''re DEFINATELY not in the shadow, use Z-Pass, otherwise, use Z-Fail.2) If you HAVE to use Z-Fail (for any reason, including that of being in the shadow), you need to try to reduce the number of polygons you need to draw (and adding the caps on the volume considerably ups the poly count, though this depends on your mesh, of course).  If you find yourself with a huge FPS drop when you enter the shadow (aka use Z-Fail), do what I do: build a plane going through the camera''s current position with the normal being LightPos - CameraPos.  Then, test the camera''s current view direction against this plane (to determine on which side of the plane the camera is currently viewing).  The logic behind this is that you can RARELY see both ends of the volume at the same time.  The only case I''ve come across is when the distance between the shadow-casting object and the shadow-receiving object (e.g. a wall) is very small (compared to the current Field of View) that you CAN in fact, see both ends.  To detect this, the only way I can think of would be to determine the angle between the plane normal and the view direction.  If it''s between, say 85 - 95 degrees, add both caps to the volume (you may want to adjust the 85 - 95 degree range depending on your Field of View, though I can''t think of a way to do this).  In the end, it comes down to:- Determine if in Shadow Volume- No?  Use Z-Pass- Yes?   - construct plane with normal parallel to light-camera difference   - test view direction against this plane.   - If facing light, add front-facing polygon cap to shadow volume. - If facing away from light, add extruded back-facing polygon cap to shadow volume. - If unsure of viewer direction (e.g. can PERHAPS see both ends), add both caps to volume (better safe then ugly)Hope these help you when you get the implementation going, my implementation really helped out my framerate.   Chris PergrossiMy Realm | "Good Morning, Dave" ;  Thanks to everyone for the help.As soon as I get the implementation up I will try out the algorithm suggested by c t o a n.But unitl then...I'm at the part now where I have the capping working correctly (thanks to mohamed ) and I am now dealing with the coplaner Z-fight between the occluder and the shadow volume cap. Hun Yen Kwoon says that we can make use of the D3DRS_ZBIAS flag when setting the render state to fix this problem. We set the value of the occluder to a higher number than the shadow volume.Well DirectX 9 doesn't have D3DRS_ZBIAS anymore. I think it's called D3DRS_DEPTHBIAS. This is what I tried.g_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, 1);m_Occluder.Render();g_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);renderShadowToStencilBuffer();renderShadowToScene();But it does not seem to work at all.?I should also mention that I am still using the Z-Pass algorithm with the capped volume._Neil    [edited by - shadowyogin on September 12, 2003 1:21:39 PM];  z-bias is a joke, its not supported on some cards, and doesnt have the same result on others.to fix it just push the near clip and far clip back ever so slightly, you''ll get the same result on all video cards.regards-Eric 