Shadowmaps or Stencil Volumes

Which of these shadow techniques is best for games? I know they use both, but which is less cpu expensive and easier to implement on not so “new” video cards.

IMO, buffers are most likely the best way to go - but I think older cards are less likely to be able to use this technique - which would force you to use stencil. (There’s also projective (?) shadows which may be preferable over stencil shadows).

Stencil shadows require a large amount of fill rate, by comparison to buffers. I’ve got to admit though, I haven’t implemented buffers and I haven’t been able to get around one issue I can see (I haven’t given it much thought either).

How do you use buffers to light/shadow an entire scene? Presumably you need a shadow/depth texture for various segments of your scene (which would be made using a grid of connecting frustums from the lights point of view)? Or do you just use one really wide angle frustum (which would give you poor quality)?

There is a paper on Perspective Shadow Mapping which solves lots (but not all) of the “how to cover an entire scene” problem.

If you’re on non-depth-texture hardware, but still have per-fragment tests, then you can use an ID shadow buffer, where each element (or even each triangle) has its own color, and you “pass” a fragment only if the ID you calculate when rendering is the same as in the map.

I believe shadow maps is going to be the preferred way in the future – movie rendering has used it for ages, and if stencil was either more efficient or better looking, then they would have used that, wouldn’t they? :slight_smile:

Originally posted by jwatte:
There is a paper on Perspective Shadow Mapping which solves lots (but not all) of the “how to cover an entire scene” problem.

Could you give us this paper’s reference ?
Thanks !

Here: http://www-sop.inria.fr/reves/publications/data/2002/SD02/PerspectiveShadowMaps.pdf

There’s one big problem with them, though. When the light is behind or in front of the camera, the map will degenerate to a normal shadow map. If the light (usually sun) is above the viewer, this typically doesn’t matter because you’d only see a small part of ground or sky anyways, but don’t start dreaming about making sunsets with PSMs.

I’ve made a small demo of using shadowmaps in a small enviroment, you can download it from http://www.hut.fi/~ikuusela/demos/EngDemo.zip

The demo is made to work with relatively old computers (GF2 is just fine), it can be optimized a lot for newer hardware. Needs 32bit colors.

-Ilkka

I’ve made a small demo of using shadowmaps in a small enviroment,

Doesn’t work on my P4-3Ghz + Radeon 9700. No crash nothing, the window just stays empty (as if it was not rendering anything). The title says 180 fps.

Y.

Originally posted by Ysaneya:
The title says 180 fps.

Maybe your eyes aren’t fast enough.

Ok, I think I fixed it. Try it again. At least you should get a better fps

-Ilkka

I have to add, though, that as nice and fast the shadowmaps are, they’re not a very safe choice. It’s often said that using shadow maps you can add shadows to your scene very easily, but reaching the quality and generality required for a quake-like game engine takes quite a lot efford.

And whatever you do, you don’t really get past the fact that some detail don’t get correctly lit due to aliasing. In most cases it can be worked out one way or another, but compared to pixel-perfect stencil shadows it’s quite a lot of trouble. And omnidirectional lights are a real pain…

All this being said, I’ll definetely go on with my shadowmap engine developement. With the dirty parts out of the way, it does look quite good.

-Ilkka

Cool demo. It worked great for me on my P3 600MHz w/ GeForce4 Ti 4400. I only got around 22fps. But that is expected due to my slow CPU. I’m just curious, what technique do you use to make the shadows soft? Do you just render the shadow multiple times while jittering the light or something else? It looks pretty good.

-SirKnight

[This message has been edited by SirKnight (edited 08-16-2003).]

JustHanging,
after a dialog that says “Faces: 1196, Vertice [sic]:2431, Textures: 4” your (updated) demo produces a solid grey window and a lot of access violations for me.

“Access violation at address 69315383: read of address FFFFFFFF.”

One of these thingies pops up every time I task switch to the demo (message pump?).

Radeon 9500Pro, Cat 3.6, Athlon XP (yup, got SSE), and all the other good things.

[This message has been edited by zeckensack (edited 08-16-2003).]

Shadow buffers have the advantage of working with alpha masks, so things like tree foliage works, using stencil on that would be a nightmare.

Shadow buffers, would use more fillrate over stencil if a point light was inside an object tho.

Works fine for me, 60 fps on a P2 333Mhz GF3.

Some graphical glitches but pretty good.

