How to prevent volume shadows from going through walls?

Problem: In my application, volume shadows are going through walls.

What I want to do is render shadows for objects inside a geometry (building/mine) using multiple light sources. I don’t want the geometry to cast shadows.

Example: Two large halls, connected by a hallway, each with one or more light sources. Now the shadows of objects in hall one appear on the walls of hall 2.

What do I have to do do prevent object shadows from going through walls?

Is there a way to make the walls cast shadows only to setup the stencil buffer in a way to prevent object shadows from affecting the stencil buffer if there is already a wall shadow? How?

i think you have to draw the wall first with depthbuffer enabled. if you do so, the shadow volume will not penetrate the wall.

The walls are drawn first:

Pass 1: Render everything (bright)
Pass 2: Render object shadows (->stencil)
Pass 3: Render black quad (darkens all pixels with stencil != 0)

Alternative method:

Pass 1: Render everything (dark)
Pass 2: Render object shadows (->stencil)
Pass 3: Render everything again (brightens all pixels with stencil == 0)

For both paths shadows penetrate walls.

Here is a little image. Actually the shadow’s side walls consist of polygons extending to infinity. So the shadow faces for the object go through room 1 and are in front of that rooms rear wall.

There must be another way to prevent this. I would need to have that wall from room 2 cast a shadow too, but not render it, only use it to blot out the object’s shadow from the stencil buffer. Unfortunately, that doesn’t seem to work for multiple light sources and shadows.

you should render the whole scene twice, not only the shadows on the second pass.

jide,

you could as well have said nothing, because what you said doesn’t give me the faintest idea what I have to do. I need some detailled explanation, because I am obviously too dumb to figure it myself.

I wonder if you haven’t taken much time to really understand my entire setup and resulting problems.

I have changed the above picture: There is now a 2nd object, and the shadow for wall #1. If I render the entire mine, creating shadows for the walls too, that shadow will darken room #1 although it shouldn’t (because it has a light). It will also blot out the shadow of the 2nd object.

You need to do a stencil and light pass for each light source. Otherwise an area that is in shadow for one light source will always be completely dark, regardless of how many other light sources there are that should affect the surface.

You cannot simply combine shadow volumes from different light sources.

Do I need to render shadows for the walls, too?

Yes, having the walls cast correct shadows will make your problem go away.

You ran into the same problem many people have encountered before: The moment you calculate shadows for some objects, you need to do so for all objects in you scene, including your static geometry. Else the shadows will seem to go through walls.

Everything that your lightsource touches also needs to cast shadows. That’s how Doom 3 works, too. That’s why many games still have shadows that suck (ie. Valve’s Source-Engine), because it’s pretty difficult to get good shadows, when you don’t calculate them for all objects equally (ie. only for dynamic objects).

Sorry, can’t tell you HOW to solve the problem, you need to find a solution that fits into your engine.

Jan.

Jan,

in other words: I have a common problem, and you have no solution. Oh yeah, and the Source engine sucks (I wish mine would look like that!). lol:

Danke für’s Gespräch. :stuck_out_tongue:

karx11erx

Actually, Jan has proposed a solution for you: make every opaque object to be shadowcaster (walls also). This will solve all your problems.

Jackis,

yes and no. It’s by far not detailled enough. I have found some good help on another forum though.

It is not enough to just make every opaque object a shadow caster. You need two render passes per shadow casting light:

#1 Clear and setup stencil (shadows)
#2 Render scene, using just that light and additive blending

Before that, you have to render the unlit scene.

Just one question: Which blend mode do I need to set for additive blending?

For the blending: glBlendFunc (GL_ONE, GL_ONE);

I didn’t say that the Source-Engine sucks. I said their dynamic shadows suck. That’s a BIG difference. In most other aspects the Source-Engine is pretty cool, in my opinion.

It’s not so easy to give you a detailed description, since it depends on how you integrate dynamic lighting and shadowing into your engine.

Technically it’s the most straight forward thing to use dynamic lighting and shadowing for everything and don’t have any precalculated lighting, at all. That’s what Doom 3 does and that’s what’s most processing intensive.

If you can live with that, then what you mentioned above is the correct way to do it.

However, many people don’t want it that way for several reasons, ie. performance or quality of the lighting (only hard shadows, the general look will be dark).

Therefore either you take the “easy” path (which can still be very difficult with stencil-shadows, since they are tricky to always get right) or you have to try out what tricks might be possible with your engine to reduce the issue. For example if you use a sector-based engine it might be possible for you to restrict the shadow-volumes to the sector that the object resides in, thus the shadows will only appear inside the sector the object is in. But that’s only ONE trick, as i already said, this is an issue for which there is no real solution.

Jan.

Are there other good and fast shadow rendering methods? If yes, how do they work?

Are there other good and fast shadow rendering methods? If yes, how do they work?
There’s always shadow mapping. You can Google it.

I know about shadow mapping. It will rather be slower than volume shadows for me. I am having 50+ light sources per scene.

I am having 50+ light sources per scene.
I can’t imagine that rendering a scene 101 times (for shadow volumes) to ever be faster than rendering it 51 times (for shadow mapping).

I currently am not rendering the scene for each light.

I currently am not rendering the scene for each light.
Then how are you doing shadow volumes? The algorithm requires:

  • 1 pass for the ambient lighting.
  • n passes to render the volumes into the stencil buffer.
  • n passes to render the geometry, with the stencil buffer culling out the pixels in shadow of the light.

This is what the algorithm requires to work. So how are you getting around that?

I don’t get your calculation Korval. Don’t you need for shadow mapping

  • 1 pass for ambient
  • n passes for rendering the scene into the shadow-map
  • n passes to add light to the scene per lightsource

too?

Additionally, for shadow-mapping you might need more than one pass to create the shadow-maps, depending on the used technique (and some other factors).

Jan.