how to speed up hundreds of sprites?

BlitzMax Forums/MiniB3D Module/how to speed up hundreds of sprites?

Midimaster(Posted 2016) [#1]
I'm creating a racing game on an 3D-terrain with a lot of trees on it. The trees are only sprites all created from the same pixmap with 256x256pix. Without the trees the game needs 1msec per flip-cycle. Now I'm positioning 300 trees and the performance goes down to 45msec per flip. What do I wrong? Is there a way to speed up a lot of same sprites?

this is my code:
	Local oak:TSprite=LoadSprite(imagePfad + "oak.png",2)
	Oak.SpriteViewmode 1
	oak.HandleSprite 0,-1
	Oak.ScaleSprite 1,3
'
	For Local i%=0 To 300
		Oak.ScaleSprite Rnd(1,3),Rnd(1,3)
		Local loc:TEntity=CopyEntity(oak)
		loc.Scaleentity Rnd(1,2),Rnd(1,2),0
		loc.PositionEntity Rnd(300),0,Rnd(300)
		loc.Entitycolor 155+Rnd(100),155+Rnd(100),0
	Next


The performance is also down even when not a single one of the trees is in the camera view.


Cocopino(Posted 2016) [#2]
I assume this piece of code is not in your main loop, otherwise, problem fixed ;)

What happens if you disable alpha on oak.png, does that speed the program up?
Or using a 64x64 png?


Midimaster(Posted 2016) [#3]
1. Of course sprites are created before main loop starts.
2. Changing blendmode did not speed up.
3. changing pixmap size to 64x64 did not speed up

I do not understand the fall off... 300 trees are only 600 triangles. A single 3D modell with 600 triangles would be called "low-poly" and would not cause problems....

Is there a problem with 300 surfaces?

How to optimize something like that? Would it be useful to combine all trees to one mesh/surface?

(I have to tell, that the graphic device is a Nvidia Gforce 7300gs. Not really a new one....)


angros47(Posted 2016) [#4]
In OpenB3D and in iMiniB3D it's possible to use batch sprites, that are much faster because only one surface is used.


Cocopino(Posted 2016) [#5]
Yes you could try OpenB3d, it could be (best case scenario) you'll only need to change your imported module so changing back and forth will be easily possible.

Still a weird problem though, especially if the sprites are not even in view. Why should that bother your videocard at all...

Maybe change the sprites for 4 polygon cross trees, and join them by using the Addmesh() command? I think that should mimic having a single, one surfaced mesh.


Kryzon(Posted 2016) [#6]
I think it's bothering the CPU.
The sprites are not in view but they're all still tested for visibility at every RenderWorld.

Using AddMesh like suggested should improve it, since it'll be a single visibility test instead of 300.


Midimaster(Posted 2016) [#7]
it looks like it is not the CPU but the graphic card. When I hide all trees, the CPU works on nearly 100% and the game runs perfect. When I show all trees the game runs like slow motion, but the CPU has 50% prozessor load...

All the trees need to face towards the camera. Sprite ViewMode=1. So it is difficult to replace it with single surface, or? Will this single surface also have this feature?

It looks like MidiB3D does not really check, whether a tree is in camera view or not. I recognize that performance also goes down, when all trees are behind camera.

test results:

000 trees with HideEntity() need 1msec
400 trees with HideEntity() need 3msec
400 colored sprites without Texture need 16msec
400 textured sprites need 47msec

I read something about VBOs. Could they help me?

I read something about Klepto's TFastSprite. Is it stillvaiable? He was not here in forum the last threee years...

I found this: http://www.blitzbasic.com/Community/post.php?topic=68860&post=769657

I now try to build a "in sight check" by my own. I think it will be a workaround but not a solution.


Cocopino(Posted 2016) [#8]

it looks like it is not the CPU but the graphic card. When I hide all trees, the CPU works on nearly 100% and the game runs perfect.


CPU could still be part of the problem though: it will then skip checks like EntityInView.


Sprite ViewMode=1. So it is difficult to replace it with single surface, or?


Yep, which is why I suggested using cross polygons ;)


TFastSprite: I think OpenB3d already has something similar built in, you could try that.


angros47(Posted 2016) [#9]
The fastest way to render many sprites, all facing the camera, is using point sprites, but not all opengl versions support them


grable(Posted 2016) [#10]
I can assure you its not the GPU that is the limiting factor here.
Its MiniB3D itself that just doesnt like too many Entities, since it does a lot of work for each one and is rather inefficient in places.
Hiding an entity allows MiniB3D to skip most of that work, which is why its faster when doing it.

But it also depends on which version of MiniB3D your using i guess. As my modified copy of klepto.MinB3dExtNew (the one that includes batchsprites), frustrum culling works as intended and entities out of view cost very little.

After some testing on my Skylake 6700K + AMD R390, with 1300 sprites on the screen:
FrustrumCulling eats maybe 2ms.
UpdateSprites is virtually free.
Alpha/Order testing and the respective sorting in the render list eats about 7ms.
So it looks to be the sheer number of Draw calls and all the setup around each entity that is the bottleneck, IE the driver and consequently the CPU.

I chose 1300 as that is the max entities i can have on screen and still target 16ms per frame.

My test, press SPACE to check frustrum culling. Mine jumps from 16 to 0ms when only the dummy cube is shown.



Midimaster(Posted 2016) [#11]
Thank you for your help and responses. It aleays points me to new ideas. Please continue....

I know only a little about 3D and advanced technics. So some terms are new to me. Is "Frustum culling" what I call "in camera view"? What is "cross polygons"? What are "point sprites"?

@Angros47
your signatur contains "OpenB3D: Minib3d for open-source languages." Do you know more about it? Is OpenB3D a complete replacement for MiniB3D? Will it still be continued? Why do i need a wrapper? Is there a project page?

Back to my trees.... New test brought out this:

MiniB3D is very poor in finding out, what is behind camera. If I check the "in camera view" by myself, I need 1msec for that. Here I hide all tree sprites which are more than 47° left or right away from my camera direction

... but this brings me back to below 16msec.


angros47(Posted 2016) [#12]
Since I am the main developer of OpenB3D, yes, I know more about it. As you might know, Simon Harris wrote years ago a version of MiniB3D for the iphone, called iMiniB3D. I forked it, porting back to the pc, and added some features. The main difference with MiniB3D is that OpenB3D is written in C++, non in BlitzMax (hence the need of a wrapper). There is a thread on this section, and another thread in FreeBasic website. The main page is on sourceforge. OpenB3D supports all features of vanilla MiniB3D, plus a lot of extensions: terrains, quaternion-based rotations, shadows, shaders, and much more.


Krischan(Posted 2016) [#13]
First a tip: don't use alpha sprites, use masked sprites with Flag 4 instead, they are much faster and nearly look the same from a distance.

As a multi-purpose sprite replacement I'm using my own single surface TQuad Type which is still in WIP, but here's a quick example (use WASD/Mouse to fly around and beware: Flip is off):



And with simple Entity instancing (copying the quad cube 27 times) it is even possible to show at least 9^3*10000 = 7.290.000 QUADS ALWAYS FACING TO CAMERA with about 275 FPS here, just to mention this is still vanilla miniB3D ;-) So it is possible, just play with the code (and my code isn't very optimized yet).



And for a full masked tree/grass example you can take a look at my old ORCS outdoor code, it has lots of trees using a similar technique: ORCS Billboard


Kryzon(Posted 2016) [#14]
The TQuad.Update method can be optimised with this:
http://www.blitzbasic.com/Community/posts.php?topic=102120#1298605


Krischan(Posted 2016) [#15]
Yes, but I think it's optimized enough for some trees. Another option is to use the miniB3D Addon "TBatchsprite" - I prefer to create my own system but it could be useful for Peter:

TBatchSprite -- batch sprites for minib3d


RemiD(Posted 2016) [#16]
@Midimaster>>you may be interested in these :
http://www.blitzbasic.com/Community/posts.php?topic=69532
http://www.blitzbasic.com/Community/posts.php?topic=102163
http://www.blitzbasic.com/codearcs/codearcs.php?code=1324


Midimaster(Posted 2016) [#17]
At the moment I'm in China for 2 weeks. but I will have a look on it, when I'm back... and report...

by the way... some days ago I flew with "Emirates". In the on board entertaining program there was a car racing game. In the copyright informations I could find out, that it was written in Blitz3D by a french team...