Speed: Engine Renderloop vs Custom Loop

Hello everyone,

I need your help to understand an issue I’m having today with my render loop. Let me explain: I have a full particle system and several Node Materials that drastically speed up when using the engine’s built-in render loop via the runRenderLoop function.

My physics simulation stays mostly stable between both approaches, but the particles and Node Material animations go completely crazy. Let’s focus on the particles for now, I used the exact same settings as in the official documentation example: https://playground.babylonjs.com/#MRRGXL#2

Here are the two ways I’m launching my render loops and their respective results.

const loop = () => {
  scene.render();
}

engine.runRenderLoop(loop)

EX1-ezgif.com-optimize

const renderLoop = () => {
  scene.render();
}

const start = () => {
  const delay = 1000 / this.frameRate;
  this.time = null;
  this.frame = -1;
  this.running = true;
  this.step = 0;

  const loop = (timestamp) => {
    if (this.time === null) this.time = timestamp;
    const seg = Math.floor((timestamp - this.time) / delay);
    if (seg > this.frame) {
      this.frame = seg;
      this.renderLoop();
    }

    this.tref = requestAnimationFrame(loop);
  };

  requestAnimationFrame(loop);
}

start();

EX2-ezgif.com-optimize

I also tried creating a hybrid version, I managed to globally slow down the framerate, but it has no effect on particles or Node Materials. What’s strange is that with the exact same configuration as in the docs, my particles are running way too fast.
Of course, I can tweak parameters like updateSpeed to something ridiculously low (e.g. 0.00005) to get the desired behavior, but that feels wrong, so I’d rather seek your expertise before doing something dumb.

Note: I’m currently forced to use runRenderLoop because I need multi-view / multi-canvas support. That’s why I’m a bit panicked, switching back would mean rewriting a big part of my application’s rendering system!

Thanks a lot for your help!

Hi @illuday welcome to the forum

cc @Deltakosh

1 Like

That looks like several scene.render() being called.

Can you ideally share a repro somewhere?

My spidey sense tells me that you may have more than one loop actve

For instance did you stop the previous render loop before calling the new runRenderLoop?
Try to add a stopRenderLoop to check

Thanks a lot for your quick replies!

I double-checked all my code, and I’m pretty sure I never duplicate any render loop.
To show you what’s happening, I reproduced both loops in a CodePen, here it is: https://codepen.io/illuday2/pen/MYKqzeW.

The result speaks for itself, and I don’t think I made any mistake in how the loop is declared.

They are the same :slight_smile:
BABYLON Loop Comparaison

(I added the correct calls to engine.beginFrame() / endFrame() in your RAF version)

The problem with not using runRenderLoop is that you do not let the system captures the frame time so the animation engines (particles included) have no clue how long was the previous frame and thus cannot adapt.

The runRenderLoop version is the correct one.

Reproduced here in the PG: Babylon.js Playground

So actually you were totally right with the updateSpeed parameter :slight_smile:

Another option is to play with a deterministic approach (one that does not adapt to framerate but unsure if this is what you need: Advanced Animation Methods | Babylon.js Documentation

3 Likes

Thanks so much for your help. It turns out my main loop wasn’t set up correctly, and I ended up adapting to it without realizing, which threw me off.

I’m going to go back through my code and review everything. Now I just need to understand why the Node Materials behave the same way, I don’t think I changed any parameters compared to the NME ones, but I’ll retrace the whole process to make sure.

If I find any inconsistencies or run into something I can’t figure out, I’ll reach out again.
Thanks again for your valuable advice.

2 Likes