1
\$\begingroup\$

I have a 2D engine that uses XNA 4.0. I have an issue with handling many objects. In my engine, I only draw visible sprites, and ignore sprites outside of the current viewport. It works, so far. I also use a RenderTarget to minimize the amount of sprite batch being called, to draw the base.

I also need to draw buildable objects, and the worst case is that there is a list with 10,000 - 20,000 objects. I need to iterate through them, to find the visible buildable objects, as well. This really affects my frame rate, especially when the viewport changes.

I could decrease the zoom level, to minimize the amount of base tiles, but the list of objects keeps the same. Using smaller texture sizes could help, but then I´m also losing detail.

How could I improve the performance?

\$\endgroup\$
  • \$\begingroup\$ You need to use a profiler and check how much time it takes to check if objects have visible boundaries and how much time it takes to actually draw the objects. Normally a simple 2d grid is used to decide if objects are visible or not so you don't have to iterate over all the objects, just the ones nearby. \$\endgroup\$ – wolfdawn Nov 1 '14 at 13:29
1
\$\begingroup\$

1) You don't need to calculate the visible objects in a single frame, you may use a bit bigger viewport, and calcultate only 500 objects per frame, if you have 20000 objects and your framerate is 50fps, in 40 frames you will have the right list, and it will take 0.8 secs

2) if your objects are not very complex or are static, sometimes is faster to put them in a vertexbuffer and draw all. letting to the gpu discard the no visible triangles... maybe you can use instancing if you use many repeated objects

3) you can use spatial division algorithms like quadtrees to discard sprites in spaces that are not visible

4) if you are using background tiles stored in an array is easy to calculate the visible array tile ofsets... and you can hook the dynamic sprites by its center to your background tiles, so when you render the background tile you know there are other sprites to render.

\$\endgroup\$
  • \$\begingroup\$ 1) is a good one! Just split the calculation operation is a good idea. I´ll try that. 2) VertexBuffer, triangles...sounds more like 3D ;) 3) Heard about that. Maybe I´ll give it a go. 4) Could get problems with big dynamic objects because they may overlap the background tile so it´s not drawn but I like that idea! Thank you so much! \$\endgroup\$ – Yheeky Oct 2 '14 at 9:09
  • \$\begingroup\$ in 4) with big tiles you have to divide them in several small ones \$\endgroup\$ – Blau Oct 2 '14 at 11:11
  • \$\begingroup\$ Yeah. I think the big textures are responsible for this massive impact on the Framerate. Got to handle that anyway :) \$\endgroup\$ – Yheeky Oct 2 '14 at 14:35
1
\$\begingroup\$

I'd highly suggest you look into implementing a Quadtree.

This would allow you to run a query to fetch all the objects in your viewport, as opposed to checking every single entity before a draw.

Have a look at the following sample query code:

List<Entity> entitiesOnScreen;
entitiesOnScreen = QuadTree.GetObjects(Viewport.Rectangle);

foreach (Entity entity in entitiesOnScreen)
    entity.Draw();

As you can see, this greatly simplifies your drawing calls. You ask the Quadtree for a list of objects contained in a Rectangle, which it quickly provides for you.

Then it is just a matter of looping through this list to draw what is on screen.

\$\endgroup\$
  • \$\begingroup\$ It really does simplify my drawing calls. Not a big improvement though because the Framerate is still at 40FPS but I like the concept. I guess I have to work with smaller textures to really improve performance. Thanks :) \$\endgroup\$ – Yheeky Oct 2 '14 at 14:34
0
\$\begingroup\$

You would likely have to switch over to the 3D (lower level) rendering and then use instancing which offloads most of the work to the GPU.

\$\endgroup\$
  • \$\begingroup\$ Interesting point. Switching to 3D is not my favorite way to do it but I´ll keep it in mind :) also thanks for the link! \$\endgroup\$ – Yheeky Oct 2 '14 at 8:57
  • \$\begingroup\$ (I've removed the link in this answer because the domain right now gives you all kinds of weird pop-ups). \$\endgroup\$ – Roy T. Jun 2 '17 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.