All utility layer objects disappear when post processes applied

In my complex project, when I set:

UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene.postProcessesEnabled = true;

Then apply any post process, all my utility layer scene meshes disappear, but picking still works for those utility layer meshes even though they can’t be seen.

I’ve tried multiple built-in and custom post-processes with the same result and am a bit stumped.

The following simple PG does NOT replicate the issue, and as the inspector doesn’t list utility layer nodes, I’m unsure how to go about debugging this.

The closest forum post I could find to my issue is this, but it’s not exactly the same issue (I’m using the default utility layer overlaid atop the main scene - I’m not changing the default render order).

Hey!
I can see the post-processed sphere on ulScene.

Yep, the PG doesn’t replicate the problem I’m having in my complex project, despite it being a similar setup.

OMG sry I’ve missed this :smiley:

1 Like

If nothing helps simulating the utility layer by dropping in another camera could solve the issue. However let’s wait for other answers…

cc @Cedric

1 Like

I’d first check with a spector JS capture to see if meshes are not rendered because of some rendering state or if the drawcall doesn’t happen at all.

Also, set disappearing mesh as always active.

1 Like

Thanks @Cedric. I’ll continue investigating today and report back if I discover anything.

@Cedric thanks again for your tips.

I’ve been able to replicate the problem:

I have 2 cameras and am switching between them every 3 seconds. The PG passes camera1 into the PostProcess constructor, but also attaches the post process to both cameras. In this setup the post process works on both the main scene and utility layer scene for camera1 only, but the utility layer mesh sphere2 disappears on switching to camera2.

If instead I pass in a null camera to the PostProcess constructor (see line 58) yet still attach the post process to both cameras, the utility layer scene sphere2 disappears for both cameras.

In my complex project I was able to workaround this by reattaching the postprocess to the new camera every time the camera is switched, but I am concerned about doing this as the camera._postProcesses array just keeps growing on each camera switch.

I hope this makes sense. Any ideas what I’m missing or is happening here?

Here’s a PG that detaches the post process from the previous camera then attaches the post process to the new camera. This works for both the main scene and the utility layer scene, however if you take a look at the console output, camera._postProcesses.length just keeps growing.

Also, maybe I’m misunderstanding, but if the post process is set to reusable shouldn’t I simply be able to attach the post process once to all cameras, and it should just work for both the main scene and utility layer scene(s)?

I’m still sifting through the Babylon.js code, but it seems PostProcesses are linked to a specific scene as well as a specific camera (which is also tied to a specific scene), so maybe this is causing inconsistencies when applying post processes to the utility layer scene and switching cameras?

It seems camera._postProcesses.length does keep growing, despite camera.detachPostProcess() being called, but detached post processes are nullified rather than being removed from array. I guess this is by design? This is likely unrelated to my central issue anyway i.e. inconsistencies when applying post processes to the utility layer scene and switching cameras.

ping @Evgeni_Popov for the post process cameras

This is by design indeed.

You can do what you want by doing it this way (you need to call UtilityLayer.setRenderCamera to indicate the camera after which the layer should be rendered):

1 Like

Thanks @Evgeni_Popov

This works so I’ve marked it as the solution, however I’m still a bit unsure why it’s required. The docs for that UtilityLayer.setRenderCamera method state:

Sets the camera that should be used when rendering the utility layer (If set to null the last active camera will be used)

But I see now I’m probably misreading this comment. I had left it null and maybe expected the utility layer camera would always be the last/current active scene camera but it seems I have to explicitly set the utility layer render camera every time the main scene camera changes.

It seems strange that the utility layer uses the current active scene camera for rendering by default but UtilityLayer.setRenderCamera needs to be explicitly set for the post processing to work on the utility layer.

There is a slight misunderstanding, because the camera is used for two different purposes, and we should probably separate these uses…

The obvious use of the camera is to render the utility scene. The less obvious use of the camera is that the utility scene is rendered (utilityScene.render() is called) in the observer originalScene.onAfterRenderCameraObservable.

Conceptually, we should not require that these two uses come from the same camera. We might want to render the utility scene with camera2 after camera1 has been processed by the main scene, which is currently not possible.

Note that if you don’t set the camera through setRenderCamera, this code is run to pick the camera:

if (this.originalScene.activeCameras && this.originalScene.activeCameras.length > 1) {
    activeCam = this.originalScene.activeCameras[this.originalScene.activeCameras.length - 1];
} else {
    activeCam = this.originalScene.activeCamera!;
}

if (getRigParentIfPossible && activeCam && activeCam.isRigCamera) {
    return activeCam.rigParent!;
}

It takes the last camera from activeCameras if there are 2 or more, or the camera from activeCamera.

1 Like

Thanks for the explanation @Evgeni_Popov