croustibat Posted October 1, 2015 Share Posted October 1, 2015 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 fineNo 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:5babylon.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:5babylon.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:5babylon.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:5babylon.2.1.js:4 BJS - [12:37:03]: Error: Cannot read property 'createShader' of nullSo, I guess I don't reset the scene properly right? Quote Link to comment Share on other sites More sharing options...
Temechon Posted October 1, 2015 Share Posted October 1, 2015 Hello, Why do you have t odelete the whole canvas each time ? Can't you just set it to display:none, or set it invisible ? Quote Link to comment Share on other sites More sharing options...
croustibat Posted October 1, 2015 Author Share Posted October 1, 2015 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. Quote Link to comment Share on other sites More sharing options...
Temechon Posted October 1, 2015 Share Posted October 1, 2015 You can just hide the canvas and call scene.dispose(), then create a whole new scene. It should work this way. RaananW 1 Quote Link to comment Share on other sites More sharing options...
croustibat Posted October 1, 2015 Author Share Posted October 1, 2015 You can just hide the canvas and call scene.dispose(), then create a whole new scene. It should work this way. Thanks Temechon, I'll give it a try Quote Link to comment Share on other sites More sharing options...
croustibat Posted October 1, 2015 Author Share Posted October 1, 2015 Temechon, thanks again, this made the trick (hiding the canvas).But still, I feel frustrated about not knowing what's behind engine.dispose()!Anyway, problem solved! Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 1, 2015 Share Posted October 1, 2015 This is the power of open source framework: you can watch the code https://github.com/BabylonJS/Babylon.js/blob/master/src/babylon.engine.ts#L2165 Quote Link to comment Share on other sites More sharing options...
croustibat Posted October 2, 2015 Author Share Posted October 2, 2015 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. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 2, 2015 Share Posted October 2, 2015 Lol yes please Quote Link to comment Share on other sites More sharing options...
croustibat Posted October 12, 2015 Author Share Posted October 12, 2015 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. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 12, 2015 Share Posted October 12, 2015 That's a good news Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted April 20, 2017 Share Posted April 20, 2017 Mobile space remains mostly uncharted Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.