In my app I am using React with vanilla ThreeJS. Recently I made a mistake and placed the following code in the react component itself instead of placing it in the effect:
let renderTarget = undefined;
if (WebGL.isWebGL2Available()) {
const size = renderer.getDrawingBufferSize(new THREE.Vector2());
renderTarget = new THREE.WebGLRenderTarget(size.width, size.height, {
samples: 8,
});
}
const composer = new EffectComposer(renderer, renderTarget);
As a result, this code was executed every time when component re-rendered, which was especially frequent when I tried to resize the window for testing.
After some time the app started temporarily crashing saying that: WebGLRenderer: Context lost., but it was also writing a lot of warnings like this: WARNING: Too many active WebGL contexts. Oldest context will be lost.. This particular warning was published when checking the availability of context here:
It creates the canvas every time it is called, which doesnât look like the most elegant thing to do considering that it crashes the renderer. So my question is, wouldnât it be better to create the same function that takes canvas as parameter instead of creating one each time it is called?
I donât think you need to recreate rendertargets on resize. They have a setSize method you can use for resizing. But if you do want to recreate it, you can/should call .dispose() on the old one first.
document.createElement( âcanvasâ ) is limited, you can only call it x times and the browser will crash. itâs because of the arbitrary limit that browsers set. you need to call it once globally, get the result and use that.
i wonder though, you are shooting yourself in the foot using react plain with three, instead of fiber. there is an entire eco system for three + react, it is larger than anything that exists in vanilla three. even your issue has been figured out https://github.com/pmndrs/three-stdlib/blob/89d7e63589d8e09879fd1737160b93e9f81c6389/src/misc/WebGL.ts three-stdlib is a pmndrs managed fork of three/examples/jsm with better stability and fixed anti patterns. isWebGL2Available is one of hundreds of things that will cause issues in functional programming.
but either way, the fix is
import { isWebGL2Available } from 'three-stdlib'
i would recommend you pull every jsm construct from stdlib as well.
Thank you very much. I canât use react-fiber because I have my own AR framework integrated into a 3D viewer with seamless switch between them. React-fiber doesnât cover my requirements there, or maybe my knowledge of it isnât sufficient.
As for the function. As I explained, I have no intention to use this function more than once, multiple calls were bug which is already fixed. My point was related to the function itself. Even if I call it once, why do I need an extra canvas to be created? It is just waste that results in a crash if not used as intended. Not the best coding style and I am surprised to see things like that in ThreeJS.
In order to create a new instance of EffectComposer you have to pass WebGLRenderer as a parameter, which means that the renderer has to be created in advance. The renderer does have a canvas element in it. So, why canât we check the context using the existing rendering canvas instead of creating one every time? Something like this: