Complex shadow volumes

I am getting strange results with this oildrum model. The shadow volumes appear correct, the edges appear correct, but the shadow doesn’t look right at all.

In shot 4, you can see that the top lip is causing a section of the shadow to be cut out, and also creating a “ribbon” that isn’t casting a shadow on any surface.

I calculated these shapes by projecting the sihlouette edges away from the light position. I did not add the front and back facing triangles to the shadow volume, and I don’t know if I am supposed to.

Any ideas?

[img]http://www.leadwerks.com/post/stencil.png[/img]

[img]http://www.leadwerks.com/post/stencil2.png[/img]

From the shot 3 I should say you should consider only the front facings. Just a guess from what I see. Btw, which shadow volume algorithm do you use ?

I copied Nehe’s tutorial #27 for the rendering.

I wrote my own edge-finding and shadow-volume routine.

When you say “front facings” do you mean surfaces that face the light, or face the camera?

Are you rendering your shadow volumes using the front faces or the back? (ie. front face the light, back face away from the light)

I am not presently rendering front or back faces. I am only rendering the sihllouette edges. I calculate the edges (relative to the light source) and project them away from the light source, creating a quad out of each edge.

The rendering routine I am using is from Nehe tutorial 27:

glclear GL_STENCIL_BUFFER_BIT
glDisable GL_LIGHTING'									Turn Off Lighting
glDepthMask GL_FALSE'									Turn Off Writing To The Depth-Buffer
glEnable GL_STENCIL_TEST'								Turn On Stencil Buffer Testing
glColorMask GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE'		Don't Draw Into The Colour Buffer
glStencilFunc GL_ALWAYS,1,$ff

'First Pass. Increase Stencil Value In The Shadow
glFrontFace GL_CCW
glStencilOp GL_KEEP,GL_KEEP,GL_INCR
lightlink.shadowvolume.draw()
										
'Second Pass. Decrease Stencil Value In The Shadow
glFrontFace(GL_CW)
glStencilOp(GL_KEEP,GL_KEEP,GL_DECR)
lightlink.shadowvolume.draw()

glColorMask GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE' 			Enable Rendering To Colour Buffer For All Components
glEnable GL_BLEND
glBlendFunc GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA

a#=lightlink.distancefade*lightlink.intensity*0.5

glColor4f 0.0,0.0,0.0,a
glStencilFunc GL_NOTEQUAL,0,$ff
'glStencilFunc GL_EQUAL,1,$ff
glStencilOp GL_KEEP,GL_KEEP,GL_KEEP
gldisable GL_CULL_FACE
glBegin GL_QUADS
tformpoint 100,100,100,camera,entity
glvertex3f tformedx(),tformedy(),tformedz()
tformpoint -100,100,100,camera,entity
glvertex3f tformedx(),tformedy(),tformedz()
tformpoint -100,-100,100,camera,entity
glvertex3f tformedx(),tformedy(),tformedz()
tformpoint 100,-100,100,camera,entity
glvertex3f tformedx(),tformedy(),tformedz()
glend
glenable GL_CULL_FACE
gldisable GL_BLEND

It looks like your stencil buffer is monocromatic.
Check where you define the PIXELFORMATDESCRIPTOR and see if the stencil bit’s is set to 1, it should be something like 8.

I have the stencil bits set to 8.

For the silhouette edge you should only consider front faces or back faces depending on the algorithm you use. Of course when calculating the silhouette, this is regarding the light not the camera.
Also, did you ensured your objects are all fully and well close ?

Use keep, incr, keep, then keep, decr, keep for the stencilop.

I’m pretty sure this will solve your problems until you have some errors elsewhere.

i think you should only calculate edges for light-facing polygons.
image #3 show edges from polygons that are facing away the light.

illustration from my own shadow volume implementation :

I don’t understand what you mean by light-facing and light-facing-away edges.

An edge is defined as the line between a triangle that faces the light, and a triangle that faces-away. So every edge will have one light-facing triangle and one light-facing-away triangle. The quad you form from each edge always faces perpindicular to the light, neither facing towards it, nor facing away from it.

For that matter, all of the edges in the above pictures could be considered “back-facing”. I am taking your comments to mean that I should not be drawing that little piece of the shadow formed from the lip at the top, but how do I arbitrarily dismiss it?

The edges on the concave rim around the top, if taken together, outline an area that faces away from the light. My shadow volume routine just recognizes individual edges. It doesn’t “know” how the edges form outlines. Do I have to perform additional calculations and figure out which way the areas outlined by a loop of edges face?

do you make sure that all projected quads have the same orientation?

and as jide already said, make sure that the model is closed. i had also such effects but they came from incorrect model geometry.

i’m not exactly sure what you mean by “add the front and backfacing triangle”. you only have to extrude the silhouette edges. but you must also add the front and back cap if you position the eye inside the shadow volume.

Thank you for taking the time to assist me here.

do you make sure that all projected quads have the same orientation?
All the projected quads face outward from the volume. They do not all face in the same direction. I found the normal of the projected quad, and did a dotproduct between that and an average of the two triangles the edge is between. That way I could tell whether the quad needed to be flipped or not, to make it face “out” from the volume.

I think the model is okay. Virtools was able to cast a correct shadow with it.

At this point, I am not using the front and back triangles, because I just want to get this working right before I worry about special cases.

I uploaded the barrel mesh here .

ok. so maybe the silhouette itself is not closed? in your second image it makes the appearance.

have you tried to visualize the volume? this may give you some additional info where something is going wrong.

It should be apparent from the red highlighted edges that there are two separate volumes. One is formed by the outline of most of the oildrum. The other is formed by the lip at the top.

Aw crap.

To decide which way the quads projected from the edges face, I calculated the normal of the quad (based on the first three vertex positions) and compared that to an average of the normal of the two triangles the quad’s edge lies between. If the dotproduct was more than zero, I flipped the quad face. So all my volume edges are pointing on the same direction that the edge’s triangles are pointing, and not in the opposite direction.

This works great for a convex outline. The outside of my shadow volume is perfect. However, it doesn’t work with the smaller volume made out of the inside of the lip at the top. Although the edges form a complete loop, the sides of the volume point inward, and the bottom points up.

Is this indeed the problem?

How do I possibly figure out which direction to make the quads point? The only way I know how to is to make a list of all vertices for the loop, order them, calculate the angle change between each vertex, and add the changes up…or something like that. It sounds horribly complicated.

HA!

The problem was which way the quads were facing.

To determine this, you take another vertex from one of the triangles, a vertex which does not form part of the edge. That point needs to lie behind the quad. Do a plane distance test with the plane equation you get from the first three vertices of the projected quad. If the distance is less than zero, reverse the order of the quad vertices.

Thanks to all that contributed.

Originally posted by halo:
It should be apparent from the red highlighted edges that there are two separate volumes. One is formed by the outline of most of the oildrum. The other is formed by the lip at the top.
ah, yes i see. my mistake.

glad it works now :slight_smile:

what i would be interested in, is what approach do you use for finding the silhouette edges?

There are plenty of tuts about this. A fast search on google gave me:

http://www.gamasutra.com/features/20021011/lengyel_03.htm
http://www.devmaster.net/articles/shadow_techniques/