Is it possible to include multiple shadow solutions in the same scene?

I’ve managed to get cascading shadows working. It was mainly for the buildings and environment to cast shadows which worked out great. However, my character had some flickering while moving around.

Turns out it was the shadow being cast by my character. Increasing the shadowMapSize property of the cascading shadow map(CSM) made it more apparant, although I had to raise the value all the way to 16384 to see any definition. I wanted to keep the shadowMapSize low at 1024 as pictured, so I did not setup the character’s material in the CSM.

But I still want the character cast it’s own shadow. Can ThreeJS’s default shadows can coexist with CSM? Or are there better methods and solutions for doing this? Or is there just something I am missing about CSM to do this properly?

Are you using r183.1? They made significant improvements to shadows.

Yes, you can use multiple shadow solutions. See this example.

In one of my programs, I used two Directional Lights - one to create shadows for the outside world and one to create high resolution shadows inside a an airplane cockpit. The lights were different distances from the viewer and the boundaries of the area were defined to avoid overlap.

That was somewhat of a special case since the lights were on the lower left, so I did not have to worry about defining shadows on the left. On the right, I could extend the high-resolution shadows to project on the wing and have the low resolution shadows start beyond that. I only used this solution while in the cockpit. In exterior view, I just used a single light source.

i think that csm is more than enough shadow for an open world scene, but if u ask me if i will use shadow, i prepare not to use shadow at all for better performance, i would used light or shadow maps baked into the gltf models, to avoid rendering shadows real time, this would result to better experience.

1 Like

I agree with your observations about the effect of shadows on performance. Where baking the shadows into the textures is not possible, I have created multiple transparent planes with shadows that float just above the texture. Where both the light source and objects are fixed, is there a way to make three.js only compute and save shadows once for use with all future frames?

That way, in the example posed by the OP, the shadows cast by buildings would be computed and saved once and the shadow cast by his animated character would be recomputed and moved with each frame..

Yes that makes sense. If the light and the static objects never move, three.js does not really have a built in “compute once and reuse forever” shadow cache for dynamic shadow maps. Shadow maps are rendered every frame as long as they are enabled. You can technically render them once and then disable shadow updates, but that only works cleanly if absolutely nothing affecting the shadow changes.

In practice the better approach is exactly what you are hinting at. Bake the entire static environment into textures. Buildings, poles, bridges, any vertical structures should have their shadows baked into the lightmap. That removes the need for real time shadow calculations for 90 percent of the scene and gives a huge performance win.

For moving elements like avatars and vehicles, floating shadow planes work really well. A simple circular blob shadow or a shape that roughly matches the vehicle footprint is more than enough for depth perception. Players just need grounding cues. They do not need physically accurate contact shadows in most gameplay situations.

Avoiding real time shadows for the environment and limiting dynamic shadows to only essential moving characters greatly improves performance and usually makes the overall gaming experience smoother, especially on lower end devices. It is one of those tradeoffs where players rarely notice the shortcut but always notice bad frame rates.

I do eventually intend to make a day night cycle, so baking shadows isn’t an option. Even so, performance is fine as of now, and I am intending to keep the shadowMapSize low.

Main concern is being able to render the character’s shadows alongside what CSM is doing.

1 Like

I was using r182. Don’t check releases nearly often enough to be immediately up to date, but changing over to it as soon as I can.

So multiple light sources count as multiple shadow “solutions”? Would it be possible to have the same light source for both types of shadows being cast?

That makes sense. A day night cycle definitely changes the equation, so I get why baking is off the table in your case.

From my experience though, a full dynamic day night system often doesn’t outweigh the performance cost, especially if smooth gameplay is the priority. Most players notice frame drops way more than they notice subtle shadow accuracy shifts over time. So keeping the shadowMapSize low is a smart call.

On the CSM side, I agree that the tricky part is getting the character shadows to play nicely with it. In setups like that, I’ve found it helps to be very selective about what actually casts shadows. Let CSM handle the large scale environment lighting, and keep the character shadow setup as lean as possible. That balance usually gives you the visual depth you want without pushing the GPU too hard.

Definitely try r183.1. They made a special effort to upgrade shadow performance.

As far as I know, each light can only have one set of shadow definitions. However, you can change some of those definitions during runtime.

Here is a side-by-side comparison of my cockpit shadows using one light source for all (left) and a second light source for the cockpit (right). This second light source is only needed for cockpit view.

As you can see, getting clear shadows is especially important in a WWII cockpit that has extensive framing. I think it would also help in your game by adding focus on your main character. And if there are other characters, it would be interesting to see their shadows sharpen as they get nearer to the main character - just as we tend to pay more attention to nearby people IRL. If your program also has a night cycle, you could use several streetlights to cast both nearby and distant shadows.

1 Like