Reduce the heaviness in the scene

Hello everyone,

I have a problem when I added the lights to the scene, it becomes heavy in moving the camera.

 addSpotLight(positionX,positionZ,targetX,targetZ){
    let spotLight = new SpotLight( 0xF6E7D2 , 0.1,8, Math.PI/2 ,0.8,1);

      spotLight.position.set( positionX, 3 ,positionZ );
        spotLight.castShadow = true;
        spotLight.name = "spotLight";
        
        spotLight.target.position.set(targetX,0.5,targetZ);
        spotLight.target.updateMatrixWorld();

        spotLight.shadow.mapSize.width = 1024;
        spotLight.shadow.mapSize.height = 1024;
        spotLight.shadow.camera.near = 0.5;
        spotLight.shadow.camera.far = 4;
        spotLight.shadow.focus =1; 
        spotLight.shadow.bias = - 0.005; 
        scene.add( spotLight );
  }

  1. Adding a single light to a scene shouldn’t be too expensive. Just keep in mind to not add more than 7-8 lights - that approximately reaches the limits of three.js lights usability (because forward renderer. 8 lights in total - regardless whether the light is Directional / Point / SpotLight.)

  2. For lower-end devices you can also disable the shadowmap - but it also shouldn’t slow down things too much on average computers, especially with 1024x1024 shadowmap texture.

  3. Additionally, each time you add a new light to the scene, Three.js recompiles some shader materials - which causes a frame freeze. If you want to use the maximum amount of lights in your scene, just add 7-8 light sources during the initialization of the scene - then reuse them by changing positions / colors / intensities. That way you can avoid adding new lights later.

1 Like

Thank you @mjurczyk,

I have 11 lights in my scene, I use the addSpotLight function to add them in the initialization time.

As a result, I have to reduce it’s it.

If you use the function you’ve shared above to create all 11 of them - you are also creating 11 shadow maps - which effectively will render the scene additional 11 times per frame (one for each light shadow map.)

If you want to use shadows - be sure to enable them only on 1 or 2 lights at most (additionally, for PointLights, shadow maps are 4-6x more expensive, since they are rendering a shadow mask in all directions - so adjust the shadow map resolution accordingly.)

2 Likes

to add to what @mjurczyk said, from three.js manual

Three.js by default uses shadow maps. The way a shadow map works is, for every light that casts shadows all objects marked to cast shadows are rendered from the point of view of the light. READ THAT AGAIN! and let it sink in.

In other words, if you have 20 objects, and 5 lights, and all 20 objects are casting shadows and all 5 lights are casting shadows then your entire scene will be drawn 6 times. All 20 objects will be drawn for light #1, then all 20 objects will be drawn for light #2, then #3, etc and finally the actual scene will be drawn using data from the first 5 renders.

It gets worse, if you have a point light casting shadows the scene has to be drawn 6 times just for that light!

it’s written a little melodramatically, but the gist is that you incur at least double the amount of drawcalls you already have which can make an impact if your scene is large enough. like he said, 11 lights === 11 more full render passes of your scene.

you should also look into baking light in blender, that is the fastest and best looking approach.

1 Like