Jump to content

looking for advice on mobile performance


Baker Xiao
 Share

Recommended Posts

Hi everyone,

We've been working on a 3d mobile RPG game for a few weeks using Babylon.js and what we've been continuously struggling with is how challenging it is to keep 60fps on mobile.

Let me share the "game" here to show you what the scene looks like: https://xiaobaker.github.io/. Don't laugh. 

Some stats:

  • We have a ground mesh with standard material
  • We have 4 different kinds of environment objects, tree1, tree2, rock1, rock2. We created 50 meshes of them using mesh.createInstance(). 
  • We have up to around 10 active characters in the camera. Each character has 6 meshes. I don't think we can instance them because each of them will need its own bone animation (one day -_-). 
  • Under 50 draw calls in total

Running this on iphone 6 with ios 10.3.3 gives under 40 fps. We are hoping to keep it at 60 with even more stuff we want to add later on. 

I'm not super experienced with graphics optimizations, so could really use some advice here. A few optimizations I'm thinking of:

  • The environment objects never change position or anything. How can we optimize for that? They use different materials, so I can't just merge them. Also, freezeWorldMatrix() on instanced meshes seem to destroy the mesh. 
  • Currently in the inspector it shows that mesh selection is taking 9.4ms and render takes 13ms. How do we bring mesh selection down? Octree can bring mesh selection down to 4.5ms but still that's quite a bit. 
  • How do we debug what's happening in the 13ms of "render"? How do we debug webGL performance issues on mobile devices in general? 
  • Any general suggestions on how to optimize for a game like this? 

Any inputs are greatly appreciated! 

Link to comment
Share on other sites

OK guys we did some profiling and identified one major bottleneck being computing world matrix for all the meshes. This happens before evaluating mesh visibility, so basically every mesh that's enabled will go through this CPU intensive process. 

We wish we can freeze world matrix for these meshes however doing that on InstancedMesh seems to cause the meshes to disappear. Bug?

Besides that, we made a bit improvement by manually doing things like mesh.setEnabled(distanceFromPlayer < X); but that only helps so much. For things inside the camera fov, computing world matrix for every mesh every frame is still quite expensive. Any ideas how to optimize that? Is there a way to force a more efficient way of calculating bounding info for these meshes?

image.png

Link to comment
Share on other sites

- For meshes that won't never move, freeze all their WM

- If you know what meshes are always in the screen (or are surely at certain moment), select them manually (ex : the player is always in the frustum, maybe the enemy players that you spawn sometimes also), this will skip the selection algo for them.

- Instances reduce the number of draw calls what's a good optimization (for obstacles or landscape elements) but there's still a WM computation for each instance (so freeze it also). You could maybe try the Solid Particle System instead (only one WM computation and one draw call) to check if it improves the performance for the landscape elements. 

- Every FX GPU side consumes time, so the lower, the fastest

 

btw, the game looks nice ;-)

Link to comment
Share on other sites

@jerome thanks for the response! The issue I ran into with freezing WM was that the mesh disappears when i freeze the WM of an InstancedMesh. I can try to get a PG repro of that if it helps. If we can indeed freeze InstancedMeshes I'm sure it'll be a huge improvement. 

 

For some meshes that do need to move a lot, I'm wondering if there's any way to simplify the calculation of bounding info since that's the most expensive thing? Maybe force using a constant box value? 

Link to comment
Share on other sites

10 hours ago, Baker Xiao said:

For some meshes that do need to move a lot, I'm wondering if there's any way to simplify the calculation of bounding info since that's the most expensive thing? Maybe force using a constant box value? 

From looking at your game I think the terrain is rather regular, or in other words: Instead of doing any bounding box and collision detection you could just compute the distance between player/npc and the rocks, if it's too small -> consider it as some kind of collision. Maybe that could be faster.

However when looking at the stats it lists around 25k+ verts so your average mesh is around 100 (Edit: It seems that's not 100 but ~1000) vertices. That seems pretty high.

Link to comment
Share on other sites

44 minutes ago, Deltakosh said:

hello, you should be able to freeze isntances. Please provide a repro in the PG, I will fix it ;)

for meshes not moving a lot: why not freezing them and manually calling comptueWorldMatrix(true) which will force the computation

 

I think you mean manually calling freezeWorldMatrix().  ComputeWorldMatrix ignores force when frozen. freezeWorldMatrix does a compute.

Link to comment
Share on other sites

4 hours ago, Deltakosh said:

hello, you should be able to freeze isntances. Please provide a repro in the PG, I will fix it ;)

for meshes not moving a lot: why not freezing them and manually calling comptueWorldMatrix(true) which will force the computation

 

hmmmm.. that's indeed an interesting idea. for characters which sometimes stand still, we can probably just freeze them whenever they don't move. will try it out! thanks a lot for the suggestion. 

Link to comment
Share on other sites

4 hours ago, Christoph said:

From looking at your game I think the terrain is rather regular, or in other words: Instead of doing any bounding box and collision detection you could just compute the distance between player/npc and the rocks, if it's too small -> consider it as some kind of collision. Maybe that could be faster.

However when looking at the stats it lists around 25k+ verts so your average mesh is around 100 (Edit: It seems that's not 100 but ~1000) vertices. That seems pretty high.

It should be around 100 vertices per mesh. Is that still considered high for a mobile game?

Link to comment
Share on other sites

13 hours ago, Deltakosh said:

hello, you should be able to freeze isntances. Please provide a repro in the PG, I will fix it ;)

for meshes not moving a lot: why not freezing them and manually calling comptueWorldMatrix(true) which will force the computation

 

I just realized that this line is supposed do exactly this job for us, right? https://github.com/BabylonJS/Babylon.js/blob/6c8f2434f2f21b702b7cac8cffd788bcd33c7c85/src/Mesh/babylon.abstractMesh.ts#L1107 I guess it won't be very useful to repeat that logic in a similar way?

BTW, InstancedMesh can be frozen correctly. What we saw previously was a bug in our own logic, not Babylon. :) 

Now we have frozen all static meshes, which gave a significant boost. And we did some naive culling logic for most objects in the scene based on distance to player, which gave another boost. 

CPU bottleneck now looks like this: (which has been reduced a lot compared to before! yay)

image.png.dee1ee39cef0ee81380ba11c30548c23.png

Questions:

1) matrix multiply seems pretty heavy here. is it feasible to move those to GPU?

2) for meshes that do keep moving, update bounding info seems pretty CPU intensive. in our case we actually don't care too much about the bounding box, we'd rather treat it as a fixed sized box. is it reasonable to consider providing a way to override that behavior to save some CPU cycles?

Link to comment
Share on other sites

9 hours ago, jerome said:

Yeah, as soon as you get a performance improvement the next bottleneck shows up.  Wondering out loud, could the value of a boundingbox change when it is computematrix is frozen? Morphing?  Maybe bake this into freezeWorldMatrix?

Link to comment
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...
 Share

  • Recently Browsing   0 members

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