issues with shadow projection with stencil

It has been a while that I wonder how to make shadow projections using the stencil buffer that cannot be seen if they shouldn’t. I decided to start this thread in order to find out any solution.

A more explanation: shadows are projected well, but if there is any occluding meshes between the vision and the shadowed object, the shadow is still visible. This simply comes from the fact that I disable depth test during the shadow rendering.
I’ve also tried to let the depth test during this process: shadows effectively disappear if they do not have to be seen. However, they are not well: sometimes they are well drawn, sometimes not at all, and for the other times they are partially drawn, depending on how you’re looking at them. And when on motion, the result is simply very bad and cannot be used for any ‘good’ program.

I actually do not use any portals, occlusion queries or whatever else to manage the view. And I’d like not to use them for shadowing. But I wonder how far it is possible.

Finally, is there other means to do shadows, like shadow mapping or shadow volume; can they avoid this problem ? (I’ve simply never tried out them).

regards

noone for that one ? Ok. maybe this is a dumb question then.

Hi,

I think it’s a little unclear exactly what you’re doing. Are you doing proper stencil shadows as described in:

http://developer.nvidia.com/object/robust_shadow_volumes.html

or something else?

/A.B.

No, I simply project my meshes onto a plane. This is what is called shadow projection. And I draw the shadow onto this plane. I use the stencil buffer for all that to work.

The situation I stippled is normal just because I disable the depth test during my shadow rendering. This seems an obligation if we don’t want to corrupt the shadow drawing (so it can look nice).

Here is simply how I do it:

Say P is the plane that will receive the shadow.
Say M is the model that will cast the shadow on P.
Say L is the light source.

I first calculate the matrix N for the shadow projection using P equation and L position.
I then draw P with some stencil stuffs.
Then I transform into N by matrix multiplication.
I disable depth test so that the shadow are correctly drawn (because I draw it onto the plane so the depth test returns the same value for both the plane and the shadow).
Then I can render M into the stencil.
I enable depth test.
Finally, out of stencil I can draw M.

There are other things I do like disable light and such, but I simplify here with what’s necessary only.

I first wanted not to use any occlusion test to avoid my problem. But I now wonder if it’s possible.

Shadow volumes seems more complicated, I didn’t have seen them yet. So robust shadow volumes are simply out of context for me.

Ok, now I see what you’re doing. I suggest the following:

  • Clear the stencil buffer to zero
  • Render the scene as usual.
  • Call glEnable(GL_STENCIL_TEST).
  • Call glDepthFunc(GL_EQUAL).
  • Call glStencilFunc(GL_ALWAYS, 0x1, 0x1).
  • Call glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE).
  • Draw your ground plane.
  • Call glStencilFunc(GL_EQUAL, 0x1, 0x1).
  • Call glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP).
  • Call glDepthFunc(GL_ALWAYS).
  • Render the shadows
  • Call glDisable(GL_STENCIL_TEST).

I think this should work, haven’t had time to try it though.

Another simple solution that can sometimes work is to draw the shadows with depth testing enabled but using a small bias to lift them from the ground plane.

/A.B.

Thanks for your suggestion. I’ll have a look at it as soon as possible.

I’m not sure your other solution could make good results. bias will provoke bad drawings depending on where it is drawn. Maybe simply translate it with a very little height over the ground can give more homogeneous results.

Stricly respecting what you said renders bad. With modification, I didn’t reached to have something well neither.

Originally posted by jide:
Stricly respecting what you said renders bad. With modification, I didn’t reached to have something well neither.
OK, sorry about that. If i clarify my intention with each line, perhaps you can find what’s wrong with the algorithm?

  • Clear the stencil buffer to zero
  • Should require no explanation
  • Render the scene as usual.
  • Puts the correct depth value at each pixel
  • Call glEnable(GL_STENCIL_TEST).
  • We now want to use the stencil buffer to mask out where to draw the shadows.
  • Call glDepthFunc(GL_EQUAL).
  • In the following code we only want to update the pixels with the same depth value as our ground plane.
  • Call glStencilFunc(GL_ALWAYS, 0x1, 0x1).
  • Use our stencil op at every pixel.
  • Call glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE).
  • When we encounter a pixel with the same depth value as the ground plane set it to 0x1, otherwise keep the value in the stencil buffer.
  • Draw your ground plane.
  • This will create a mask of 0x1 for all visible pixels of the ground plane.
  • Call glStencilFunc(GL_EQUAL, 0x1, 0x1).
  • The stencil test should only pass when the pixel is equal to 0x1.
  • Call glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP).
  • Don’t modify the values in the stencil buffer
  • Call glDepthFunc(GL_ALWAYS).
  • Disable z testing (I now there’s other ways to do this)
  • Render the shadows
  • The shadows should be rendered into the masked region.
  • Call glDisable(GL_STENCIL_TEST).
  • Disable stencil testing

Did this help?

/A.B.

How can I thank you ? The first time I simply bad implemented what you said.

Even if I don’t have the same looks for my shadow, compared to before (if a region has several shadows projected on it, it’s darker than other regions)and this provokes very ‘unsoft’ shadows, I think I can do them look better.

You’re great ! :slight_smile: