Shadow map with multiple lights.

Started by
6 comments, last by cr88192 10 years, 11 months ago

This is a quick question i wanted to ask and see how other are handling this. In my engine on every update i scan for all the visible objects in the Octree and store them in array. Then i iterate over each object and for each object i check how many lights affects it. For each lights that affects the object i put it in his own depth map. Once i am done, i interate over all the lights and perform shadown mapping for each light. For some reason this does not sound too optimal to me, so i was wondering how other people are doing it. Is there a better way of doing this.

Thanks.

Advertisement

this doesn't actually sound too far off from how I am handling it, except that I only create/update the shadow-maps for light-sources within a certain radius (for smaller-scale lights, and use delays for updating each light). if a light gets too far away, its shadow-maps are destroyed.

currently, I am using a bigger 1024x1024 cube-map for the sun, but most smaller lights are currently using 256x256 cube-maps (was using 128x128, but made it bigger to increase shadow precision).

this is actually being combined with the use of stencil-shadowing for smaller objects (like characters and random 3D models), mostly because the shadow-maps aren't really all that precise and update slowly, making them a lot better for things like general scenery/terrain and not so much for something like a moving NPC.

currently, shadow-maps are also not used for object-attached dynamic lights, which instead use stencil shadows exclusively (theoretically though, for something like a lantern or projectile, a person could just have a much more rapidly updating shadow map though if-needed).

performance? not necessarily great, but it is workable I guess. there are tradeoffs here.

I think I saw something at one point IIRC using a camera-space depth-map and (somehow) making this work with shadow-mapping, but I am not really sure how exactly...

