26

I have a problem while cleaning up my WebGl-Scenes. I'm using Three.js with a WebGlRenderer. In my application I have to change the views quite often and therefore need to render new scenes all the time. Uptil now I destroy and reinitialize the entire Threejs scene. After switching the scenes about 15 - 20 times I get following warning:

WARNING: Too many active WebGL contexts. Oldest context will be lost.

After switching a couple of times more the context is lost completly and the application crashes.

Is there a way to destroy the current WebGl context, when cleaning up? Or does the WebGlRenderer always create a new WebGl context when being instantiated?

I'm using Three.js R64.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
kassette91
  • 275
  • 1
  • 3
  • 6
  • 2
    Unless you have a split-screen system for rendering, one context is sufficient. It's not intended to discard and create context frequently. – Dragan Okanovic Feb 04 '14 at 09:31

3 Answers3

21

I've got same problem, but i couldn't solve it using SPA, because of requirements.

There is .forceContextLoss() method in WebGLRenderer (rev 71, maybe was early) for this situations.

So, my code in 'deallocate' method is somemethig like

_self.renderer.forceContextLoss();
_self.renderer.context = null;
_self.renderer.domElement = null;
_self.renderer = null;
  • This works. Although it's undocumented in r74, it is there https://github.com/mrdoob/three.js/blob/r74/src/renderers/WebGLRenderer.js#L308 – ElDog Feb 21 '16 at 21:04
  • This works for me also. At the same time, it worth mention that the extension “WEBGL_lose_context” simulates webgl context loss, it doesn't mean the browser **actually frees the resources on the GPU allocated** by the webgl context, but may just pretend that it did. There was a discussion thread on [Kronos](https://www.khronos.org/webgl/public-mailing-list/public_webgl/1611/msg00017.php). – Farside Dec 11 '17 at 15:54
  • This is not supported on IE11. My SPA worked beautifully with Chrome but with IE11 I started see quick performance degeneration. With IE I guess only option is to have singleton WebGL context (in ThreeJS case the WebGLRenderer) and reuse it throughout the session. – Sami Viitala Aug 17 '18 at 12:47
  • 1
    Still useful in 2020 (THREE.js Release 113). – steveOw Dec 15 '20 at 22:45
14

You can keep the same renderer for different scenes. The renderer does not care what scene it will render. You can supply a different Scene everytime you call render() if you like.

// instantiate only once and keep it
var renderer = new THREE.WebGLRenderer();

// current scene and camera. Switch whenever you like
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(...);
fillScene(scene);

// rendering always uses current scene
function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

/* ... 
 *   somewhere in your application
 * ...
 */
if(condition) {
  // switch scene
  scene = new THREE.Scene();
  fillOtherScene(scene);
}
theHacker
  • 3,984
  • 1
  • 19
  • 34
3

You should create and use only one WebGlRenderer. In my SPA (single page application) I had weird problem with camera/scene in THREE.js after few redirects. It was because WebGlRenderer was created every time when one particular page was rendered. There was no error in console log (only the warning you wrote). Bug appeared as change in camera position and problems with rendering.

kraag22
  • 3,340
  • 3
  • 29
  • 37
  • hey! kraag, i am developing threejs using angular directive, i have problems with memory leak when i redirect it, u manage to solve ur problem? how do you clean up threejs? – Tim May 15 '15 at 09:28
  • as I wrote. Use only one WebGlRenderer – kraag22 May 15 '15 at 14:09
  • Yup, but I need view which is the threejs rendered into other view (which use d3) and then I need to reinitialize the threejs, so I need a clean way to remove them or should I just hold the rendered once initialised? And keep it for future use? – Tim May 15 '15 at 14:26