pmndrs / drei

🥉 useful helpers for react-three-fiber
https://docs.pmnd.rs/drei
MIT License
8.16k stars 666 forks source link

Cached useEnvironment gainmap texture no longer works after renderer lost context #2023

Closed AaronClaes closed 1 month ago

AaronClaes commented 1 month ago

Problem description:

I use a gainmap for my environment files to prevent large HDR files.

<Environment files={[`/hdri/potsdamer_platz_1k.jpg`]} />

My application has pages with and without the Canvas element. When the Canvas loads the first time, everything works fine. But if I go to a page without the canvas, and then return to a page with the Canvas, the gainmap no longer works.

Relevant code:

I noticed this snippet in the source code:

// Gainmap requires a renderer
if (extension === 'webp' || extension === 'jpg' || extension === 'jpeg') {
        loader.setRenderer(gl)
}

So I assume once the renderer loses context, the texture breaks.

Suggested solution:

I managed to solve the problem by adding the following snippet to the useEnvironment hook:

useLayoutEffect(() => {
    // Only required for gainmap
    if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;

    function clearGainmapTexture(event) {
        useLoader.clear(loader, multiFile ? [files] : files);
    }
    gl.domElement.addEventListener("webglcontextlost", clearGainmapTexture);
}, [files, gl.domElement]);

I clear the cached texture if the context is lost, so they will reload with the current renderer.

I don't know if this is a good solution in general and if there are better ways to deal with this problem. I also cannot clear the event listener because it is removes it before the webglcontextlost event triggers.

I can open a PR if this solution is fine, feedback is welcome!

github-actions[bot] commented 1 month ago

:tada: This issue has been resolved in version 9.108.4 :tada:

The release is available on:

Your semantic-release bot :package::rocket: