Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: What's the best way to draw a lot of sprites?  (Read 12491 times)

0 Members and 1 Guest are viewing this topic.

coder2k

  • Newbie
  • *
  • Posts: 3
    • View Profile
What's the best way to draw a lot of sprites?
« on: January 07, 2013, 01:23:24 am »
Hello everyone, this is my first post :)

I'm trying to create a game with an isometric map and I wonder what's the best way to draw it. At first I was drawing all tiles seperately but that was way too slow with a map size of (64x64 tiles). Then I thought I could draw all tiles to a RenderTexture first and just draw that onto the screen. Turned out well - worked really fast. But the problem is the limitation of the size of a RenderTexture. On my older PC I just can't create a RenderTexture that's big enough (and the middle-sized RenderTexutures are way too slow).
Any suggestions?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: What's the best way to draw a lot of sprites?
« Reply #1 on: January 07, 2013, 01:40:17 am »
In programming never ask for 'the best way', because there is no such thing, is always completely depends on what you want to achieve.

Generally you should try to reduce the draw calls, for this you can use sf::VertexArray and store all the needed information in there.

Additionally you'll also have to make a decision on how much backwards compability you want to support...
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

coder2k

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #2 on: January 07, 2013, 01:46:05 am »
Okay, you're right. But perhaps there is a "best way" for what I want to do.

To reduce the draw calls I drew the sprites onto a RenderTexture and then simply drew that onto the screen. As mentioned before: The maximum size could be a problem.
Can you explain how sf::VertexArray could help me? Isn't that one only for primitives like rectangles, etc? I need to draw images onto the screen. Or am I missing something?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: What's the best way to draw a lot of sprites?
« Reply #3 on: January 07, 2013, 01:57:11 am »
Can you explain how sf::VertexArray could help me? Isn't that one only for primitives like rectangles, etc? I need to draw images onto the screen. Or am I missing something?
What are images? Exactly quads/rectangle. ;)

With sf::VertexArray (or for more flexibility std::vector<sf::Vertex>) you define every point (vertex) of your image and apply the needed texture coordinate to it. Thus you can use one texture and one vertex array with one draw call, but display hundred or even thousands of 'images'. And since graphics card are build to handle millions of vertices the performance will be very good.

You can look at the documentation here and some example code here. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

coder2k

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #4 on: January 07, 2013, 02:09:51 am »
Thanks for those links! Definately will look into that...seems like the way to go. Have to refresh my C++ knowledge ;-)
Thanks for your support so far :)

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #5 on: January 07, 2013, 02:51:33 am »
Try this: http://pastebin.com/DjaXwD4t

Usage:
SpriteBatch sb;
sb.setRenderTarget(window); //initialization

for(int i=0; i < spritesCount; i++) //in your game loop
        sb.draw(sprites[i]);
sb.display();

 

Should be at least 2x times faster than standard drawing (if you use texture atlases).
If need this for tiles, you can skip sprites completly and use:
void draw(const Texture *texture, FloatRect dest, IntRect rec, Color color);
 
« Last Edit: January 07, 2013, 02:53:30 am by krzat »
SFML.Utils - useful extensions for SFML.Net

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: What's the best way to draw a lot of sprites?
« Reply #6 on: January 07, 2013, 03:07:09 am »
Does Spritebatch allow the usage of individually transforming (positioning, rotating and scaling) each sprite?
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #7 on: January 07, 2013, 03:21:58 am »
Yep. It was meant to replace standard drawing (of sprites) completly.
SFML.Utils - useful extensions for SFML.Net

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: What's the best way to draw a lot of sprites?
« Reply #8 on: January 07, 2013, 04:51:41 am »
Is there any more code? From what I saw in the link there is some code that handles transformations, but no function that allows you to move each sprite individually as you'd like. I am asking because I am programming a similar class and I want to see different approaches towards it.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #9 on: January 07, 2013, 11:30:52 am »
It takes a sprite, generates vertices from it and stores them in array. You have to redraw each sprite every frame.

As I understood, you want something different: keep track of all the sprites and update vertices only when something changes. The problem i see here, is that SFML doesn't support depth buffer, so each time you want to remove sprite(or insert it behind existing one), you have to rewrite both arrays (or implement depth buffer).
« Last Edit: January 07, 2013, 11:39:01 am by krzat »
SFML.Utils - useful extensions for SFML.Net

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: What's the best way to draw a lot of sprites?
« Reply #10 on: January 07, 2013, 03:29:45 pm »
Quote
The problem i see here, is that SFML doesn't support depth buffer, so each time you want to remove sprite(or insert it behind existing one), you have to rewrite both arrays (or implement depth buffer).

This is a problem that has no good solution around it as deleting a member of a std::vector can usually be expensive. My use cases are mostly to initialize the container of vertices with a set quantity and discourage changing sizes. In my case for my own programming I wouldn't add any function for that kind of handling, but since it's going on the wiki I'll implement it just in case.

Eventually the container has the capacity of being reused, so once its usefulness is gone you just set a new texture and work it from there on what you need to do with it.

I do redraw the vertices everytime, just that I don't update their positions, rotation or anything else unless the programmer states that he wants to with the said functions. Like a class with a std::vector of sf::sprites would.
« Last Edit: January 07, 2013, 03:38:59 pm by masskiller »
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: What's the best way to draw a lot of sprites?
« Reply #11 on: January 07, 2013, 08:00:47 pm »
Try this: http://pastebin.com/DjaXwD4t
A few tips:
  • Use std::vector<sf::Vertex> or sf::VertexArray instead of reimplementing them with sf::Vertex* and new[] and delete[]. Then you also get rid of the bug occurring when SpriteBatch is copied, and you don't need the destructor anymore. Avoid manual memory management wherever possible.
  • Setting the pointer to NULL in the destructor is completely useless ;)
  • Are the trigonometric functions really such a performance issue that a lookup table (and the reduced precision) is appropriate?
  • You re-invent the wheel instead of working with sf::Transform.
  • Modulo is clearer than the binary AND operator, and since the second operand is a constant expression, the compiler will optimize it.
  • In your constructor, prefer the initializer list over assignments.
  • Never write using namespace in headers. It's includers can do nothing against it.
  • Include the C++ header <cmath> instead of the C one <math.h>.
  • Make code const-correct. For example, draw() should take a reference to a const sf::Sprite.
  • Use static_cast instead of C casts, they are safer.
In general, make things simple, correct and bug-free before applying micro-optimizations that won't be noticable.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: What's the best way to draw a lot of sprites?
« Reply #12 on: January 07, 2013, 10:55:21 pm »
Thanks for hints. Here is version with fixes: http://pastebin.com/Jk0m1VE8

This is port from C#, so some optimizations make less sense. I can't use Transformable because double wrapping (on C#) would destroy performance. This is why standard drawing is 3x times slower on .Net.

Drawing without lookup tables is 30% slower on C++ and 80% slower on C#. Current lookup has maximum error of 0,6% - IMO worth it.

I'm also happy to say, that C# version is as fast as C++.
SFML.Utils - useful extensions for SFML.Net