Texture loading is freezing my game for 6 seconds


I have got some weird problem that I do not understand.
I load my level assets asynchronously with a loading screen. And when I get my promise resolved and remove the loading screen, the level takes 6 sec or more to appear on screen.

I checked Chrome’s debugger, and it seems that there are two odd things occurring.

First, there are plenty calls to ConvertCubeMapToSphericalPolynomial which freeze the first frame of the game for ~6sec:

Second, it also seems that the textures of the game level take a very long time to be loaded (I load the scene tileset.babylon with BABYLON.SceneLoader.ImportMeshAsync):

I tested the loading time of tileset.babylon in the playground, and it is much faster (less than 1 sec) than on my local server ^^ which is weird:

So it seems that there is something weird going on…
Is there anybody who know where ConvertCubeMapToSphricalPolynomial is coming from? and whether it could be slowing down the texture loading?

Thank you very much for your help :smiley:

Ok so I think the problem is similar to what was discussed in this thread: PBRSpecularGlossy and ReflectionProbe - Questions & Answers - HTML5 Game Devs Forum

I think I reproduced the problem at a smaller scale than in my game here:

(In the actual game, the problem become worse cause I use these tiles several time to generate a world, increasing the number of calls to ConvertCubeMapToSphericalPolynomial)

I was expecting the problem to come from the use of an environment Texture (line 25); however, it seems that to comment out the skybox creation (line 27 to 30) decrease the loading time dramatically!

Is there a way to prevent the initial freeze while still using a skybox?

Here we are:

uhh… yeah… except that I very need to keep the clouds :smiley: !

EDIT: using the same code, but loading the cloudy skybox instead: https://www.babylonjs-playground.com/#JUKXQD#145
Still taking several seconds to load, is there something wrong with my cloudy skybox… is it too big?

I’m wondering if this can come from the place where you serve the file from

I see nothing wrong else

Pinging @sebavan to get second thoughts

I have the same problem when I run the code locally (the PG is a reproduction of my problem).

In the following link, it seems that there is a way to skip the many calls to ConvertCubeMapToSphericalPolynomial:
PBRSpecularGlossy and ReflectionProbe - Questions & Answers - HTML5 Game Devs Forum
However, I don’t really understand how to apply it to my case.

You are using a pbr material so it relies on environment lighting computed from the environmentTexture. To compute it, it uses ConvertCubeMapToSphericalPolynomial which convert the 1024 cube to polynomial so going over 1024 * 1024 * 6 texels with heavy maths, so it can definitely take time. It will also be looking wrong for roughness as it has not been preprocessed.

I would in your case either not use a PBR material or rely on an env texture.

1 Like

thank you for your reply :slight_smile:

Is it possible to use a high resolution texture (1024x1024) for the skybox texture, and use a low resolution (128x128px) for the environmentTexture?

I think this is what my teammate (@Num_T) tried to do with:

    scene.environmentTexture = new BABYLON.CubeTexture(assetPath + "3D/NewWorld0/skybox_lighting.env", scene);

    let texture2 = new BABYLON.CubeTexture(assetPath + "3D/NewWorld0/Skybox/skybox", scene);
    let skybox = scene.createDefaultSkybox(texture2, true, 5000);
    skybox.infiniteDistance = true;
    skybox.applyFog = false;

However, as soon as the high resolution texture ("3D/NewWorld0/Skybox/skybox") is used as skybox, it seems that it is automatically used for the environmentTexture as well :confused:

EDIT: @sebavan, also, is there an observer that can notify us when the computation is done? cause I would like to hide my loading screen only when the level is visible.

You should not use the default skybox with pbr (second parameter should be false) or it would need the computation for the skybox material.

Then regarding the observer, scene.isReady would do.

Hope that helps.

Sounds like what I need. I tried to use False as second argument, but it did not change much the loading time for some reason :confused:

I thought I would try to properly time it with “True” and with “False”, to be sure there is no improvement, while trying onReadyObservable:

But, for some reason my observer never get called :confused:


The latest param prevents to apply the texture passed in the helper as the env texture for the scene.

1 Like

That solves the issue :smiley: thank you very much!

However, in term of the observable, I see you replaced it with scene.executeWhenReady() which works, but is it normal that the observable did not work?

Thanks again for solving this issue :blush: that unlocked my day :smiley: