Scene flickering when turning off light

Hi folks,

I have an application where I can toggle lights to see how they interact with certain models.
When disabling the light the first time I see some kind of flickering in the scene.
All following toggle operations work smoothly.
I use the light.setEnabled function.

This is the PG example, the light automatically turns off after 1 second, at that time you can recognize the flickering.

Is there something I can do about it?

Best regards

1 Like

Because one frame box disappears when the lights are turned off (the same happens with dispose), and I found that StandardMaterial doesn’t have this issue.
Recompiling the material after turning off the lights also does not resolve the issue.

However, you can use:
hemiLight.intensity = 0
Steer clear of this issue.
scene.removeLight(hemiLight), setting hemiLight.setEnabled(false) or hemiLight.dispose() in the material compile callback does not cause flickering.


Thx a lot for that quick answer, I can definitely work with that :+1:

Would you agree that this can be considered as a bug?
I mean the workarounds are fine but using light.setEnabled should definitely be the go-to solution when it comes to toggling lights on and off.

I think this is a bug because StandardMaterial doesn’t behave consistently with PBRMaterial.

The problem comes from a shader recompilation. Because it is a light change, we can’t keep the old shader while the shading is compiling, leading to this flickering. There’s no real clean solution to this, but you can use the workarounds provided by @xiehangyun. You can also disable parallel shader compilation:

Note that there’s the same problem with the standard material. If you can’t see it, it’s probably because the recompilation is faster than with a PBR material.


@Evgeni_Popov thx a lot for that clarification. :+1:
I guess parallel shader compiling is used for improving performance, so deactivating it may be disadvantageous in that regards.
Can you give a little insights what this would mean in praxis?

Parallel shader compilation allows to compile shaders in the background. When enabled, it can avoid stuttering when a new shader must be compiled during the course of the program.

When that happens, the new shader is compiled in the background and the existing shader is used until the new one is available. When parallel shader compilation is not available, we must “wait” for the new shader to be compiled before using it, so the mesh is not displayed during that time (hence the stuttering).

Note that if all your shaders are compiled at start, parallel shader compilation will have no effect.

@Evgeni_Popov I tested that and I’d interpret the result as the exact opposite.
There are now 2 scenarios in the updated PG:

  • Switch material type after 1 second => new shader has to be compiled
  • Switch off light after 2 seconds

According to your explanation I’d expect that scenario 1 switches smoothly with parallel shading enabled, while scenario 2 works best with parallel shading disabled.
However both scenarios switch smoothly with parallel shading disabled, while stuttering both times with parallel shading enabled.

Replacing a material with another one won’t benefit from the mechanism I’ve descrived above. It’s only if you change one (or more) properties of the existing material that leads to a shader recompilation that it will kick in.

It seems to work when parallel shader compilation is disabled because you have a single object on screen which does not move: even if the synchronous compilation took 2s, you would not see a stuttering and you would simply see the update 2s after it should have happened.

Now, if you add a moving object, you should see the stuttering on the moving object:

However, the compilation is fast and the browser may cache the result to reuse it the next time (try to clear the cache of the browser between each test), so it may not be easy to see it. If you switch to WebGPU, you will clearly see it, as the compilation is slower in this case (note that parallel shader compilation is not implemented yet in WebGPU).