Deferred lighting and shadows

What is an efficient way to cast shadows when doing deferred lighting? Shadow map per light seems to be quite expensive - I am talking several dozen lights (up to 150) influencing the scene.

most lights shouldn’t cast shadows and can be either treated like a regular point light, a projected textured light or baked into a light texture.
Alternatively if you have several spotlights facing the same way you can put them all in the same texture.
But normally you should only have a small handful of shadow casting lights.

Cheating is an option you should consider in this case

You can prioritize the lights, so that only some of the lights cast shadows. This is especially important if your scene is changing every frame, requiring constant regeneration of the shadowmaps. Dim lights (relative to the other lights) can have their shadows dropped.

If you have a lot of static geometry and the light is static, you can render two shadowmaps, one for the static objects that doesn’t change, and one for the dynamic objects that changes per-frame. This is useful if the cost of generating the maps is a good percentage of your frame time, to offset the two potential lookups.

If you have lights that have significant luminantion dropoff, you can exclude pixels beyond a certain distance from the light, saving shadowmap lookups.

Yeah, I had thought of prioritizing lights, but that can become a pain, too.

Another problem I am having is this: If I include some light source that is partially occluded, the only way to prevent it casting light to scene areas it shouldn’t affect is to use a shadow map, am I right?

Is there no efficient way to do shadowing for lots of light sources?

If I include some light source that is partially occluded, the only way to prevent it casting light to scene areas it shouldn’t affect is to use a shadow map, am I right?

Define “partially occluded.” A spot light is effectively a light source that has occlusion built into it. You could implement a spot light as a point light with a shadow map that culls out all of the area outside of the spot itself. But it’s much easier to just do it mathematically.

So if you have a light source that you can statically and mathematically generate occlusion for, you should do that.

Not talking about spotlights. I had thought of something like this:

The red dot at the top is a point light. The blue angle to the left is the viewer position. The gray area is the shadow, the red area is lit by the point light. Green is what the viewer sees (frame buffer contents).

As far as I have understood it, if I wouldn’t use a shadow map for the light here, with deferred lighting it would light the gray area, too (as the viewer doesn’t see the wall in front of the light and hence it doesn’t get rendered - only the wall in the shadow does) - is that right?

My application is an old shooter game (Descent 2) where you can have several dozens bright, moving point light sources in a frame (gun shots, that is).

As far as I have understood it, if I wouldn’t use a shadow map for the light here, with deferred lighting it would light the gray area, too

If you don’t use a shadow map, or some other form of shadowing technique, it doesn’t matter if you’re using deferred rendering or forward rendering or whatever. You won’t get shadows unless you use a technique that produces shadows.

Shadow techniques and the overall rendering method (forward vs. deferred) are essentially orthogonal. The one doesn’t have anything to do with the other.

Deferred rendering is nothing more than an optimization for producing images. It’s still a rasterization-based renderer; it’s not like the difference between a rasterizer and a raytracer or something.

My application is an old shooter game (Descent 2) where you can have several dozens bright, moving point light sources in a frame (gun shots, that is).

Descent, like most games of its era, used static lights. The only non-static lights were lasers and such, which did not cast shadows.

I know what deferred lighting is and how it works. I know what Descent is and how it works, and I have changed it a lot during the last 7 years in my project (D2X-XL).

D2X-XL computes lightmaps for static lights and to some extent does occlusion culling by determining which faces of the visible area are out of sight of a light source.

All I was asking for was a shadowing technique as efficient as possible, since computing 50 shadow maps per frame doesn’t seem to be a realistic approach (and the light sources I am talking about are pretty bright and not the kind you could just not have cast shadows) - maybe there are tricks and methods I’ve simply never heard or read of.

Do you really have 50 lights visible at the same time, and needing cast shadows for each ?
Maybe the 4 nearest/brightest lights will be enough ?
Screenshot please ?

Dark level as reference:

Phoenix (very fast firing):

Lasers:

Singleplayer action {~ 20 moving light sources):

These picture are just meant to give you an impression. In a multiplayer session significantly more light sources may be present, and the same is true for certain singleplayer missions with a lot of hostiles around. D2X-XL is already doing some optimization by making groups of shots (e.g. two Phoenix blobs or four laser bolts) a single light source, but that’s not sufficient.

Pics 2 and 3 show that the shots indeed are very bright.

All I was asking for was a shadowing technique as efficient as possible, since computing 50 shadow maps per frame doesn’t seem to be a realistic approach

There is no realistic approach for shadowing from 50 dynamic light sources.

Each frame, randomly take 4 lights out of 50, being winners of have cast shadows. It will strobe like hell, but still be fast. Can be a weighted rand() taking in account brigthness and distance from view.
Does your level structure allow to easily render only the nearest geometry, to render faster shadow depth maps ? This could be done once per frame, then all lights will reuse it ?

…But casting shadows requires rendering the scene from the point of view of each light source - so the ‘nearest geometry’ for light #1 won’t be the same as for light #2, etc so there is no possible reuse.

one possible cheat could be to render a shadow from the nearest bullet/missile to the player/camera. So no matter how many bullets a player fires, render only 1 shadow to keep things moving fast(er).

Obviously in the screenshots you showed, you can reuse the geometry as lights are very near from each other. A basic AABB including all nearby lights+radius will do.

The images shown aren’t the only possible scenario.

As already explained, there is “no realistic approach for shadowing from 50 dynamic light sources”, short of using the best hardware you can.
So you will have to cheat, and of course each cheat will not be applicable to all situations. It will be a visual/performance compromise for each case.

I think people have summed this up pretty well: there’s no algorithmic approach (the way deferred rendering changes the factors that make multiple light sources expensive). Instead there are just a lot of ways to cheat.

If you have an efficient culling system, lots of small meshes, and batching/vertex throughput is the bottleneck, you might see some win by reducing the distance that various lights cast shadows.

I think everything else are various forms of caching, precomputing, and in other ways taking advantage of not having to solve the whole problem perfectly.