Render only after user interactions

I am managing a scene from external data but the users can control the camera and move some objects. When the render loop is running most of the renders result in no changes but still make the laptop fan go wild.

What is the best way to skip calling scene.render() if the scene has not received any updates from outside and the user is not trying to interact with it directly?

Invalidating scene based on incoming data is easy. And for detecting user interactions I was hoping to rely on camera.onViewMatrixChangedObservable, but that does not seem to be triggered while the scene is not being rendered.

The solution I found:

const inputChanges = pick(camera, [
  'inertialAlphaOffset',
  'inertialBetaOffset',
  'inertialPanningX',
  'inertialPanningY',
  'inertialRadiusOffset',
])
if (some(inputChanges)) {
  localState.isDirty = true
}

This is right, you can maybe just attach to scene.onPointerObservable?

I toyed with that idea as well, but then I have to recreate the logic of detecting regular move and a drag move, which is not desirable.

Ideally I would like to see this as:

  engine.runRenderLoop(() => {
    if(!camera.hasPendingChanges()){
      return
    }
    scene.render()
  })

I might over-prioritize my use-case and miss some harder to calculate inputs, but this seems like a low hanging fruit to improve the perceived performance through reduced CPU heat for a lot of content out there. What do you think?

Isnt that camera.onViewMatrixChangedObservable ?

I agree (only when there is no physics or animations though).

hasPendingChanges can be something like camera.inertialBetaOffset === 0 && camera.inertialAlphaOffset === 0 (for an ArcRotateCamera)

1 Like