Baker Xiao Posted August 15, 2017 Share Posted August 15, 2017 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! Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 15, 2017 Author Share Posted August 15, 2017 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? Quote Link to comment Share on other sites More sharing options...
jerome Posted August 15, 2017 Share Posted August 15, 2017 - 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 ;-) Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 15, 2017 Author Share Posted August 15, 2017 @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? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted August 15, 2017 Share Posted August 15, 2017 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 Quote Link to comment Share on other sites More sharing options...
Christoph Posted August 15, 2017 Share Posted August 15, 2017 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. Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted August 15, 2017 Share Posted August 15, 2017 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. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted August 15, 2017 Share Posted August 15, 2017 Yes correct! Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 15, 2017 Author Share Posted August 15, 2017 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. GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 15, 2017 Author Share Posted August 15, 2017 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? Quote Link to comment Share on other sites More sharing options...
Christoph Posted August 16, 2017 Share Posted August 16, 2017 7 hours ago, Baker Xiao said: It should be around 100 vertices per mesh. Is that still considered high for a mobile game? I don't think so, I confused in that post active and total meshes so the Edit I made is not correct Baker Xiao 1 Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 16, 2017 Author Share Posted August 16, 2017 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) 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? Quote Link to comment Share on other sites More sharing options...
jerome Posted August 16, 2017 Share Posted August 16, 2017 http://doc.babylonjs.com/classes/3.0/boundinginfo#islocked-boolean Quote Link to comment Share on other sites More sharing options...
Baker Xiao Posted August 16, 2017 Author Share Posted August 16, 2017 10 minutes ago, jerome said: http://doc.babylonjs.com/classes/3.0/boundinginfo#islocked-boolean oh interesting. that basically freezes the bounding box including translation though, right? we do want the bounding box to move along with the mesh, otherwise they might be culled during frustum culling. Quote Link to comment Share on other sites More sharing options...
jerome Posted August 16, 2017 Share Posted August 16, 2017 Yep this prevents the BBox computation. Then you can update it by your own computation (translation only) if you want Baker Xiao 1 Quote Link to comment Share on other sites More sharing options...
JCPalmer Posted August 16, 2017 Share Posted August 16, 2017 9 hours ago, jerome said: http://doc.babylonjs.com/classes/3.0/boundinginfo#islocked-boolean 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? Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted August 16, 2017 Share Posted August 16, 2017 Actually if the world matrix is frozen the bounding info won't change 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.