Scene rendering in background

Hi again! This community has been really welcoming and I appreciate that.

Now, I have some networking code tied to onBeforeRenderObservable. If I minimize the window, the network pauses until the window has focus again. I didn’t modify engine.rendereveninbackground, but I tried setting it to true anyway. No luck.

I didn’t post this in Bugs because maybe I just don’t understand how the rendering loop works. Or maybe there is a better place to put my network code? Does deterministic lockstep only work with physics enabled?

I hope I’m not asking too much. My networking works fine if I put it on a setInterval or keep the window focused. I’m just stumped on how to keep the network loop rolling in the background.

So I managed to push the networking into a web worker and decouple it from the render loop. Working great, and is probably the better way to go anyway. I am still curious about why it wasn’t working when tied to onBeforeRender. Seems like it should have been to me.

First - this is an amazing solution :slight_smile: And the right one I would say

About the onBeforeScene not working - this is due to this line in the engine’s renderLoop function:

            if (!this.renderEvenInBackground && this._windowIsBackground) {
                shouldRender = false;
            }

when the window is in the background, babylon is trying to be efficient and NOT render, which means - no beforeRender callbacks. You can set engine.renderEvenInBackground = true; to get it to work in the background

Thanks, @RaananW. I think this may be a bug then. I set engine.renderEvenInBackground = true and it still paused the network when it went to the background. Is there a specific point I need to set this property?

can you reproduce that in the playground?

https://playground.babylonjs.com/#V0DK6P

I popped the devtools out and then minimized the window and the counter stops moving. Bring the window back up and it starts counting again.

1 Like

requestAnimationFrame unfortunately is now mostly optimized and won t even run in modern browsers when the window is minified.

I guess you could on minimize stop the render loop and call in a setInterval() the function engine._renderLoop() and switch back to raf when the tab is visible again.

As it is mostly protecting users (draining battery on left over tabs), I am not to sure if we should integrate the workaround as a standard.

1 Like

Makes the most sense to me. Maybe the documentation should reflect this?

1 Like

im using this code:

engine.runRenderLoop(() => {
    World.scene.render()
})
setInterval(() => {
      if(!window.document.hasFocus()){
           engine.stopRenderLoop()
           engine._renderLoop()
      }
})

the problem is it will constantly stop the render loop.
should i save hasFocus() in a variable so it can compare if window.document.hasFocus changed to stop the renderLoop?
or do you have a better idea?
and what do you mean by “switch back to raf” how should i implement that?

it should be more along those lines (disclaimer: pseudo code…)->

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

let intervalId = 0;
window.document.onblur = () => {
  engine.stopRenderLoop();
  intervalId = setInterval(renderLoop, 16);
}
window.document.onfocus = () => {
  clearInterval(intervalId);
  engine.runRenderLoop(renderLoop);
}

And the best might be to rely on the visiblity APIs instead of onblur/onfocus: Page Visibility API - Web APIs | MDN

4 Likes

Hi,

I hope I’m not to late to this. But it looks like when I switch the tab (hiding the one with Babylon), setInterval does not run as fast as it should. Have you come across this?

yes and unfortunately there is not much we can do at the babylon level for this :frowning: You could try to put a smaller interval and render when on the right time.

1 Like