Oh yeah I forgot to say, the window was at 1024x768. When I made it smaller, the fps jumped up quite a bit to just at or around 100fps.

-SirKnight

There are a number of tradeoffs between shadow maps (aka shadow buffers) vs shadow volumes.

Shadow volumes:
Pros:

  • robust (using the techniques discussed in a paper by Cass Everitt and Mark Kilgard)
  • per-fragment accurate hard shadows
  • handles omnidirectional light sources

Cons:

  • robust version requires watertight polygonal meshes (e.g. closed triangle mesh with consistent orientation)
  • for dynamic models, finding silhouettes must be done on host processor (which can be costly for large models)
  • not scaleable for complex scenes due to large fillrate requirements: shadow polygons tend to overlap (which leads to large stencil overdraw) and occupy large screen area. Fillrate requirements can be reduced using the EXT_depth_bounds extension.

Shadow maps:
Pros:

  • Simple algorithm -> can be implemented entirely in hardware
  • Works with any model that can be rendered into a z-buffer, not just polygonal ones (perhaps not a critical requirement now, but may be useful in the future)
  • Fast: shadowing calculations are performed in image space (using depth comparisons), so performance is largely independent of scene complexity

Cons:

  • Because shadow maps work in image space, this means we can get sampling artifacts such as aliasing (this is what Perspective Shadow Maps partially addresses).
  • Another annoying sampling artifact is the “scale/bias” needed to make sure that surfaces do not incorrectly shadow themselves.
  • By default, only handles directional lights (e.g. a spotlight).

Unfortunately, because of these tradeoffs, there is no easy answer to which of the shadow methods is the best. I do believe that as games incorporate more and more complex models / scenes in the future, shadow volumes will break down performance-wise (the scaleability issue) and that newer techniques based on shadow maps will become preferred.

Eric

A few things are missing from that (mostly quite comprehensive) list:

  • for dynamic models, finding silhouettes must be done on host processor (which can be costly for large models)

Finding silhuette edges can be done in hardware. What you do is you render the mesh with a special shader that determines whether the vertex’s normal would be pointing towards or away from the light. If it points towards, do T&L as normal. If it points away, you transform the position of the vertex far away from the light. This creates the shadow volume.

  • not scaleable for complex scenes due to large fillrate requirements: shadow polygons tend to overlap (which leads to large stencil overdraw) and occupy large screen area. Fillrate requirements can be reduced using the EXT_depth_bounds extension.

There’s more to it than this.

Shadow volumes require 2n + 1 passes, where n is the number of lights. First, you make a pass for drawing the volumes into the stencil buffer. Then, you make a pass for using that buffer to apply light. Lastly (or first), you make an ambient pass.

Shadow maps only require n + 1 passes, assuming that your fragment processor has enough instructions to do all the per-fragment processing that you need. You need one pass per light for the shadow maps, and then you need 1 pass for the rendering of the scene itself.

  • By default, only handles directional lights (e.g. a spotlight).

Using cubemaps, you can handle point lights. The problem there is that a point light requires 6 passes.

Originally posted by SirKnight:
I’m just curious, what technique do you use to make the shadows soft?

The good old: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008781.html

I also tried rendering the penumbras by filtering the depthmap, which wouldn’t require finding silhouettes, but went back to the old method because the shadow antialiasing you get with the old method makes quite a difference.

The omnidirectional lights are handled via dual paraboloid shadow maps. Not sure if that’s the best way, but it’s not bad either.

zeckensack: Strange. Looks like you’re missing one of the extensions I use (no, I don’t check…) The reason you get the error message when task switch could be that redraw causes the error.

Adrian: What kinds of graphical glitches? Can you post a shot?

-Ilkka

What about dual paraboloid shadow mapping, which covers point lights? With this technique you can use point lights as well for shadow mapping.

Originally posted by Banzai:
What about dual paraboloid shadow mapping, which covers point lights? With this technique you can use point lights as well for shadow mapping.

From what I’ve seen that doesn’t work well unless you have well tesselated geometry.

Originally posted by NitroGL:
From what I’ve seen that doesn’t work well unless you have well tesselated geometry.

Yes, but the fact is that you need the well tesselated geometry only during the shadow map generation phase. After that you can draw the scene with lower tesselation. And as the shadow map generation produces a depth map only (no need for textures or lighting), the rendering should be very fast.