How to pre-load (lots of) textures in a backgroud thread smoothly

My intention is to download the files (cubemaps) to cache them for further usage I don’t need to have them in memory, just download them to make a fast load.

I already managed to make that preload with two different methods:

  • Adding addCubeTextureTask and calling load() in the assetsManager.

  • Using a recursive function that creates a promise and once a texture is loaded it gets disposed and tries to load the next one.

Unfortunately both options are lagging the navigation a lot, is there any other alternative?

Thank you for any tip!

Do you experience lagging while loading, after loading or when changing the textures?

@labris while loading once all the tasks have been completed it becomes smooth again.

Seems that the simplest solution will be to use loading screen until all needed assets are loaded, then hide loading screen - Creating Custom Loading Screens | Babylon.js Documentation

I already have a proper loading screen working, but I know that I’ll need those textures later that’s why I try to load them in advance meanwhile the viewer is already running (with the actually needed textures already loaded).

By default, all texture contents are cached by the engine, so if you load the same texture twice, it will be instant (and resource will be shared to save memory).
This is one way.
Another is to indicate that you want to cache the resources associated with your scene/game inside the local IndexedDB of the browser - Optimizing Using Cached Resources | Babylon.js Documentation

1 Like

That was exactly what I want to chache them even before being used for that I tried to load and dispose them to make a fast reload when is the texture is required.

Thank you for your time.

Hello,
thanks for sharing your concern.
whereas stacking once all the assignments have been completed it gets to be smooth once more.

I’ll try to summon the great guru @Deltakosh :slight_smile:

@Escobar there is an idea @Evgeni_Popov posted in Throttle processing power/bandwidth to keep stable FPS during loading - #15 by Evgeni_Popov

TLDR: moving as much of texture loading into a worker as possible. I am still working on this myself, since had other fires pop up that took me off that branch

How did you managed to do that? I tried by moving

BABYLON.Tools.LoadFile(textureFile, function () {});

into a worker and it gets downloaded but it doesn’t speedup the loading time :unamused: placing a loadcubetexture there do not help since I cannot send scene as reference to place the texture in that reference, and probably making a secondary copy do not help with loading times neither.

Thank you for your time, I’ll owe you a beer for each useful tip!

More trying to solve the frame lag caused by loading textures during runtime. For workers, only tried downloading a whole glb and transferred back the buffer for Babylon to load. That does not help the lag much. (I think because textures are then further extracted on the main thread by SceneLoader)

I am not sure this will work for your setup if you are not using packed up glbs/a custom extension that gets hit. The thing that helped performance (somewhat) is slowing down how many/often the textures get processed by Babylon. Again, this might not be what you are after at all :smiley:

loadMaterialPropertiesAsync returns a Promise.all()

https://www.npmjs.com/package/p-limit used this library to create a limiter for all the texture load promises that get pushed in there.

@FrameVRWill this might be interesting for us as we get into our asset load queues.

Here is my task.js code where oEvent.data is a Babylon SmartArray that contains the URL of each texture

onmessage = function (oEvent) {
const suffix = ["_px.jpg","_py.jpg","_pz.jpg","_nx.jpg","_ny.jpg","_nz.jpg"];
for(var t=0; t<oEvent.data.data.length; t++)>
{
console.log("Background download: ",oEvent.data.data[t]);
for(var i=0; i<6; i++)
{
const textureFile = oEvent.data.data[t] + suffix[i];
BABYLON.Tools.LoadFile(textureFile, function () {});
}
}

It downloads the files but unfortunately I didn’t get any performance gain as if “the scene babylon” doesn’t take advantage of “this babylon” download.

Maybe someone of you could use this code in your tests if you find it useful.

Btw loading textures with LoadFile using promises is speeding up the loading a lot but if I don’t use them in a Babylon Texture it seems that they are removed by the garbage collector and unfortunately if I use them in a texture the laggy loading appears again.

Any tip to avoid the gc to remove them?

1 Like

Can you just hang on to them with a reference in an Object that you know sticks around ? Also then can release them by deleting the key, when you do want them cleaned up.

As long as you have a reference to a loaded texture in something attached to window( in its chain of references ), the GC should not clean it up.

1 Like