Trying to draw around 100,000+ non-changing (other than color, rarely) sprites

So, I’m trying to see if this is possible or just asking too much, but…

My game has quite a few “sectors” in the galaxy that share a single texture, never move, or change (other than color when the owner changes).

In the past I’ve done just a spriteBatch.Draw(…) and could get 60fps, but with not much overhead.

I’ve tried this link: https://community.monogame.net/t/minimal-example-of-drawing-a-quad-into-2d-space/11063

To see if drawing quads would improve performance, but it actually performs worse (I can post the Game.cs I made if needed).

So, is there a way to do this or am I asking too much?

Thanks

Why do you need 100k sprites on screen?

When you say non-changing sprites, do you mean that not even the position is changing? If you can put all sprites into a static vertex buffer, then 100K is nothing, unless they are large, in which case pixel fill rate will kill performance.

If you need to upload 100K sprites every frame to the GPU, I guess you’re somewhere in a grey zone, where performance will suffer noticeably, but it’s probably still doable.

That’s right, not even the position is changing, I’ll look into a static vertex buffer.

See the bottom post.

2 Likes

I have three tutorials on creating a 3D tile engine. The third covers using a vertex buffer that has me rendering one million quads at about 100 fps. That should help you out.

3 Likes

Well, that’s an interesting coincidence. How about two million moving ones:

However, for your purpose 200 000 of static this isn’t needed. It is of course absolutely possible, as Markus said, fill rate will be your bottle neck way before anything else.

As Willmotil said, using insanced quads is 100% way to go, you will use single quad in binding of first vertex buffer and array of whatever struct you need (at least position, possibly scale, possibly also UV offset in case of multiple sprites per texture) of given quantity as second binding. I’ve scrolled through Willmotil example and I believe it should work fine.

3 Likes

Well now, that’s something!

1 Like

Assuming the space you’re drawing them to fits in a single screen…

Another option might be to just render them all once, or in batches, to a RenderTarget2D. If their positions, rotations, and scales never change independently this would probably work. For colour, if you’re not particular about the draw order, you could probably just render the new one with the new colour to the render target when needed and carry on.

If the space you’re drawing them to is larger than a screen, and you only need to view portions of them at a time, look into a QuadTree to partition your world space. This will allow you to only draw what’s visible.

Other than that… I should get around to learning how instanced quads work one of these days :stuck_out_tongue:

1 Like

@GeonBit already created this scenario and you can try that here:

@evgLabs

Remember to Visual Studio profiler to make sure you aren’t loosing too much time in your code outside of the draw calls and focus on making sure you are speeding up the right thing.