Performance Optimization for Dynamic Lights in a Car Simulator Using Three.js

Hello everyone,

I am currently working on a car simulator that utilizes dynamic lights, as demonstrated in this video: Dynamic Lights Car Simulator. However, I also have a version without dynamic lights, where all the lights have fixed positions and rotations: Fixed Position Lights Car Simulator.

This simulator is based on the Neon Racer Car Simulator.

I am seeking advice on performance optimization for the dynamic lighting implementation, particularly with the lights being part of the rigid body. Additionally, I’ve noticed that the camera occasionally lags behind due to FPS drops during gameplay.

Any tips or strategies to improve performance and camera responsiveness would be greatly appreciated!

    return (

    
<>


        <group>


            <RigidBody
softCcdPrediction={50}
collisionGroups={collisionGroups.OWN}
solverGroups={collisionGroups.OWN}

friction={0.1}
onIntersectionEnter={(e) => {
  if (e.collider) {
    // Eğer yere değiyorsa driftContact.current = true olur
    const isGround = e.collider; // e.collider ile temas edilen nesneyi kontrol et
    driftContact.current = isGround ? true : false;
  }
}}
onIntersectionExit={() => {
  // Yerden ayrılınca driftContact.current = false
  driftContact.current = false;
}}
  
            name='car'
                position={[position[0],position[1],position[2]]}
                rotation={rotation}
                canSleep={false}
                ref={chasisBodyRef}
                colliders={false}
                type="dynamic"
                scale={scaleOfCar}
                angularDamping={angularDamping}
            >
     

   <group ref={allBody} scale={[1,1,1.25]}>
{
  //burası 0.5 arttı
}




                <CuboidCollider collisionGroups={collisionGroups.BODY}
  mass={0.1} position={[0,0.45,0]} args={[0.8, 0.4, 0.4]} />
                
                <CuboidCollider collisionGroups={collisionGroups.BODY}
 mass={2} position={[1.4,0.35,0]} args={[0.2, 0.2, 0.4]} />
                <group>
                {
!Nitro  && nitroForce == 100  && <ModelForAnimsPrimitive url={Nitro} meshArgs={{position: [0,0,0], rotation: [0,0,-Math.PI / 2], scale: [0.01,5,0.25]}} BodyArgs={{colliders:false}} controller={false} myIndex={999} />
}
                <CuboidCollider collisionGroups={collisionGroups.BODY}
 mass={1} position={[-1.4,0.35,0]} args={[0.2, 0.2, 0.4]} />
                </group>
</group>





                {/* chassis */}
{/* chassis */}
    {/* chassis */}
    <group visible rotation={[0, -Math.PI / 2, 0]} ref={chasisMeshRef} scale={0.6}>


{
    type === "GLB" && CarFBX && <primitive key={Math.random() * 1000} ref={carRef} object={CarFBX} />
}


{type === "FBX" && body.current && body.current.length > 0 && body.current.map((mesh, index) => (
<mesh key={"car_racer" + index}>

<primitive ref={carRef} object={mesh} />
</mesh>  
))}






</group>


    
                {/* wheels */}
                {wheelsRef.current && wheels.map((wheel, index) => (
                    <group key={index} ref={(ref) => ((wheelsRef.current)[index] = ref)} position={wheel.position}>
                        <group scale={[1,1,1]} rotation-x={-Math.PI / 2}>
                        <mesh position={[0,0,0]}>
                                <cylinderGeometry  collisionGroups={collisionGroups.WHEELS} args={[0.25, 0.25, 0.225, 64]} />
                                <meshStandardMaterial map={_wheelTexture}/>
                            </mesh>

   
                    
                            <mesh position={[0,0,0]}>
                                <cylinderGeometry collisionGroups={collisionGroups.WHEELS} args={[0.25, 0.25, 0.225, 64]} />
                                <meshStandardMaterial  map={_wheelTexture} />
                            </mesh>
                        </group>
                    </group>
                ))}
     

     <pointLight
            ref={pointLightRef}
            color={"white"}
            intensity={2} // Şiddeti düşürdük
            position={[-5, 3, 0]} // Başlangıç pozisyonu
            distance={50} // Mesafeyi artırdık
            angle={Math.PI / 2} // Açıyı pozitif yaptık
            penumbra={0.2}
            decay={0.1} // Dağılma faktörünü artırdık
            castShadow
            shadow-mapSize-width={256}
            shadow-mapSize-height={256}
            shadow-near={0.5}
            shadow-far={50}
          />

            </RigidBody>
        </group>

        {MemoizedPlayerList}

        </>  
    )

lights are very expensive, but lights casting shadows are ultra expensive. that one pointlight will render the entire scene 6 times extra, if you have, say, 10 of these, you render the scene 61 times every single frame.

you can have maybe one single shadow casting point light and one or two spot/directionallights.

games used tricks to overcome that. cascading shadow maps is one. but with threejs you have to keep the amount of lights small.

ps you can do a lot with envmaps, even animating them, see https://codesandbox.io/p/sandbox/lwo219

still envmaps are very fast, animated envmaps can be fast depending on the system, or slow. i think windows has a problem with it.

1 Like

But the problem is this:
After I added the lights into the rigid body, issues arose. Even though I changed the position and rotation of almost all the lights, the optimizations did not eliminate the stuttering; the screen started to dim occasionally. However, before adding the lights to the rigid body, there were no issues, so I believe there is another reason.
With the optimization, I reduced the RAM usage of this simulator to 1.5 GB, but it only became problematic after I added the light source into a rigid body.
Now it stutters much more than before; normally, there wasn’t any stuttering.

optimized version

So my question is: Can I update the envMaps when the car’s position or rotation is updated?

rigid body or not, it doesn’t make a difference where the light is mounted. a rigid body is just a three.group with some meshes in it. if you have strange effects that must be related to something else. since the light casts shadows, it can well be that it’s occluded sometimes which cold provoke a flicker.

2 Likes

Good day from Turkey, and I apologize if I took up your time.
If you have any suggestions, feel free to share them on YouTube or here.
We’re turning this into a game.
Thank you very much in advance.

By the way, since I am making this game by myself, I occasionally need help. Thanks again for your assistance!