Jump to content

Properly reinitializing BABYLON.Engine


croustibat
 Share

Recommended Posts

Hi!

I'm developing a web app with a 3d viewport made with babylon js.

It's initialized on a canvas object.

In my app, it's possible that the viewport is completely destroyed and I need to flush every BABYLON objects instantiated.

It's possible then that the canvas is recreated and I need to build a new scene again (on a new engine).

There are two functions, one called when the canvas dom object is created and rendered, the other is called when it's destroyed.

After the canvas is created, I do this:

  function CreateEngine(_canvas) {    var engine = new BABYLON.Engine(_canvas, true);    window.addEventListener("resize",function() {      engine.resize();    });    return engine;  };  var engine = CreateEngine(mycanvas);  var scene = new BABYLON.Scene(engine);  scene.clearColor = new BABYLON.Color3(0.97,0.97,0.97);  console.log("Created a scene");  engine.runRenderLoop(function(){    scene.render();  });

Then when the canvas is destroyed I do this:

  if (engine !== null) {    console.log("Scrapping engine...");    currentScene.dispose();    delete currentScene;    engine.stopRenderLoop();    engine.dispose();    delete engine;    engine = null;  }

First canvas creation works fine

No error is raised when I destroy it.

But, when I create the canvas again, here is what I get:

 

BJS - [12:37:03]: Unable to compile effect: r._ErrorEnabled @ babylon.2.1.js:4t._prepareEffect @ babylon.2.1.js:15t._prepareEffect @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadFragmentShader @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadVertexShader @ babylon.2.1.js:15t @ babylon.2.1.js:15a.createEffect @ babylon.2.1.js:5r.isReady @ babylon.2.1.js:15r.render @ babylon.2.1.js:11t.render @ babylon.2.1.js:13t.render @ babylon.2.1.js:9t.render @ babylon.2.1.js:9t._renderForCamera @ babylon.2.1.js:10t._processSubCameras @ babylon.2.1.js:10t.render @ babylon.2.1.js:10(anonymous function) @ scene.js?56edd9bde385c4f695f9d16bb8263e0a27da1ee0:53a._renderLoop @ babylon.2.1.js:5(anonymous function) @ babylon.2.1.js:5

babylon.2.1.js:4 BJS - [12:37:03]: Vertex shader:defaultr._ErrorEnabled @ babylon.2.1.js:4t._prepareEffect @ babylon.2.1.js:15t._prepareEffect @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadFragmentShader @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadVertexShader @ babylon.2.1.js:15t @ babylon.2.1.js:15a.createEffect @ babylon.2.1.js:5r.isReady @ babylon.2.1.js:15r.render @ babylon.2.1.js:11t.render @ babylon.2.1.js:13t.render @ babylon.2.1.js:9t.render @ babylon.2.1.js:9t._renderForCamera @ babylon.2.1.js:10t._processSubCameras @ babylon.2.1.js:10t.render @ babylon.2.1.js:10(anonymous function) @ scene.js?56edd9bde385c4f695f9d16bb8263e0a27da1ee0:53a._renderLoop @ babylon.2.1.js:5(anonymous function) @ babylon.2.1.js:5
babylon.2.1.js:4 BJS - [12:37:03]: Fragment shader:defaultr._ErrorEnabled @ babylon.2.1.js:4t._prepareEffect @ babylon.2.1.js:15t._prepareEffect @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadFragmentShader @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadVertexShader @ babylon.2.1.js:15t @ babylon.2.1.js:15a.createEffect @ babylon.2.1.js:5r.isReady @ babylon.2.1.js:15r.render @ babylon.2.1.js:11t.render @ babylon.2.1.js:13t.render @ babylon.2.1.js:9t.render @ babylon.2.1.js:9t._renderForCamera @ babylon.2.1.js:10t._processSubCameras @ babylon.2.1.js:10t.render @ babylon.2.1.js:10(anonymous function) @ scene.js?56edd9bde385c4f695f9d16bb8263e0a27da1ee0:53a._renderLoop @ babylon.2.1.js:5(anonymous function) @ babylon.2.1.js:5
babylon.2.1.js:4 BJS - [12:37:03]: Defines: r._ErrorEnabled @ babylon.2.1.js:4t._prepareEffect @ babylon.2.1.js:15t._prepareEffect @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadFragmentShader @ babylon.2.1.js:15(anonymous function) @ babylon.2.1.js:15t._loadVertexShader @ babylon.2.1.js:15t @ babylon.2.1.js:15a.createEffect @ babylon.2.1.js:5r.isReady @ babylon.2.1.js:15r.render @ babylon.2.1.js:11t.render @ babylon.2.1.js:13t.render @ babylon.2.1.js:9t.render @ babylon.2.1.js:9t._renderForCamera @ babylon.2.1.js:10t._processSubCameras @ babylon.2.1.js:10t.render @ babylon.2.1.js:10(anonymous function) @ scene.js?56edd9bde385c4f695f9d16bb8263e0a27da1ee0:53a._renderLoop @ babylon.2.1.js:5(anonymous function) @ babylon.2.1.js:5
babylon.2.1.js:4 BJS - [12:37:03]: Error: Cannot read property 'createShader' of null

So, I guess I don't reset the scene properly right?

Link to comment
Share on other sites

Hi Temechon!

I'm building my app using the Meteor framework.

In usual meteor patterns, dom elements can get created/destroyed quite often.

But as you say, I think I'm going to hide/show the canvas, and just flush the meshes, textures, materials and cameras, it should do the trick.

I thought there was a quick/efficient way of doing all that stuff by disposing the engine instance. But sadly, disposing and deleting the engine seems to make me unable to create a new one.

Link to comment
Share on other sites

Thanks for pointing the right place.

From what I see of the source, dispose() already seems to dispose all the scenes, stops the render loop, removes any event listeners, releases the audio engine, does something with webgl (probably reset it).

Everything seems to be properly destroyed, so that's strange that I can't dispose an engine object and create a new one, then setting a new render loop with a new scene without my program to fail.

My code right now is a bit messy, I will try to reproduce that behaviour in a babylon playground, just for curiosity. And for science.

Link to comment
Share on other sites

  • 2 weeks later...

Hi again,

I had the time to make some testing around those concerns.

Starting form fresh, with a simple (and clean ;) ) project, I could make the dom destruction/reconstruction work fine with Babylon engine. But after a few cycles of creating a canvas DOM node, creating a babylon engine, building up a dummy scene, disposing the engine, destroying the canvas node, I ended up with a strange chrome warning saying there were too many webgl contextes. This seems to be a known issue inherent to js garbage collection. For me that was the final proof saying that this is definitely the wrong pattern here, as Temechon said.

And reinitializing the scene is simple by doing so:
engine.stopRenderLoop();engine.clear(BABYLON.Color3.Black(),false,false);window.removeEventListener('resize');if (engine.scenes.length!==0) {    //if more than 1 scene, while(engine.scenes.length>0) {    engine.scenes[0].dispose();}

I couldn't observe any memory leak doing this dozens of time, it seems pretty reliable.

I will keep developing with that method, which is simple and clean.

Link to comment
Share on other sites

  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...