How to assign texture only if it's fully loaded?

Hi there, i’m currently trying to load textures in my configurator app at runtime. The problem i’m facing is that when i switch textures the material gets black for a short amount of time till the new texture is loaded. I tried to solve this with the onLoad function of the TextureLoader() but it’s not working like i want. Here is a codesandbox that has this issue:

It happens because you are assigning the pending texture right away. A fix can be as simple as:

const [map, setMap] = useState(new THREE.Texture());
useEffect(() => {
  loader.loadAsync(`./textures/${AFLG}/${texture}.jpg`).then(texture => {
    setMap(texture); // NOTE Assign new texture only after it's loaded
  });
}, [AFLG, texture]);

This ensures at no point a pending texture is assigned to the model (you can also try preloading the textures before user even clicks them, at least some low-resolution versions, so that the user experience is smoother - you can swap immediately to a low-res texture to give user instant feedback, and load a high-resolution version in the background, swapping to it when it’s ready.)

1 Like

To avoid this, you can load all textures in advance and then use them.
please use useTexture.preload(‘path’); function.

is the memory waste really that big to warrant disposal on unmount? i notice that on a slow connection it’s almost unusable, materials get re-loaded when alternating options. imo if memory was a problem so that you decided against useTexture, perhaps it was just that the textures are way too big. door.jpg for example is 4k and almost 4mb. do you really need 4k? squoosh + webp + 2k yields like 80kb, the visual difference is minor. even cloning them so that each component has their own texture to mutate wouldn’t be that bad, and the clone can be disposed of course.

I’m building a configurator with 50+ textures with different resolution options so i thougth it would be better for the memory if i dispose stuff. Also i have the same texture many times, because i use different repetition values based on the objects sizing. What do you guys think is the right approach for such a big project? Preloading all textures is not an option, because it would be too big of a data load.

Good point, i definetly have to compress my textures alot more (the textures in the Sandbox are not the textures i’m using). I’m wondering what settings you use on squoosh to get 80kb (with 80% quality i only get ~400kb)?

By the way, this works thanks alot!!