Good practice with useLoader(TextureLoader, ..) for web performance (preload ?)

I have this component which works

import {
} from "@react-three/fiber";
import { TextureLoader, SRGBColorSpace } from "three";

export default function EnsembleImage(...)
const couche1 = useRef();
const image = useLoader(TextureLoader, "/slide/nature_morte.avif");
   <mesh ref={couche1} position={[0, 0, 4]}>
        <planeGeometry ... />

I would like to accelerate the first print of this. The image is actually enormous and take a while to load. There’s also a custom shader as you can see. Actually, only a third of the image is visible on my website and the camera moves after to show it all. Is it possible to load a first picture on load which would represent only a third of the whole version, and then load the full picture when this second one is loaded ? I made this but it is not working:

useEffect(() => {

couche1.current.material.uTexture = useLoader(


Is it actually a good idea ? If yes, how to wait for the answer of useLoader ? It must come from this. How would you accelerate all this globally ? Quite an open question. I am here if you need more information. Thanks.

i would suggest you compress the image first, use squoosh for instance. and webp. also down-size it, 4k would imo be already too big for most usecases, try 2k.

then, useTexture instead of useLoader, because in threejs loading a texture will start the moment the camera “sees” it. if the texture isn’t shown first and the camera later bumps into it it will create runtime jank because texture upload is expensive. useTexture will pre-emptively gpu upload it. also all loader hooks have preload functions, so you can start downloading right away.

function EnsembleImage() {
  const texture = useTexture("/slide/nature_morte.webp")

1 Like

Thanks a lot

you are sure webp is better than avif ?

no, but i’ve never even heard of avif before.

Well, it seems avif format has gained adoption after all:

1 Like