Light and framerate

When I started importing models to my software I always took caution on two factors in order to keep framerate working fast:
1- DrawCalls
2- Number of triangles.

Today i got to a new problem and i have no idea on how to solve: Light.

I got a model that was working fine with good framerate but it looked too artificial. I asked my designer to add some lights and shadows to make it look more realistic. She added 72 spotlights all around the model. In the end it got realist and works fine on her machine. But when i try to open it on three.js editor it got all slugish.
Then i tried to remove all 72 spotlights and it all seemed good on speed again.

So the question is…how many spotlights can i have in a scene and have good performance?

Ouch. Lights have a cost. WebGLRenderer has a limit. WebGPURenderer may help speed it up, but not sure if Three has it yet.

Also it depends. Are you enabling shadows? That’s more cost.

See here for ideas:

You’re best bet for lowest effort is redoing the asset with much less than 72 lights.

You can also “bake the lights” into the texture if the lights will not change dynamically in realtime.

1 Like

I’d start to have second thoughts going above 4-5 dynamic lights. Beyond that it’s probably time to consider: baking lights into textures, baking AO, or using an environment map. Depends what you’re doing which techniques are a good fit, though.


Even the most random environment map encodes waaaay more complex light detail than any number of lights you can add to your scene.
With a good environment map and 1 to 3 lights, you can light most scenes pretty well imo. add some AO/post and you’re pretty solid.
Changing the number of lights can also trigger shader recompiles, so the use of actual software lights should be considered and used sparingly, since each light increases the cost of all shaders doing lighting.

1 Like

First I would like to thank all of the answers. You all gave me a lot to think about. So I need to keep the number of real lights in scene from 1 to 3 for performance issues.

Really liked the idea of baking light to texture and it will sure solve a lot of issue about shadows and lighting.

About enviroment light, Is there a tutorial on how to choose or make a good enviroment light? I know its a light that comes from an image. I tried make a 360 panorama picture of the place with lights and adding as an enviroment light…but i am not sure if its the best way to do it.

As for the question of the 3 lights total. Is light frustum culled? I mean if i have a place with 78 lights…does Threejs remove the lights i am not looking or do I have to create and remove the lights as i move around manually by code?

As for the question of the 3 lights total. Is light frustum culled? I mean if i have a place with 78 lights…does Threejs remove the lights i am not looking or do I have to create and remove the lights as i move around manually by code?

Lights are not culled, and also – adding/removing lights requires recompiling material shaders. So even that tends to be expensive.

If you’re looking for a “realistic” scene, then getting environment maps from somewhere like HDRI Haven can be a good option. If you’re going for something more hand-designed, have a look at THREE.RoomEnvironment and its example usage. The general idea is to create a scene with bright emissive meshes as “lights”, render that whole scene into a cubemap, and then use that cubemap as your baked environment map. This can be done quite cheaply when your app loads, no need to download an external texture. Example of the result here.

1 Like

Been thinking on the answers for a while and i have 2 questions.

The fists is about th elights not being culled. Suppose i want to make a big open world (just to extrapolate the problem). This big world would have to work only 3 dinamic lights? How you do it? You move this lights with the user to have different functions depending on where the user is? I mean the light that works to make shadows for a lantern in a city is it the same that makes lights on another city?

About the RoomEnviroment. I have created this in my system and works well but I noticed when the RoomEnviroment is created there is some lights and some boxes. The lights i take it are emitors of light. My first guess for the boxes were that they were occluders of the emitted light. But then i created a RoomEnviroment where i placed a box between the light and the object being illuminated and noticed this box has no effect on the illumination. So what is the boxes for in the RoomEnviroment? Why werent it created only with the position of each light?

The environment map gives not just diffuse illumination, but also specular reflections. Consider a metallic sphere – you’d want to see something reflected in that sphere, not just the lights! Here’s a screenshot taken with RoomEnvironment and a metallic sphere:

With only lights and no boxes or surrounding room, the reflections would be pretty boring.

Suppose i want to make a big open world (just to extrapolate the problem). This big world would have to work only 3 dinamic lights?

Hopefully someone doing more gamedev-related projects can comment here… But in my opinion, the dynamic light objects in three.js are not a great fit for this type of application. Perhaps it would be better if each object were influenced by the N nearest lights, rather than all lights currently in the scene. But unless you’ve explicitly overridden the .distance property of a light, its range is technically infinite, however dim it might appear from 2000km away. And more importantly, three.js doesn’t implement selectivity to assign different lights to affect different objects.

Other approaches to consider would be:

  1. baking all lighting to unlit materials
  2. bake lightmaps or ao maps
  3. light probes (currently more advanced, but maybe we’ll have an off-the-shelf implementation someday)
  4. other types of global illumination (currently very advanced…)

I think (1) and (2) are most common today.

I think in a lot of game scenarios… you have one directional shadowcasting light that follows the player around,( then possibly another colored rim light that follows the same rig but positions relative to the camera view direction etc.)
You don’t want the directional light to track the players position tightly, otherwise you get shimmering as the shadow caster moves across the geometry, so instead you make it only move if the player has moved a certain distance from the cameras focal point… and you try to make that x/y distance be close to a multiple of the shadowmap density so that when it does move, it moves to a similar grid coordinate for the shadow not appear to shimmer. If tuned right, this can give you a feeling of the a seamless sunlight being everywhere.

Then, per region or zone or via area boxes, you may have local lighting setups that are different… for instance an animated point light+shadow caster for torches/campfires… that sort of thing. these fade in and out according to the players proximity to the relevant “zone”. Some older console games like San Andreas also used an environment “map” in their zones that encoded a light color+intensity from 8 different cube corners, and uses that to tint the overall light colors based on camera direction to give lighting more variation… like neon lights glowing from a certain direction in a night club zone… or blues/greens for underwater etc.

It really varies from game to game but those are some of the general principles. General rule of thumb on consoles is that you can expect hardware support for 4 lights minimum, up to 8 or 16 on higher end systems… so actual lights have to be pretty carefully managed.

Smoke and mirrors!

1 Like