Skip to main content
gamedev.net
🔒 Locked

Per-Object Shadowmaps

Started by SimmerD Apr 19, 2004 at 1:41 AM 0 replies 2.6k views
Original Post
SimmerD
SimmerD
Has anyone played with per-object shadow maps? I did several years ago in a small demo, but didn''t really take it very far- at the time I was still playing w/ object ids. Let me explain how I''m planning to use them - I''d love to hear other experiences. I''d like self-shadowing for some objects, but depth shadow mapping my entire scene for the sunlight was way slow and aliased. Yes I know about PSMs, etc that can help, but just the speed of rendering to a 1k x 1k shadow map was killing my fps. So, what I''ve done is to break shadowing into two parts : static and dynamic. Static shadows are like lightmaps, except they only store an occlusion amount in [0..1]. These are done at a 6 texels per meter density, and then undergo a 3x3 blur at create time, followed by bilinear filtering at runtime - so they look smooth, if not soft in the correct way. By each world surface having an occlusion factor with each light, I avoid many potential shadowmap issues, including leaks and depth precision problems. I''ve also found through playing with shadow map approaches for several years on world geometry, that few approaches work really well on world geometry. Depth approaches alias when drawing front faces, and have light leaks when drawing back faces. Object ID''s fix this to some degree, but are more expensive to compute, and a pain to allocate, and must be filtered at runtime to avoid wall/floor shadowing problems. If you''re willing to not have your lights move at runtime, you can pre-bake per-light occlusion info in occlusion maps, or in vertices. With Dynamic shadows, the problems to solve are world->entity shadows, entity->world shadows, and entity->entity shadows. The since all 3 cases involve entities, you can do your shadows per-entity. For the 2nd two cases, find your entity''s bounding sphere, create a frustum from bounding sphere out to the shadow fade distance, along the light direction. What I''m doing now is to render the entity in black to a white texture, and modulate with the world or entity shadow receiver''s occlusion term already in dest alpha. Then use this combined static * dynamic shadow term to choose where the lighting goes. The downsides to this are that : a) your entities can''t self shadow - not a huge deal for most objects. b) Sometimes when your shadow casting entity is very close to a wall or object in front of the entity, the black & white entity shadow map gets mapped onto the geometry that should be lit, causing artifacts. To solve both of these problems, you can use 8-bit depth shadow maps. The key idea is to keep things fast & avoid needing > 8 bits of depth, which slows things down and hurts compatibilty with older hw. So, you still create a per-entity frustum, but instead of rendering the entity in black, you render the entity and any other entity or geometry intersecting the mini-frustum into the shadow map with an 8-bit depth value mapped over the shadow casting entity''s bounding diameter. This should actually be mapped from [0x1-0xfe] instead of [0x0-0xff]. When drawing the objects in the mini-frustum, test their depth vs the 8-bit depth in the shadow map and see if they are in shadow or not. You can use alpha test if the object should be lit, otherwise, write zero to dest alpha. This way any object that could potentially screw up the shadowing due to being too near the caster, gets mapped into the caster''s depth range, and is shadow testing properly. If you have too many object interactions, you might want to merge many nearby objects into a single mini-frustum and into the same shadow map. World->entity problems can be solved by creating a frustum from the entity back towards the light, mapping depth the same way. Come to think of it, all of these cases are the same. Any casting entity has a frustum that goes from the light through the entity''s bounding sphere, and then out to the shadow fade distance. Any world geometry or entity in that area can be rendered to the shadow map using the 8-bit depth. Objects way in front of the entity all get mapped to value [0x00] and all behind the entity get [0xff].
billy_zelsnack
billy_zelsnack
Below I wrote up my current thinking for static lightmapped scenes + shadowed+ing dynamic geometry on crap hardware. It uses stencils, but I am really liking what you are suggesting for shadowed+ing dynamic objects and might look into it instead.

--------

Lightmaps generated from radiosity can make for really nice and really cheap rendering. The problem is that to get nice shadows you need to have pretty hires lightmaps. Not a problem for small scenes, but for large scenes it becomes an issue.

So how about breaking the radiosity generation (shooter style) into two pieces. Direct and indirect. We''ll process each light seperate and accumulate them into the framebuffer later.

Take a light and cut the shadows out of the geometry by brute force (keep both unshadowed and shadowed pieces) and then optimize. Generate shadow volumes while you are at it too and optimize them.

Subdivide the geometry into patches and elements.

Shoot the energy from the light into the scene.

Only the unshadowed pieces should have any energy. Make a copy of those energies.

Continue iterating the radiosity as usual.

Once you''re done, subtract out the energy copy you made earlier. Your radiosity should contain only the indirect contribution.

Now take the geometry and optimize it based on vertex energies. (Remember it is subdivided into elements at this point) Since indirect energy is pretty low frequency, this should optimize very well.

To render:

for each light
{
Render static geometry shadow volumes into stencil
Render dynamic geometry shadow volumes into stencil
Render accumulate dynamic geometry vertex lit (testing stencil)
Render accumulate unshadowed pieces vertex lit (testing stencil)
Render accumulate indirect lighting geometry (testing stencil)
}
Multiply in textures (or be fancier and do it while you are rendering each light)

You could also just merge all the lights at precompute time and render them all at once.
very unhelpful and/or unfriendly

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.