Light Shadows design issue?

WebGLRenderer allocates one shadow map per light even for lights that are not supposed to cast shadows

This issue is related to this question.

As you can see on shadowmap_pars_fragment.glsl, a new shadow map is allocated on GPU for every light, even for those having castShadow = false;

#ifdef USE_SHADOWMAP

    ...

    #if NUM_DIR_LIGHTS > 0

        // Reserving NUM_POINT_LIGHTS texture units
        uniform sampler2D directionalShadowMap[ NUM_POINT_LIGHTS ];
        varying vec4 vDirectionalShadowCoord[ NUM_POINT_LIGHTS ];

    #endif

    ...

#endif

This is a problem because the GPU has a rather limited capacity of concurrent texture slots. The following error can occur when there are too much lights with renderer.shadowMap.enabled = true :

gl.getProgramInfoLog Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (16).

On this fiddle, we’re only using 4 concurrent shadow maps by moving some LightShadow and setting light.castShadow = true to the 4 nearest lights.
But if you try to increase the number of lights (just change numLightRows), You may see the error.

Additionally, You may also see the error :

Varyings over maximum register limit

Which is bound to the number of shadows coordinates that are sent to the fragment shader.

I think we should go back to something like allocateShadows().
The shadow maps for PointLights are sent here.

Three.js version
  • Dev
  • r84
Browser
  • All of them
OS
  • All of them
Hardware Requirements (graphics card, VR Device, …)

Depends on maximum texture units.
Check the Max Texture Image Units here
Or new THREE.WebGLRenderer().capabilities.maxTextures;

Author: Fantashit

2 thoughts on “Light Shadows design issue?

  1. Can I just say, I think its really crazy that A.) this is an issue at all, that B.) there seems to be no interest at all in fixing it now, that C.) This is only labeled as a “suggestion” and finally D.) No one has pointed out how terrible my “solution” is or anything….Having tested it a bit I gotta say the performance penalty is huge. I’m just not qualified to make such a drastic change to the rendering code on my own at this point, though I will continue to work on it. It would be great if someone with some experience with this lib would chime in about my “solution” and offer some potential optimizations/design changes.

    Until then though, I defy you to point out another graphics library that will straight up crash if you give it more than 15 lights and a single shadow. If this hard limit to the number of lights than can be placed in a scene is the intended behavior, it should at least be documented and handled by the renderer without crashing it.

    TL;DR I insist this is a bug, and deserves more attention from experienced devs than it has gotten. Really anything at all would help me in the right direction at this point.

Comments are closed.