So I have this huge ground mesh and I wanted to make it more interesting by adding some grass spots over it. I initially used a 3D model - I loaded the model and created around 1000 instances, and spread them around the perimeter. I then realised that maybe using grass sprites will not only do the same job but will be cheaper too. I loaded the sprites but for some reason, my total frame increased by ~5ms. I
know that I have a “limit” of 16ms for optimal performance so it just seemed strange that using sprites turned up so expensive. I checked the example PG(https://www.babylonjs-playground.com/#9RI8CG#0) on the sprites how-to-page of babylon.js and surprisingly the scene has 2000 loaded trees and everything runs in ~2ms. So I must be doing something wrong, but I have no idea what. My sprites are 64x64 and the source image is only 12KB (I dont know if that even matters but I reckoned I should mention it).
Hey @Djani_Daud, do you have a playground that we can look at to help trouble shoot?
I do not have a playground but here is a link to the scene:
http://interactivetable-com.stackstaging.com/game/optimised.php
Here is a screenshot (in case it turns out that I am the only one who experiences the performance drop)
I will try to replicate it in a playground and I will share the link ASAP.
Can you see the same performance drop here where 2000 sprites are in use ? https://playground.babylonjs.com/#9RI8CG#0
Also in your case instances might be a bit faster and even use a smaller buffer if the geometry is really small
The scene you have sent me runs in ~1.2ms. That is what surprises me the most. I am starting to believe that the problem comes from the source image that I am using.
So I tried using another texture… nothing changed. I also created a playground and filled it with 2000 sprites of my texture and the performance was great - around ~2ms. So this means that something is wrong in the scene that I am working on.
Now the question is, am I the only one who experiences the performance drop, because if that is the case, then I would continue using sprites. Here is the link to my scene PolyKingdom.
I get about 27-30fps. Turning off sprites in the inspector results in 60fps. There is definitely an error or issue somewhere, as you have a relatively low amount of sprites.
I had a project(now gone). With 30.000 objects like trees, rocks and vegetation very densely populated.
I used a worker to determine the distance from the player to the objects. If the objects were farther away than some threshold, I used sprites, otherwise I used instances. And that project could handle thousands of sprites and hundreds of instances at a smooth 60fps. Have you tried replacing your sprite with the tree one from BabylonJS?
The thing is that the Babylon sprites are user-friendly and let you do a number of things (like setting the visibility on a per-frame basis for each sprite) that leads to reconstructing the vertex buffer each frame: in your PG, most of the time is spent in the Sprite.render
function because of that.
Optimizing sprite rendering has already been discussed in this thread SpriteManager WebGL transparency draw issues and improves and a PR has been alluded to but never created.
So I found the reason why the scene is so expensive:
When I was building the scene, I wanted to give the field a bit more variety so I randomized the width and height of each grass sprite. I commented that part of the code and the scene now runs in ~1ms instead of ~6ms! I do not know if this is a bug, or what causes this behaviour but maybe someone should take a look at it.
I recreated the bug in a PG:
https://www.babylonjs-playground.com/#9RI8CG#161
Note that:
To recreate the bug I used: https://www.babylonjs-playground.com/#9RI8CG#0 . The scene runs in ~1ms (as expected).
I then added the 3 lines of code that randomize each sprite’s size and the scene started running in ~4ms.
However, when I commented out the 3 lines of code, the scene was still running in ~4ms even though I was not changing the sprite size. I find this to be extremely strange
If you change the sprite size manually, it also doesn’t appear to cause any slowdown. Perhaps all of them being a different size is the problem, as all the individual instances might require some different computation that isn’t needed when all use the same scaling factor? Or perhaps some optimization can be applied when they’re identical that doesn’t work when they aren’t?
I only took a brief look, so I don’t know for sure
Lose the .toFixed(2)
in you random number generator and you will see a difference.
By the way you could use BABYLON.Scalar.RandomRange(0.4, 1)
Note: adding toFixed(2) to this also slows things down. Numbers are faster than strings.