(I don't really remember the specifics, bit I think it was based on ray-marching similar to parallax-occlusion mapping or similar, but I could be wrong here...).

but, yeah, it is a mystery if anyone has better ideas?...

Just for information, in my game engine I got multiple BVHs (one for static objects, one for dynamic objects and one for skinned objects) for objects in my scene. Scene lights are stored in another "BVH" (each light has bounding volume in leaf that describes area lit by the light).

First of all, I test which light's bounding volumes are seen from the camera. This gives me a list of lights, for which I need to have shadow map. For each light in the list I decide its "importance", e.g. whether it's really needed to have the shadow map and at what resolution. The "importance" is based (for point lights) upon their distance from camera, their lighting radius (currently I use surface area of their bounding volume) and their intensity (low intensity lights doesn't need high resolution shadows), for sunlight the importance is (if we're in exterior) maximal - e.g. it has always defined resolution.

Next thing I have to check is whether dynamic BVHs has changed inside the light bounding volme or whether light position has moved. If none of these happened, I check whether I already have shadow map at wanted resolution for this light -> in that case I don't need to update it. Otherwise I render shadow map for that light.

Updating shadow map is again tricky, I again traverse static and dynamic BVHs for leaves intersecting the light's volume. Those leaves are models that need to be rendered.

E.g. summarized, I only update shadow map when I have to, and update it only using models that are affected by light.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

Just for information, in my game engine I got multiple BVHs (one for static objects, one for dynamic objects and one for skinned objects) for objects in my scene. Scene lights are stored in another "BVH" (each light has bounding volume in leaf that describes area lit by the light).

First of all, I test which light's bounding volumes are seen from the camera. This gives me a list of lights, for which I need to have shadow map. For each light in the list I decide its "importance", e.g. whether it's really needed to have the shadow map and at what resolution. The "importance" is based (for point lights) upon their distance from camera, their lighting radius (currently I use surface area of their bounding volume) and their intensity (low intensity lights doesn't need high resolution shadows), for sunlight the importance is (if we're in exterior) maximal - e.g. it has always defined resolution.

Next thing I have to check is whether dynamic BVHs has changed inside the light bounding volme or whether light position has moved. If none of these happened, I check whether I already have shadow map at wanted resolution for this light -> in that case I don't need to update it. Otherwise I render shadow map for that light.

Updating shadow map is again tricky, I again traverse static and dynamic BVHs for leaves intersecting the light's volume. Those leaves are models that need to be rendered.

E.g. summarized, I only update shadow map when I have to, and update it only using models that are affected by light.

I am using an bounding volume around my lights as well, but that won't work if you have directional lights. So how are you handling that type of light.

I am using an bounding volume around my lights as well, but that won't work if you have directional lights. So how are you handling that type of light.

There are actually several solutions on handling this. In my case, the only directional light is the sunlight (respectively moonlight in the night), they're handled separately. As I stated in case of exterior scene the sunlight has maximal importance (e.g. it will always be rendered).

Now you need to somehow work with shadow maps for sun. In my case, I use cascaded shadow maps. For more information on them, see http://msdn.microsoft.com/en-us/library/windows/desktop/ee416307%28v=vs.85%29.aspx (or just google for "cascaded shadow maps" - there is like a TON of resources) ... and as "rendering importance" is maximal for sunlight, the "cascades" gets re-rendered, if either camera-position changes, light-position changes or dynamic object in the exact cascade has moved.

And as cascaded shadow maps cover the whole view frustum, they're perfect for simulating shadows for directional lights (note that they might not cover 100% of your frustum in order to optimize, you can cover F.e. only like 50% of your view frustum, and make your shadows disappear in the distance ~ with same number of cascades you will get better resolution of shadows near the camera). Cascaded shadow maps can (and should) be stabilized to achieve non-shimmering shadows.

NOTE: Of course if you have lots of directional lights, there is no way to do cascaded shadow mapping for all the lights at good frame rate (performance reasons of course).

NOTE 2: That spotlights can also use cone as bounding volume. Somehow limited directional light (affecting just known area of plane that is perpendicular to light direction) can also have bounding volumes (like "infinite" cylinder - it's actually finite, because you can limit near and far planes to just cover the scene).

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

in my case, lights also have bounding volumes.

in the case of the sun, it is basically a very large point-light which floats some distance over the player's head (placed upwards some distance, roughly 256 meters or so IIRC).

I still use cube-maps for it, but made the slight tweak that it normally only redraws the bottom of the cube-map (if the 'sun' flag is set).

the large light value for the sun effectively basically just gives the sun a very large bounding box and causes it to nearly always place at the top of the light-priority list, so it is normally always visible.

granted, this is kind of a lame way to handle the sun (vs either spotlights and directional lights), but alas...

for a spotlight, probably either a cone or frustum would be used for culling.

probably a simple solution would be defining a frustum in terms of 6 or so planes, then basically just check things against these planes (and check this frustum against the view frustum to detect whether or not it should be visible).

sort of like:

http://en.wikipedia.org/wiki/Viewing_frustum

just with a light instead of a camera.

in this case, a directional light could probably be treated as a sub-case of a spotlight (it looks like a directional light, but is handled by the engine more like a spotlight).

#cr88192

But computing Sun-shadows as point light shadows yields incorrect result (unless that point light isn't at distance of 149.6 * 10^9 meters ~ assuming you want to do same Sun-shadows as they're on Earth) ~ actually it should be treated as spherical (not point) light shadow of sphere at distance of 149.6 * 10^9 meters and radius of 6.9 * 10^8 meters.

The problem is, that the distance to sun is larger (by magnitudes) than dimensions of world - thus we can simulate Sun-light and Sun-shadows using directional light and ortho- projected shadow map (note that for correct softening and specular reflections we have to take Sun's radius into account).

All of this is assuming we want to correctly simulate sun light behaviour (or closely approximate it). Of course there are reasons where you don't want to approximate it (Non-photorealistic rendering, stylisation, etc. etc.) ... or that you can fine-tune everything so it looks very good in the end. smile.png

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

the main reason to use a point light in my case is mostly due to not really having the code in place to properly handle directional lights.

however, if the sun always stays reasonably directly overhead, then the shadow issue isn't really all that bad (as the player moves, so do the shadows, so near the player, the shadows tend to point in about the right direction).

this mostly works, but does leave a minor issue that as the player moves around, so do the exact locations of the various shadows, which does look kind of fake.

granted, if the sun were a stationary point-light (rather than one which follows the camera), then it would be a bit worse of a problem...

This topic is closed to new replies.

Advertisement