Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clean up Threejs WebGl contexts

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.

like image 276
kassette91 Avatar asked Feb 04 '14 09:02

kassette91


People also ask

How do I get rid of WebGL context?

Refreshing a webpage should free all resources. There is no official way to dispose of a WebGL context just like there's no official way to dispose an Image or a <video> or pretty much anything else in JavaScript.

How do you dispose of 3js?

Whenever you create an instance of Texture, three. js internally creates an instance of WebGLTexture. Similar to buffers, this object can only be deleted by calling Texture. dispose().

What is a scene in three js?

Scenes allow you to set up what and where is to be rendered by three. js. This is where you place objects, lights and cameras.


3 Answers

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;
like image 178
Konstantin Eletskiy Avatar answered Oct 19 '22 17:10

Konstantin Eletskiy


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);
}
like image 44
theHacker Avatar answered Oct 19 '22 17:10

theHacker


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.

like image 3
kraag22 Avatar answered Oct 19 '22 17:10

kraag22