Performance issue with SpotLights.setEnabled and material.maxSimultaneousLights


I am experiencing a performance issue with SpotLights when calling the setEnabled function. I have an empty scene with a ground and 10 game units (characters). When a unit is selected, I activate a SpotLight with a projectionTexture. Each time one or more units are selected, I use the setEnabled method on the pre-created SpotLight object (with its texture loaded in advance). Conversely, I use setEnabled(false) to deselect.

The problem I’m observing is that the setEnabled method takes a significant amount of time, to the point where I sometimes receive the message:
[Violation] 'requestAnimationFrame' handler took 496ms

A workaround that confirms that the issue is related to the setEnabled method: if I replace setEnabled(false) with this.spotLight.intensity = 0 and vice versa with intensity 2, it works perfectly and instantly.

The problem seems to be related to this line of code: terrainMaterial.maxSimultaneousLights = 1000; With a value of 1000, I encounter the issue, but with 10, there is no lag.

PS: The default value of maxSimultaneousLights is 2, which seems surprisingly low. Is there a bug regarding this?

I attempted to reproduce the issue in a playground, and it’s even worse. As soon as I increase the value from 10 to 20, it generates compilation errors in the PG console.


PS 2: I disabled shadow and set includedOnlyMeshes to only one mesh (ground) for optimization but it changes nothing.

babylon version : 6.39.0 (+ gltf loaders + debug editor)


There is more : when using seEnabled, I got sometimes some scene flickering and I see FPS going from 60 to 50. If I use the workaround with intensity, no flickering, and the FPS is always at 60.

You can’t have too many lights affecting a mesh, there are GPU resources involved with each light (one uniform buffer per light), and these resources are quite limited. You should search for maxSimultaneousLights in the forum. For example

Note that you can set engine.disableUniformBuffers = true to avoid using ubo for lights, and you’ll be able to use more lights simultaneously. However, this will also disable ubo for materials, which may result in a slight drop in performance.

Your PG without ubo support:

Note that I’ve disabled projection texture, as you run up against another GPU limitation which is the total number of texture units a fragment shader can use. This is around 16 (depending on your GPU), so if you have too many spots, you’ll get an error like Error: FRAGMENT shader texture image units count exceeds MAX_TEXTURE_IMAGE_UNITS(16).

1 Like