Loading textures at runtime to reduce loading time

Hi guys,

For my game, I would like to load specific textures to run on desktop and different textures to run on mobile. The textures to run on mobile will have lower resolution, which helps the game to load faster.
I am currently setting my default textures at run time at low resolution, and if the system is desktop, then it will load the higher resolution accordingly. However, when I disable the “preload” option for the high resolution textures, when I run the game on desktop, the high resolution textures don’t load. Below is the code that implement the loading of high resolution textures at run time:

Theoretically, if I disable the “preload” option, the textures should load at run time when I assign those textures to a specific material that is enable in the scene, so I am not sure why it is not loading.
The link to my project is:
https://playcanvas.com/editor/scene/980921

you can find the high resolution textures in the following folder:

Thank you!

Let’s see if I can explain this :slight_smile: The auto dependency load that you mention is part of the asset and asset registry system.

The section of code that you have shown here doesn’t really reference either.

        for( var i =1; i < this.imagesEntity.length +1 ; i++){   
            var currentPic =  this.pictureData[i.toString()];
            var pictText = this.app.assets.find(currentPic.Painting_Material.substring(0, currentPic.Painting_Material.length -4).concat('_2k.jpg'), "texture");

            this.imagesEntity[i-1].model.meshInstances[0].material.diffuseMap = pictText.resource;
    
        }

Taking this bit of code where you attempt to assign the texture to the material’s diffuseMap property. this.imagesEntity[i-1].model.meshInstances[0].material.diffuseMap is getting the property diffuseMap from the material resource object.

The material object has no knowledge of the asset system.

With pictText being the asset of the texture, as the texture resource hasn’t been loaded yet, pictText.resource is null. Accessing the resource does not trigger the asset registry to load it.

So basically, it is assigning null to the material’s diffucseMap.

There is an easy fix here though which is to trigger the load on pictText: (untested)

        var self = this;
        for( var i =1; i < this.imagesEntity.length +1 ; i++){   
            var currentPic =  this.pictureData[i.toString()];

            var pictText = this.app.assets.find(currentPic.Painting_Material.substring(0, currentPic.Painting_Material.length -4).concat('_2k.jpg'), "texture");
           (function() {
                var j = i;
                pictText .ready(function (asset) {
                    self.imagesEntity[j-1].model.meshInstances[0].material.diffuseMap = asset.resource;
                });
            })();

            this.app.assets.load(pictText);    
        }

As a side note: To check for this.app.touch for a mobile check may be an issue as laptops and PCs may have touch screens.

It works! Thank you yastar!

What is the proper way do you think to distinguish between desktop and mobile?

Not bad for typing it in untested :grimacing:

As for mobile detection, your best bet is checking the browser agent and there are a lot of libraries for that (eg https://github.com/kaimallea/isMobile)

The downside is that now iPads don’t give a mobile agent anymore. I’ve seen some developers check the agent and screen resolution to see if it’s an iPad which is a bit hacky :man_shrugging:

ahh I see I will try those out thank you Yastar. Btw it gives me this warning using your code, it still works but not sure if it will case any issue later on:

The warning is: Dont make function within a loop

Ah, the correct way would be to refactor that out to a function rather than creating an anonymous one in a loop.

1 Like