Question about shadows and their influence on draw calls and polygon counts

Is it expected to potentially have increased draw calls and poly counts when shadows are enabled with the shadow autoUpdate property set to true?

I am experiencing this. My assumption is that frustum culling is altered in a way to allow out of view meshes be able to correctly cast shadows that should be on screen.

I go from a comfy 100 or so draw calls with about 400K polygons to almost 300 draw calls with almost 900K polygons in a day night cycle where the shadows are not updated at night and are in the day.

Just curious if this is normal behavior.

After some testing, I found that this is not a reasonable explanation. I manually set the shadows autoUpdate to false when the directionalLight was at a point where the most shadows would be cast per it’s shadow.map parameters and the drawcalls still halved in quantity.

What’s going on here? I plan on building a fiddle unless there is a known explanation of this behavior.

Edit* Maybe that is a good explanation if indeed frustum culling is disabled for any object that casts shadows while autoUpdate is true. That would explain it, but would also suck.

And there it is…

if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {

Bummer. Well, I guess that makes my decision of whether or not to merge a bunch of geometry together a lot easier as I really do not need to consider frustum culling for certain objects.

So, object culling is disabled when using shadow maps? :scream:

It seems so only when the shadow’s autoUpdate value is true and the object is set to cast shadows. Although that line of code I posted doesn’t make the autoUpdate part clear (not sure where in code that comes into play), I can certainly see the performance difference in app.

But autoUpdate is mandatory when you have moving objects, which is almost always.

Somehow I thought that each shadow map rendering made its own list and culling.

Somehow I thought that each shadow map rendering made its own list and culling.

Evidence in my case at least would suggest otherwise. Hoping a three.js pro will have some insight.

1 Like

I see the line you posted in WebGLShadowMap.js.
But in WebGLRenderer.js it is like this:

if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {

So my previous statement is false. No, the shadow maps don’t disable the normal object culling. And there is light camera culling.

In the line of code you posted, object.castShadow is used to not render the object if it doesn’t cast shadows. I think the increment in draw calls and polys (roughly the double) is just the objects being rendered in the shadow map (and correctly culled), which is expected as you asked in the first place.

Ahh I see. Got it. Was surprised to see such a difference. Thanks for explaining.

1 Like

Yeah, shadow maps are costly :confused: You’re welcome.

1 Like

And now I understand why, and also kinda how shadow maps work in general. Thanks! You are a three.js pro!

Thanks! :grin: BTW glad to teach something useful.
Yeah the objects are all rendered with a simple and fast shader (single color, or even no color rendering) in the shadow map. Only the Z buffer is useful.

1 Like