WebGLRenderer
allocates one shadow map per light even for lights that are not supposed to cast shadowsThis 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 PointLight
s are sent here.
Depends on maximum texture units.
Check the _Max Texture Image Units_ here
Or new THREE.WebGLRenderer().capabilities.maxTextures;
@neeh I just ran into this issue myself. Relieved to at least find I'm not the only one... Have you been able to come up with a temporary solution or anything? I'm pretty desperate as this is totally stopping my progress right now.
The fiddle doesn't work for me at all fwiw (Uncaught TypeError: Cannot read property 'matrix' of null
at setupLights (threejs.org/build/three.js:22287)
)
@cl4ws0n I'm the guy from the stack overflow question, and I'm sorry, I've tried a lot but haven't found any solution. Eventually, I had to limit the number of lights.
Indeed, the fiddle seems broken.
@cl4ws0n I just updated the fiddle for r85.
Unfortunately, The fiddle won't help you because the issue is inside Three.js and I wasn't able to hack around it.
After this fiddle, I worked on another solution that deals with 1 layer of prelit textures, 1 layer of ShadowMaterial
and a fixed number of lights that are moved on the scene based on the actor's position. This can potentially lead to an infinite number of lights.
I don't remember why but this is broken. Firstly, I think there's a bug with ShadowMaterial
that can't handle more than 1 light.
However, I'm pretty sure we can make the first fiddle work by overriding the MeshPhongMaterial
and passing LightShadows
as uniforms.
Alright @arcs- @neeh I finally have a working solution so I thought I'd share even though there are some limitations which prevent me from making a pull request/Stack answer. Here's a diffy / raw diff, either of which you can apply to the source with git apply thatfile.diff
for right now. The issues left are the following:
WebGLRenderer
at the very least but I have left it until I can resolve whether its possible to make that determination.capabilities.maxTextures
is a safe option for the maximum number of shadows, so that is also hardcoded for now.Other than that and some room for optimizations, it's all good afaik. Let me know if you run into any issues if you end up using it.
I'd really like to hear any thoughts on how we could integrate a light baking and/or shadow fading system so the transitions can be more subtle/suitable for first person
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.
I agree with ghost! I'm working on a project where I need more than six lights. I could live with only a few of them casting shadows, but it's crashing even when I disable shadows for all but one light... THIS IS A BUG!
I'm hitting this same problem here as well.
Nothing helpful to add, I'm afraid, except another voice of frustration over this issue.
I came up with a solution for my application where I simply disable shadows if the number of lights gets too big. It's ugly, but it keeps my app stable and lets powerful enough machines render shadows:
var lightCount = x_div * z_div + 1,
textureCount = textures.length,
shadowsEnabled = (lightCount <= renderer.capabilities.maxVaryings - 3) &&
(lightCount + textureCount <= renderer.capabilities.maxTextures);
renderer.shadowMap.enabled = shadowsEnabled;
Most helpful comment
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.