Three js canvas lagging every few seconds

Hello,

I’m bulding an animation of a glb model.
After loading it on the scene, few seconds pass by and it starts to lag.
Another few seconds pass, and the lag dissappears, then the cycle begins again.
this is the code for initializing the scene:

function initScene() {
  const renderer = new THREE.WebGLRenderer({
    antialias: true,
    canvas: document.getElementById('three-js-canvas')
  })
  // const three_js_col = document.getElementById('three-js-col');
  renderer.setSize(window.innerWidth,window.innerHeight);
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 15000)
  window.addEventListener('resize',() => {
    camera.aspect = (window.innerWidth * 10/12) / window.innerHeight
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth * 10/12, window.innerHeight);
  })
  const environment = new RoomEnvironment(renderer);
  const pmremGenerator = new THREE.PMREMGenerator(renderer);
  const controls = new MapControls(camera, renderer.domElement);

  scene.background = new THREE.Color(0xffffff);
  scene.environment = pmremGenerator.fromScene(environment).texture;

  camera.position.set(0,50,50);
  camera.rotation.z = Math.PI;

  controls.enableDamping = true;
  controls.update();

  const light = new THREE.AmbientLight(0xFFFFFF,1);
  scene.add(light);
  const axesHelper = new THREE.AxesHelper(20);
  scene.add(axesHelper);
  return {
    scene: scene,
    renderer: renderer,
    camera: camera,
    controls: controls,
  }
}

This is how i’m loading the model

async function loadModel(scene,robot_name) {
  async function getRobotModel(robot_name) {
    ...
    return model.url;
  }
  const loader = new GLTFLoader();
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.7/');
  dracoLoader.setDecoderConfig({type: 'js'});
  loader.setDRACOLoader(dracoLoader);
  loader.load(
    await getRobotModel(robot_name),
    (glb) => addModelToScene(glb,scene),
    (xhr) => {
      if(xhr.lengthComputable){
        loading_progress.value = (xhr.loaded/xhr.total)*100;
        if(loading_progress.value >= 100){
          loading_complete.value = true;
        }
      }
    },
    (err) => {
      alert(err);
    }
  )

and this is where the code above is called

onMounted(() => {
  function animateScene() {
    requestAnimationFrame(animateScene);
    controls.update();
    renderer.render(scene,camera);
  }
  const {scene,renderer,camera,controls} = initScene();
  loadModel(scene,robot_name);
  animateScene();
})

I’ve been trying to find the issue looking for memory leaks topics, but haven’t found a solution.

Are you using a LoadingManager to ensure all your async resources are loaded before running initialization? It looks and sounds like some resources may still be loading after your first render…

Thank you for a tip.
Currently not, I will try it tomorrow and give you a feedback.
Altough even if not used, would it cause a persistent “lag cycle”? Im currently loading 1 model and the “lag cycle” happens after the model is loaded.

I would suggest running a performance profile in Chrome dev tools for a few seconds, it should be possible to see “something” in the graph where frames are dropped. Your code looks reasonable to me. Are you quite sure that onMounted is being called exactly once?

Also, especially if you’re developing with some hot reload server, you may need/want to cancel the animation loop somehow, otherwise you may have many render loops running at once.

1 Like

Didn’t know about the hot reload thing. That’s very useful. Thank you.

OnMounted()

Is called as a part of a component lifecycle whenever a component is created.
In other words, whenever a page is being opened, onMounted is being called, so it should only be called once. I will debug it just to be sure. Tomorrow I’m gonna reply with test results.

While reading posts about lags/low framerate, I’ve seen a lot of posts about the complexity of loaded model, I’m also gonna check the issue there and post results tomorrow.

Again, thanks for the ideas and tips :slight_smile:

The performance looks normal to me. I’ve updated the code and it seems that the issue was with hot reload whenever i’ve updated the code.

let animation_request;
onMounted(() => {
  function animateScene() {
    animation_request = requestAnimationFrame(animateScene);
    controls.update();
    renderer.render(scene,camera);
  }
  const {scene,renderer,camera,controls} = initScene();
  loadModel(scene,robot_name);
  animateScene();
})

onUnmounted(() => {
  // hot reload
  cancelAnimationFrame(animation_request);
});
2 Likes