shrimpwagon

Understanding SceneOptimizer

Recommended Posts

Need some serious guidance with SceneOptimizer.
 
I promise I have thoroughly read through the wiki page https://github.com/BabylonJS/Babylon.js/wiki/How-to-use-SceneOptimizer-tool
 
I believe I have included the scene optimizer javascript correctly.
 
Not sure if I am implementing the code correctly.
 
Basically, I'm trying to downgrade rendering on slower devices (eg Samsung Galaxy S4).
 
Using this code below, I never see anything coming through on the console.log when testing on my Linux Debian laptop in Chrome 38.

Javascript include:
 

<script src="/libs/babylon/babylon.1.14.js"></script><script src="/libs/babylon/babylon.sceneOptimizer.js"></script>

Code:
 

var _canvas = document.getElementById("renderCanvas");var _engine = new BABYLON.Engine(_canvas, true);BABYLON.SceneLoader.Load("", "babylon/room.babylon", _engine, function (scene) {	// Wait for textures and shaders to be ready	scene.executeWhenReady(function () {		// Optimize scene rendering		BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.HighDegradationAllowed(),			function() {				console.log('FPS target reached');			}, function() {				console.log('FPS target NOT reached');			}		);            // ...

I've tried changing out High to Low and Medium but I'm never seeing the log. Leading me to believe I'm not implementing right. Also not sure, even if I get a log from it that it is degrading.

I'm unable to find any other examples from a Google search.

Can someone provide a very very simple working example where it will just auto degrade whenever the frame-rate starts dropping below 30?

Thank you so much. And thank you for such a brilliant library. I'll share my project when it's done.

Share this post


Link to post
Share on other sites

Your code seems correct. Do you wait enough time? Process could be long because by default SceneOptimizer waits 2s between passes.

 

You can define tracking duration like this:

var options = BABYLON.SceneOptimizerOptions.HighDegradationAllowed();options.trackerDuration = 2000; // ms

Share this post


Link to post
Share on other sites

Hmmm.... I definitely waiting the 2 seconds.
 
Changed the code but I still don't see anything in the console.log.
 

// Optimize scene renderingvar scene_optimizer_options = BABYLON.SceneOptimizerOptions.HighDegradationAllowed();scene_optimizer_options.trackerDuration = 2000;BABYLON.SceneOptimizer.OptimizeAsync(scene, scene_optimizer_options,	function() {		console.log('FPS target reached');	}, function() {		console.log('FPS target NOT reached');	});

Share this post


Link to post
Share on other sites

Ok, pinpointed a few things.

 

Looks like the above code needs to be before scene.executeWhenReady.

 

When I did this it was trying to fire however I was still getting an undefined function error.

 

In babylon.sceneOptimizer.js line 316. The scene variable does not have the getEngine function as I did a console.log on it.

 

 

// Scene optimizer toolvar SceneOptimizer = (function () {    function SceneOptimizer() {    }    SceneOptimizer._CheckCurrentState = function (scene, options, currentPriorityLevel, onSuccess, onFailure) {        // TODO: add an epsilon        if (scene.getEngine().getFps() >= options.targetFrameRate) { // throws error here because the scene var doesn't have a getEngine function            if (onSuccess) {                onSuccess();            }             return;        }
So I just changed it to use BABYLON.Tools

 

// Scene optimizer toolvar SceneOptimizer = (function () {    function SceneOptimizer() {    }    SceneOptimizer._CheckCurrentState = function (scene, options, currentPriorityLevel, onSuccess, onFailure) {        // TODO: add an epsilon        if (BABYLON.Tools.GetFps() >= options.targetFrameRate) {            if (onSuccess) {                onSuccess();            }            return;        }
But still very slow on my Galaxy S3 in chrome. Getting only 7 FPS. I've tried High, Medium and Low degradation. Is my phone just that old and slow?

I only have 1 camera, 1 light source and 4 planes. One plane has a texture.

On my Galaxy S3 on Firefox I'm getting somewhere between 20 and 30 FPS. Better. But the arc camera is all jacked up. Most the time only half the camera shows up and when I pinch or unpinch the scene flys away. It like over zooms really quickly.

Share this post


Link to post
Share on other sites

Hey SW,

 

It sounds as though it might be your scene objects.  Although they may appear as simple objects and elements, it's hard to say whether there is an issue with the geometry, your light, texture, and/or camera.  Without knowing the properties of these elements, it's impossible to pinpoint the problem.  If you post the files, I'm certain someone could quickly solve this.  Otherwise, everything posted here thus far appears to be in order.  Are your scene elements all declared using JavaScript, or was an external application used to generate them?

 

Cheers,

 

DBawel

 

My bad - it's obvious you are loading a .babylon scene file.  But what program and exporter did you use?

Share this post


Link to post
Share on other sites

Great. Making progress. I'm using babylon.2.0-alpha.js and the scene optimizer seems to be working ... sort of.

My console.log is firing in Chrome on my Linux. But when I'm on my Galaxy 3 I'm still having weird issues.

I'm getting the engine.getFps() and just updating a span tag to show it.

For about 8 secs it shows 60 fps which can't be right because it is slow as molasses.

When I don't set the trackerDuration (default 2000) it reads, "Reached target FPS." So it IS firing. And I guess is true because it's showing 60 fps, but again, it's super slow. Then after about 3 or 4 more seconds tanks to 6 fps.

If I set trackerDuration to 10000, I never see a message at all. It's doesn't say it's reached or not reached. It starts out showing 60 fps, which isn't true, then drops to 7 fps and the scene never downgrades nor does it alert me that either of the callbacks fired for the target fps.

Share this post


Link to post
Share on other sites

I have tried to apply the SceneOptimizer which results in a great part of the meshes in the scene become invisible. They are still there as collision still are being handled, but they are not visible. Doesn't matter if the degradation level is low, moderate or high. The meshes that "disappear" are for the most part bigger simple structures like walls, floors and ceiling with no textures assigned. Do anyone know why this is happening?

 

Screenshots before and after the SceneOptimizer is called:

 

Before

 

After

Share this post


Link to post
Share on other sites

You must create your own optimizer option and adjust the max FPS (here 40) trigger the optimizer if the minimum limit.

default limit is 60 FPS, if your FPS go below 60, the optimizer starts optimize your scene.

To see what happens, look in the debugLayer. you can see what is deactivated when the sceneOptimiser started optimize your scene.

 

Here is what I use as a custom option that works very well:

 

function YourOptimizer() {var result = new BABYLON.SceneOptimizerOptions(40, 3000);result.optimizations.push(new BABYLON.TextureOptimization(0, 256));result.optimizations.push(new BABYLON.PostProcessesOptimization(1));result.optimizations.push(new BABYLON.LensFlaresOptimization(2));result.optimizations.push(new BABYLON.ShadowsOptimization(3));result.optimizations.push(new BABYLON.RenderTargetsOptimization(4));result.optimizations.push(new BABYLON.ParticlesOptimization(5)); result.optimizations.push(new BABYLON.RenderTargetsOptimization(6));    result.optimizations.push(new BABYLON.HardwareScalingOptimization(7, 4));return result;}
 

Use:

BABYLON.SceneOptimizer.OptimizeAsync(scene, YourOptimizer());
 

Share this post


Link to post
Share on other sites

After using the newest versions.

When I put all that inside of scene.executeWhenReady it doesn't fire at all ever.

I think the scene optimizer has its own scene ready method.

 

I know it has been very long, but I am having the same issue and I would like to know if there is a way to fixe it.

Here is a part of my code.

When running this code, I only get the "success !", but the framerate is not reached, and when I initiate the SceneOptimizer inside scene.executeWhenReady(), I never get anything inside the console.log...

I also tried putting the SceneOptimizer inside runRenderLoop(), it looks like it's working, but it seems wrong (it keeps sending dozens of messages of success/fails)... 

BABYLON.SceneLoader.Load("somePath", "SomeName", engine, function(scene){	BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.LowDegradationAllowed(30, 2000),		function(){			console.log("success !");			}, function(){			console.log("failed !");			});	scene.executeWhenReady(function(){		//setting my scene properties		});	    }, function (progress){                //Do stuff            });}

Yeah, I know the identation is messed up... Oh, and BTW, I am using BabylonJS v2.2.0-alpha.

Share this post


Link to post
Share on other sites

Well, after a lot if trials and errors, sounds like I found the solution by using defered and promises.

$.when(SomeSceneLoadingFunctionReturningPromise()).done(function(){	scene.createOrUpdateSelectionOctree(engine);	BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.LowDegradationAllowed(30, 10000),		function(){					//Optimization successful				},		function(){					//Optimization failed				});	engine.runRenderLoop(function(){		if (scene.isReady()){			scene.render();		}	});});

It could be nice to include in the doc or the tutorial that the SceneOptimizer or the Octree should be run/updated once the scene is loaded and before it's rendered, because I couldn't find anything telling that anywhere... (apart from the source code of the OCTREE demo)
Also, scene.executeWhenReady doesn't work for the SceneOptimizer, as it looks like it never fires up, and specifying the SceneOptimizer before the scene has fully loaded seems to induce a "premature optimization" meaning that the failed/success is returned too soon (even before the scene has started rendering some times)...

I hope this can answer some questions.

 

Also, I found out why  larsiii23 was getting "invisible" mesh. It's because new meshes created by the SceneOptimizer when calling MergeMeshesOptimization are not added to the octree, thuse are ignored when rendering the scene.

When running a SceneOptimizer, you should remember to run createOrUpdateSelectionOctree() while doing it.
It should be added into the MergeMeshesOptimization source code when meshes are merged. I am gonna create an issue on github to see if they could add it.

Share this post


Link to post
Share on other sites

Oh yeah, it can be run once the first frame has been rendered.

However, waiting for the scene to be fully loaded seems mandatory. As the SceneOptimizer starts "optimizing" as soon as it's said to, even if there is no real scene to optimize yet (as it is still loading).

The fact that trying to run the SceneOptimizer inside ExecuteWhenReady does not work is good to know though.

I am glad to help, I would be happy to improve the doc  ^_^

Share this post


Link to post
Share on other sites

Perhaps I misunderstood the way it's supposed to be used, but apparently setting UpdateSelectionTree with something like this :

var mergeMeshOpti = new BABYLON.MergeMeshesOptimization(priority);mergeMeshOpti.UpdateSelectionTree = true;

Does not seem to be working, I tried looking at the source code but it does not seem to be going into get or set when defining the new property. The only way I found to set it to true is to set it manually in the source code. I am looking into it as I am writting this.

 

[EDIT] Nevermind, I am a bit slow this morning, it should be set as a "general" Babylon option like this :rolleyes:  :

BABYLON.MergeMeshesOptimization.UpdateSelectionTree = true;

It could be cool to be able to set it up like so though :

new BABYLON.MergeMeshesOptimization(priority, true);

Thuse, changing the prototype to :

BABYLON.MergeMeshesOptimization(priority (number), UpdateSelectionTree (boolean))

In case someone would want to handle octree update manually on some MergeMeshesOptimization, and automatically on some others, dunno why someone would want to do that, but you never know what twisted schemes can come out of a dev's tormented mind...

Share this post


Link to post
Share on other sites

Well, it's done, I am using babylon.max.js, and I modified the line 29627 to :

function MergeMeshesOptimization(priority, updateSelectionTree) {
And the line 29680 to :
[EDIT]Edited out, my code was bad, I was tired and had a brainfart, please download the latest build (currently in alpha) if you want this to work. ;-)
If you want to add it natively or if someone wants to customize his Babylon version ^_^

Of course, the "specific" setting has the priority over the "global" one.

So, now if someone wants all the MergeMeshesOptimization to behave the same and update octree, he can set UpdateSelectionTree with :

BABYLON.MergeMeshesOptimization.UpdateSelectionTree = true;
And if he wants the optimizer to behave differently on a specific MergeMeshesOptimization pass, he can set up his MergeMeshesOptimization like so :
myOptimizer.optimizations.push(new BABYLON.MergeMeshesOptimization(priority, true/false));

Share this post


Link to post
Share on other sites

have some issue too with OptimizeAsync

if i set it be outside render loop is not triggered if i set it inside render loop it is, is that correct?

// not working

BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.ModerateDegradationAllowed(25, 2000),	function(){	
		if ( mydebug ) {
			console.log("Optimization successful");
		}
	}, function(){ 
		//Optimization failed
	});

engine.runRenderLoop(function () {

	scene.render();
    engineFps.innerHTML = engine.getFps().toFixed() + " fps";
    
});
engine.runRenderLoop(function () {

	BABYLON.SceneOptimizer.OptimizeAsync(scene, BABYLON.SceneOptimizerOptions.ModerateDegradationAllowed(25, 2000),	function(){	
		if ( mydebug ) {
			console.log("Optimization successful");
		}
	}, function(){ 
		//Optimization failed
	});
	

    scene.render();
    engineFps.innerHTML = engine.getFps().toFixed() + " fps";
    
});

 

Share this post


Link to post
Share on other sites

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...

  • Recently Browsing   0 members

    No registered users viewing this page.