Dynamically adding lights to the scene causes meshes to flicker when using parallel shader compilation

In my application, I’m dynamically adding point lights to the scene to draw the user’s attention to various meshes. I noticed that this can cause the scene to flicker when there are many lights being added.

Looking into the issue, I came across these forum posts: Adding / Destroying point lights (maybe it shall be in Bugs section ?), Scene flickering when turning off light - #5 by Evgeni_Popov. The root of the issue is that the shader is necessarily being recompiled when a new light is added to the scene. With parallel shader compilation, this can cause the scene to flicker when the shader compilation completes and the shaders get swapped.

I can partially work around this issue by adding the max number of lights to the scene on initialization, thus pre-compiling the shaders, but there are still certain points in my application when I need to create a new material with new lights, and I incur this brief flicker.

Is there a way to have the parallel shader compilation sync more accurately with the render loop? Alternatively, if I’m misunderstanding this issue and this cannot be avoided, is there an optimal way to dynamically add lights to the scene?

I’ve created a “worst-case scenario” playground here with a bunch of flickering: https://playground.babylonjs.com/#RC2IAH#174. It’s adding a bunch of lights to a somewhat complex scene on the render loop. I also tested with a PBRMaterial + Material Plugins, and this exacerbates the issue due to slightly longer compile times. I imagine this gets even worse if using WebGPU. I’m testing on an M2 mac on Chrome with the immersive web emulator installed.

Thanks for any help!

1 Like

I believe this thread may help - Dynamic enable of point light - #4 by Blake

1 Like

Thanks for linking this! I am currently pooling the point lights to work around this issue, though there are some great tips in there that I hadn’t considered. Resource pooling is always a great technique to use.

However, it currently seems like I have to initialize the max number of lights in my scene immediately to avoid flickering. This is unfortunate since my scene can have a large number of lights. Instead, I’d prefer to create an empty light cache on initialization with a set limit on the number of lights in the scene, similar to the solution linked. I would then dynamically allocate and use cached lights as needed until I reach the limit, at which point I would have to use some heuristic to determine where lighting is needed the most, and reuse lights accordingly. This scenario is where the parallel shader compilation syncing would come in handy, but I’m okay with allocating all of the lights on initialization if I need to.

1 Like