Working with on-demand rendering loop

For my application, I perform rendering only when there are changes in the scene.

Using this scheme:

engine.runRenderLoop(() => {
    if(isChangesInScene) {
        isChangesInScene = false;
        scene.render();
    }
});

However, when I change the material for a mesh (and set isChangesInScene=true), or add it to a HighlightLayer, the changes are not applied immediately, and the rendering that is called right after the changes does not reflect them. And since no more renderings are called (until the next changes occur in the scene), the scene remains rendered incorrectly.

To solve the problem when changing the material, I called material.forceCompilation(mesh), but this didn’t help.

Is there perhaps some mechanism that allows tracking whether more frames need to be rendered to correctly display the scene with all the changes?

You could render the scene multiple times. Set a maxRenders constant to limit the render count to this value.

This doesn’t sound like the most elegant solution. Are there perhaps some events that allow us to understand whether the internal processing of the mesh has been completed?

But the simplest one and works for sure :wink:

Not actual:

However try this one: EDIT: I didn’t save the PG, wait a moment… This one doesn’t work.

EDIT2:
Working PG: https://playground.babylonjs.com/#6N2UDN#1

EDIT3:
I have two PGs open with tha same code. In one of them it works in the second one it doesn’t… WTF! I’ve just created a screen recording but I’d rather investigate a bit more on the issue, don’t want to look like an idiot if I screwed up something obvious :smiley:

EDIT4: One of them didn’t stop the default render loop.

If the change takes longer than the timeout, then there will be an incorrect result on the screen, and if we make a very large timeout, then there is too much unnecessary rendering, which negatively affects the battery life of mobile devices.
When I worked directly with WebGL, after each change (loading textures, compiling shaders, and so on), I called a special callback that initiated a frame redraw. Is there something similar in Babylon?

You could use a numberOfRendersNeeded variable instead of isChangesInScene. Or even better create a function called function rerender(changeType) and call this to queue some render cycles. Queue number of cycles according to changeType.

Can you poll Babylon.js docs / Babylon.js docs isReady()?


More generally, is it really that we need actual renders? Or is it not rather some async stuff going on which takes a bit. So the problem would be to figure out how to measure precisely when the async stuff has finished.

No timeout but render cycles. You might associate number of rendering cycles needed to the actions you perform. If you add a mesh to the HL it’s 2. If you move the mesh, it’s 1. So you render 2 times or once. If you perfrom these actions together call render (2 > 1) 2 times.

Is that == scene.render()?

Yes, it is.

1 Like

Can you double check? https://playground.babylonjs.com/#BZFHT1#2

I have created a component for react-babylonjs that listens to movements and animations.
in my own app (not react-babylonjs) i had a similar issue as yours. I made a global variable that I could change to force a rerender. something like:

let isForced = false

....
if(isChangesInScene || isForced){  
  isForced = false .... 
} 

....
function forceRender() { isForced = true }

some inspiration for render on demand

related thread: What is the correct way to render on demand - #22 by samevision
little video: Render on Demand by dennemark · Pull Request #253 · brianzinn/react-babylonjs · GitHub

Currently, I’m using isReady and running forceCompilation if !isReady. The callback of this function tells me when the compilation is finished, and I perform a redraw.

However, I wish Babylon.js had a mechanism that would allow intercepting all changes in the scene (shader compilation, texture loading, and other things). It’s a pity that it doesn’t exist. Without it, you constantly need to figure out which callbacks to attach to which events that might change the scene when rendering is complete.

Nothing red appears.

The problem is that something might load into the scene some time after the changes were made.

For now, I’ve figured out the issue. It’s a pity that Babylon.js doesn’t have exactly what I was looking for, but your answers have given me an understanding of what to do next. Thank you all very much!

1 Like

I see. Even after 3 s nothing changes.

Oh interesting! Checked in Chrome, not working. In Firefox, working.

I believe this functionality will be very welcomed by the community. Nowadays a lot of products are designed for mobile platform at the first place, desktop comes as second. Saving the battery by rendering only the necessary amount of frames could be a very useful stuff.

@Deltakosh what do you think about it? Can we somehow notify the client code that everything has been rendered? If so and we get enough votes and you give me some pointers where to start I’m willing to do the PR.