First render(s) to RenderTargetTexture blank in Chrome

Hello!

I’m having an issue with Babylonjs where the first time(s) I try to render to a RenderTargetTexture, it simply appears blank. Subsequent attempts to render work perfectly.

It doesn’t seem to be timing related. Even if I wait several seconds before the first render, between the renders, or do them all in one frame, I see the same results. In my main app I’ve also seen the first two renders always come out blank, but in the repro below only the first is blank.

This also seems to be browser dependant. I’m seeing this problem in Chrome (and chromium based browsers). FireFox always renders on the first try no matter what.

I’ve reproduced the issue in this playground link: https://playground.babylonjs.com/#2MWJ5F#2. If you load this in FireFox, you’ll see four spheres appear in the top right corner, which is the expected behavior. If you load this in Chrome, the first one is blank, and the other three appear normally.

What I’m trying to do: My app needs to move some objects to a new location, create a camera pointed at them, take a picture of them (render one frame to a RenderTargetTexture), then delete the camera and move the objects back to their original location. I then use Tools.DumpData to convert the RenderTargetTexture into a png for display in the browser and then delete the RenderTargetTexture.

This playground simulates what I’m doing by creating the camera, creating a sphere, rendering one frame, then destroying both.

Can anyone help explain why the first renders are coming out blank?

Thanks so much!

Welcome aboard!

You should wait for the render target texture to be ready before doing the rendering: compiling shaders may take more than one frame, so if you do a readPixels while the shaders have not been compiled yet, you will get an empty texture because meshes won’t have been rendered.

You can do it like this:

1 Like

Thanks so much for the quick reply!

This is helpful but I’m still perplexed. The issue with this sample is the sphere is created outside of the doItWhenReady function. If I move it inside that function, then I still have the same issue:

You can see in this code that the first render is still blank in Chrome, even though isReadyForRendering is returning true. Can you give any more advice on why the first render still isn’t working?

Here’s why this matters: In my app, I’m moving meshes away from their normal location, taking a render of them, then moving them back. Therefore, I can’t wait more than one frame for the render, or the user of the app would see the objects disappear and re-appear. I could clone the meshes, but they’re large and complex objects so I’d like to avoid that for performance reasons. So I’m trying to find a way to do the render in one frame. The sample code here simulates this by creating the sphere on the same frame we call render(), which seems to be the issue making it not appear right away.

It’s OK for the readPixels to be done a later frame, or for the RenderTargetTexture to be created ahead of time, but the actual render needs to be on objects that were just moved into place. This seems to be the sticking point.

The only solution I can find through experimentation is to do a few “wasted” renders. Create a RenderTargetTexture, render a couple blank frames to “prime” it so that the real renders work later. This feels really hacky to me, surely there must be something I’m missing?

isReadyForRendering checks that the meshes in the renderList array are ready. So, if this array is empty, it will return true directly.

The problem is not so much the meshes themselves, but the compilation of their materials: that’s what may take time and will make isReadyForRendering returns false for a few frames.

You can use the material.forceCompilationAsync method to compile a material for a given mesh. For eg:

1 Like

Thanks so much for your help! I was able to get it working by doing a forceCompilationAsync when the app starts up, that way everything is compiled and ready to go. Cheers!

1 Like