PDA

View Full Version : How to prevent volume shadows from going through walls?



karx11erx
12-05-2006, 01:29 AM
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?

RigidBody
12-05-2006, 03:27 AM
i think you have to draw the wall first with depthbuffer enabled. if you do so, the shadow volume will not penetrate the wall.

karx11erx
12-05-2006, 03:53 AM
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.

http://www.descent2.de/temp/shadows.jpg

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.

jide
12-05-2006, 04:40 AM
you should render the whole scene twice, not only the shadows on the second pass.

karx11erx
12-05-2006, 04:49 AM
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.

Xmas
12-05-2006, 05:17 AM
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.

karx11erx
12-05-2006, 05:54 AM
Do I need to render shadows for the walls, too?

skynet
12-05-2006, 06:19 AM
Yes, having the walls cast correct shadows will make your problem go away.

Jan
12-05-2006, 06:31 AM
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.

karx11erx
12-05-2006, 06:54 AM
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. :p

Jackis
12-05-2006, 06:58 AM
karx11erx

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

karx11erx
12-05-2006, 07:35 AM
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?

Jan
12-05-2006, 09:38 AM
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.

karx11erx
12-06-2006, 05:34 AM
Are there other good and fast shadow rendering methods? If yes, how do they work?

Korval
12-06-2006, 09:00 AM
Are there other good and fast shadow rendering methods? If yes, how do they work?There's always shadow mapping. You can Google it.

karx11erx
12-07-2006, 03:21 AM
I know about shadow mapping. It will rather be slower than volume shadows for me. I am having 50+ light sources per scene.

Korval
12-07-2006, 08:28 AM
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).

karx11erx
12-07-2006, 08:47 AM
I currently am not rendering the scene for each light.

Korval
12-07-2006, 09:21 AM
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?

Jan
12-07-2006, 09:36 AM
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.

Korval
12-07-2006, 02:04 PM
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?No.

You need n passes for each light. Then, you have 1 pass for the geometry, using n separate depth textures.

Granted, for 50 lights, you'll need several passes. But you'll need far from 50 separate passes. Plus, because you're not destroying your depth buffer (which you have to do with shadow volumes) between each pass, you can take advantage of an automatic depth-first pass to use early z-culling of fragments.

Now, do some (perhaps many) people do shadow mapping that way? Yes. However, this is often for other reasons. Fragment shader length is one; this allows them to have effectively longer fragment shaders than you execute in one pass, as long as the shader code for each individual light can fit.

But that has nothing to do with the shadow mapping algorithm itself; the algorithm allows for the possibility of using n+1 passes.


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).Perhaps, but:

1: These are not full scene passes. Just passes over objects in that part of the scene.
2: You're not using up vast quantities of fillrate rendering large overlapping volumes like you are with shadow volume rendering.

Brolingstanz
12-07-2006, 07:54 PM
Granted, for 50 lights, you'll need several passes.Are you sure about that?

Komat
12-07-2006, 10:18 PM
Originally posted by Korval:
You need n passes for each light. Then, you have 1 pass for the geometry, using n separate depth textures.
With geometry shaders is should be possible to render several shadowmaps simultaneously altrough that is likely to be advantageous only for specific scene & light setups.



Plus, because you're not destroying your depth buffer (which you have to do with shadow volumes) between each pass
There is no destroying of depth buffer in shadow volumes, actualy they depend on the depth buffer containing correct values to work. Only the stencil must be cleared.

Komat
12-07-2006, 10:24 PM
Originally posted by Leghorn:

Granted, for 50 lights, you'll need several passes.Are you sure about that? I think his point was to tell that you might end with more passes not to tell exact value which depends on capabilities of the hw such as number of shader instructions, uniforms, samplers, size of textures and support for array textures.

Of course you can pack 64 256x256 shadowmaps into one 2048x2048 texture if you wish and if you fit into shader length and uniform size limit.

dReddi77
12-07-2006, 10:52 PM
There is still deffered shading, which requires one pass for scene rendering into the big buffer + n passes for n lights.

The disadvantage of this technique is one big render texture to hold all the data, but with next generation hardware that should not be a performance issue :)

Regards,
dReddi

karx11erx
12-08-2006, 03:46 AM
Please stop the thread hijacking!

If you have that much time, why don't you help me along with my questions in my thread about soft volumetric stencil shadows?

You guys all seem to know so much, but if asked for details, hardly ever tell a noob what he needs to know. :)

My trick is to compute the closest wall in the way of an object's shadow, increase that distance by some factor and cap the shadow volume there. That will not always give me perfect shadows, but for my application works sufficiently well.

Undertaker
12-11-2006, 03:02 AM
You can do an exact intersection of the shadow volume with the wall and clip the shadow volume to the wall plane, that way you will have the exact vizibile shadow frustum.
In fact, this is the way it should be done for static geometry with precalculated shadow volumes.

I don't understand though why you wouldn't want to make walls cast shadows too...

rgpc
12-12-2006, 06:15 PM
Originally Posted by karx11erx
You guys all seem to know so much, but if asked for details, hardly ever tell a noob what he needs to know.I think the noob needs to pull his head in and read the thread again. You've been given the solution - but you sound like you're too lazy to do it for yourself. In pretty much all your posts you've come back with a smart arsed response.


Originally posted by Jan
The moment you calculate shadows for some objects, you need to do so for all objects in you scene, including your static geometryGo off, change your engine to calculate shadow volumes for the static geometry (ie. Walls) and see what happens. Then you can come back and bitch that Jan didn't provide you with a solution.

Jan
12-12-2006, 11:47 PM
Thanks rgpc.

k_szczech
12-13-2006, 12:08 AM
1. Common mistake is that people do not read carefully about what shadows are before they implement it. Shadows do NOT darken the scene - shoadows only tell what pixels can receive lighting from particular light source.

2. If your wall does not cast shadow, then all objects on one side of wall can receive light from light source on other side of wall. That's wrong and that's why wall needs to cast shadow.

3. You can optimize your application using some precomputed visibility list that will tell you that some areas NEVER receive light from a light source. This can be done for lights that do not move and for lights that move in restricted area. If you do that, then you don't need to cast shadow from a wall since your light does not affect anything that's on the other side of the wall.
So, even if your shadow goes trough a wall, you don't see it on the other side, because "shoadows only tell what pixels can receive lighting from particular light source" and you allredy know that pixels on the other side do not receive light.

End of discussion...

nom
12-17-2006, 07:59 AM
@karx11erx

I am a little late to join this discussion... you could still use stencil shadows if you are not using z-fail (if your cam is above these rooms, like strategy game), and if your rooms have straight walls, you can cut shadow volume which you use to fill stencil buffer with clipping planes that you position in each wall. I think you can have up to 8 clipping planes in one time.

of course, this means that shadow will be "cut" even on "passages"... but maybe in level design you could solve this somehow.

nom
12-17-2006, 08:10 AM
p.s.

also, in level design, artist can create shadow volumes for all static object, for all static light sources. this way you would not need to calculate + clip them.

if artist uses 3dsmax, you can easily write plugin that will generate shadow volume depending on the lights artist created in the scene.

for dynamic lights or moving objects, if walls are thick, you can generate shadow volume objects that are shorter than wall thickness. this way their shadows will not go through them.

but honestly, the best would be to cast shadow volumes for all objects in the scene. you could use "modeled" shadow volumes (which can be optimized a lot, since manually modeled) and calculated ones.