just noticed: the Version 7.32.2 makes the function BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync never resolve the promise and the function CreateScreenshotUsingRenderTarget never calling the successCallback()
It seems like the internal texture-readyness-check (setTimeout()) never gets true - stuck in endless loop.
I cannot reproduce this in PG unfortunately - i am a bit lost.
Version 7.32.0 was working - i guess this has something to do with the big Frame graph PR?
Do you have any ideas where do look next to debug this further?
Version 7.35.1 is broken for me, tracked it back to the last working Version 7.32.0.
This is part of a more complex project, the default Playgrounds from the docs all seem to work, so I struggle to reproduce this…
Using WebGL2, nothing too fancy for the engine/scene setups, removed all postprocesses … BJS - [20:43:27]: Babylon.js v7.35.1 - WebGL2 - Parallel shader compilation
Electron 33 / Chrome 130
This functions generates preview images of items to be saved to disk. The call to BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync resizes the engine … and hangs … not resolving promise.
... new BABYLON.Engine(this.canvas, false)
.. this.scene = new BABYLON.Scene(this.engine)
...
let engine = this.scene.getEngine() as BABYLON.Engine
let camera = this.camera_item.camera as BABYLON.ArcRotateCamera
...
let data = await BABYLON.Tools.CreateScreenshotUsingRenderTargetAsync(
engine,
camera,
{
precision: 1.0,
width: 1024,
height: 1024,
},
'image/png'
}
If you request a width/height for the screenshot which is different from the output (canvas) width/height, can you make a test where the requested width/height is the same as the canvas? It’s a different code path in the code, it may help use narrow down the problem.
Another test: in case you don’t pass a parameter for the “samples” parameter (6th parameter of CreateScreenshotUsingRenderTarget) or if you pass 1, can you pass 4 and see if that helps?
Due to the different environment (Electron / browser), you may not be able to reproduce the error in the browser, unfortunately… If you can give us a repro in a separate github project / by sending us a private email if the project is not to be disclosed, we might (hopefully!) find the bug quickly.
Thanks again for all your time!
Right now I’m unable to share the project in its current state / reasonable time - I try further deconstruct, shrink it and try to make it available.
Vite → http://localhost → Chrome behaves exactly the same as in Electron. So this may not be a difference.
Differences to Playground are:
multiple scenes for 3D and GUI
multiple cameras
GLB-Models / multiple materials
Typescript/Treeshaking/ES6-Module-Imports? (no errors in log)
Have you been able to perform these tests in your existing code:
If you request a width/height for the screenshot which is different from the output (canvas) width/height, can you make a test where the requested width/height is the same as the canvas? It’s a different code path in the code, it may help use narrow down the problem.
Another test: in case you don’t pass a parameter for the “samples” parameter (6th parameter of CreateScreenshotUsingRenderTarget ) or if you pass 1, can you pass 4 and see if that helps?
Thank you for your patience!
I tried both your suggestions with no difference in behavior. Noticed that different width/height scaled my entire viewport/canvas. Also samples = undefined, 1, 2 or 4 makes no difference.
Everything in the scene is already loaded and running - screenshot is called on button click.
I debugged to the point where texture.isReadyForRendering() check is false
thanks to Vite the @babylonjs/core file: is chunk-Q7QCB…
Can you debug inside isReadyForRendering? You should end up in ObjectRenderer._checkReadiness at some point (use v7.35.1+). The call to mesh.isReady(true) will probably return false, so you should also step inside this function to see more precisely what’s wrong. Try to get the name of the mesh or the material that is not ready. It’s not the ideal way to debug, but without a repro, I don’t see how to do it.
Thank you again @Evgeni_Popov for encouraging me to debug deeper!
Tracked this down to ParticleSystems “not being ready” aka not having mesh-emitters set
→ already answered in Screenshot and ParticleSystem
_checkReadiness() {
...
const particleSystems = this.particleSystemList || scene.particleSystems;
for (const particleSystem of particleSystems) {
if (!particleSystem.isReady()) {
returnValue = false;
Solution/Workaround
Setting dummy-mesh for all (in my case unused) ParticleSystems in scene, before calling BABYLON.ScreenshotTools.CreateScreenshotUsingRenderTargetAsync
Not quite clear to me, why this happened exactly since v7.32.2 …
Some graceful failing would have also been helpful, not launching infinite setTimeout() …
Thanks again for your help and great work with babylon.js!
Sure. we should use this function whenever there is no render loop to use. I can see if i can move it somewhere that is tree-shakable and won’t add too much to a package using the shader precompilation. i’ll add it to my list of stuff-to-do