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

Author Topic: Sprite Efficiency  (Read 22541 times)

0 Members and 2 Guests are viewing this topic.

Solluxx

  • Newbie
  • *
  • Posts: 19
    • View Profile
Sprite Efficiency
« on: February 04, 2013, 06:44:53 am »
Hola, I was just wondering what, if any, implications creating sprites on the fly has. I would think creating a texture and sprite in the header and then just calling the sprite would be more efficient, but is it ok if I just make the texture in the header and then create sprites and set their parameters on the fly, letting the scope clean them up after every draw? Will this hit the performance enough where I should be worried about it? I prefer making them on the fly for header cleanliness but meh. Any thoughts you may have would be great.

-Sam

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite Efficiency
« Reply #1 on: February 04, 2013, 07:58:22 am »
Sprites are lightweight objects, the difference should not be noticeable.
Laurent Gomila - SFML developer

Solluxx

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Sprite Efficiency
« Reply #2 on: February 05, 2013, 02:18:01 am »
ok awesome ty

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #3 on: February 05, 2013, 08:52:19 am »
I have a similar question. What if I have hundreds of objects(in tile engine, for example)? Stroring every sprite in Tile class will need more memory, but on the other hand creating them on the fly may create some perfomance issues. What is the best way to do it?
« Last Edit: February 05, 2013, 08:56:37 am by moarthenfeeling »
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite Efficiency
« Reply #4 on: February 05, 2013, 10:36:07 am »
There's no best way. Measure the memory taken, the CPU consumption, and decide which compromise is best for your particular application.

Note that for a tile map you probably want a single vertex array instead of many sprites.
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #5 on: February 05, 2013, 11:27:27 am »
Thanks, Laurent!

And another question: what are the main differences between using sf::Sprite and sf::VertexArray for tiles?
« Last Edit: February 05, 2013, 11:34:42 am by moarthenfeeling »
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite Efficiency
« Reply #6 on: February 05, 2013, 11:40:00 am »
With a vertex array you can put all your tiles into a single entity, which makes a big difference when you draw it, since performances directly depend on the number of calls to the draw function.
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #7 on: February 05, 2013, 11:46:29 am »
Thanks again, I'll try to do it that way. :)
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #8 on: February 05, 2013, 01:03:39 pm »
Some things are not pretty clear though...
Right now I use this method. I have a tileset map, with char keys(chars are needed to read information from level file)

std::map<char, Tile*> tilesetMap;
Where Tile is just a simple struct(which will then contain collision information, animation etc.) with a texture created in a Tileset class(using the tileset sf::Image) and a sprite which uses this texture

struct Tile {
        sf::Texture texture;
        sf::Sprite sprite;
};
 

The level is stored like this:
std::vector<Tile*> map;

So when I draw a tile I just do:
int id  = x + y * width;
sf::Sprite tempSprite = map[id]->sprite;
tempSprite.setPosition(x * TILE_SIZE, y * TILE_SIZE);
mainWindow->draw(tempSprite);

What changes do I have to make to use vertex arrays?

(my method works pretty good, though
18068 kb in RAM for 4x4 map and 18088 kb for 276*15 map)
« Last Edit: February 05, 2013, 01:14:42 pm by moarthenfeeling »
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

krzat

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Sprite Efficiency
« Reply #9 on: February 05, 2013, 01:32:28 pm »
You can use my tilemap renderer: http://pastebin.com/SrBE69EC

You need to write custom TileProvider function to wire it with your code.
SFML.Utils - useful extensions for SFML.Net

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite Efficiency
« Reply #10 on: February 05, 2013, 02:02:54 pm »
First, having one texture per tile is definitely overkill. At least, use the same sf::Texture instance for tiles that are the same. And to get the best performances, store your whole tileset into a single sf::Texture (if possible).

Then why do you set the sprites' position everytime? It's a fixed value, just assign it upon loading.

But back to the point. Instead of having a vector of N sprites, requiring N draw calls, you could just gather all these static sprites (they never change, right?) into a single entity composed of many quads, that you can draw in a single call. Trust me, the difference is huge, both in terms of performances and memory consumption.
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #11 on: February 05, 2013, 02:16:45 pm »
krzat, thanks, I don't think I will use the entire code, but some parts will be very helpful

Laurent, so do I have to keep one texture in a tileset instance(for example) and keep pointers to this texture in the tiles? If so, how do I use a part of a texture?(I'm new to SFML haven't figured this yet)

About sprite position... yeah, it was pretty stupid I guess. :) EDIT: I have to do this, because I have only n instances of Tile, where n - number of tiles in the tileset, because creating different instance for each tile in map will be overkill, so I have similar tiles in a tileset, I just draw them in a different places, therefore I have to assign sprite position for a tempSprite
 I don't have to make N calls, because I draw just those tiles which are seen on the screen at the moment.

Quote
you could just gather all these static sprites (they never change, right?) into a single entity composed of many quads
Is there any examples? I've never done such things before, so example would be very helpful and I believe it will really boost the perfomance.
« Last Edit: February 05, 2013, 02:31:29 pm by moarthenfeeling »
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite Efficiency
« Reply #12 on: February 05, 2013, 02:46:12 pm »
Quote
Laurent, so do I have to keep one texture in a tileset instance(for example) and keep pointers to this texture in the tiles?
No need to store references to the texture, sf::Sprite already does that. All you need to store for a tile (with your current design) is a sf::Sprite, ready to be drawn.

Quote
If so, how do I use a part of a texture?
sprite.setTextureRect(sf::IntRect(left, top, width, height));

Quote
Is there any examples? I've never done such things before, so example would be very helpful and I believe it will really boost the perfomance.
The corresponding tutorial is not online yet, and there's no official example that uses a vertex array yet. But if you search on this forum, and probably on the wiki, you should find interesting stuff.

Because it's not very hard, let's try a brief explanation.

If you have a sprite:
sf::Sprite tile;
tile.setTexture(&tileset);
tile.setPosition(x, y);
tile.setTextureRect(sf::IntRect(tx, ty, w, h));

window.draw(tile);

Then you can easily create a similar entity with a vertex array:
sf::VertexArray tile(4, sf::Quads);

// first Vector2f is the position, second Vector2f is the texture coordinates
tile[0] = sf::Vertex(sf::Vector2f(x, y), sf::Vector2f(tx, ty));
tile[1] = sf::Vertex(sf::Vector2f(x + w, y), sf::Vector2f(tx + w, ty));
tile[2] = sf::Vertex(sf::Vector2f(x + w, y + h), sf::Vector2f(tx + w, ty + h));
tile[3] = sf::Vertex(sf::Vector2f(x, y + h), sf::Vector2f(tx, ty + h));

window.draw(tile, &tileset);

FYI, that's more or less how sf::Sprite is implemented internally.

Now put more than 1 quad into your vertex array:
sf::VertexArray map(sf::Quads, 4 * nbTilesX * nbTilesY);
for (int i = 0; i < nbTilesX; ++i)
    for (int j = 0; j < nbTilesY; ++j)
    {
        float tx = ... // from your loaded map info
        float ty = ... // from your loaded map info

        map[(i + j * nbTilesX) * 4 + 0] = sf::Vertex(sf::Vector2f(i * w, j * h), sf::Vector2f(tx, ty));
        map[(i + j * nbTilesX) * 4 + 1] = sf::Vertex(sf::Vector2f((i + 1) * w, j * h), sf::Vector2f(tx + w, ty));
        map[(i + j * nbTilesX) * 4 + 2] = sf::Vertex(sf::Vector2f((i + 1) * w, (j + 1) * h), sf::Vector2f(tx + w, ty + h));
        map[(i + j * nbTilesX) * 4 + 3] = sf::Vertex(sf::Vector2f(i * w, (j + 1) * h), sf::Vector2f(tx, ty + h));
}

window.draw(map, &tileset);

That's it, a super optimized static tile map :)
« Last Edit: February 05, 2013, 08:21:21 pm by Laurent »
Laurent Gomila - SFML developer

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Sprite Efficiency
« Reply #13 on: February 05, 2013, 06:13:55 pm »
There're some problems with your code, Laurent. First of all, there're some problems with your loop and second, sf::VertexArray has its arguments switched, and third, window.draw doesn't work this way, so this code doesn't work for me. :(
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Sprite Efficiency
« Reply #14 on: February 05, 2013, 06:23:26 pm »
so this code doesn't work for me. :(
If you already recognize what's wrong, you will also be able to fix it.

In the forum, the codes that people give are often meant as inspiration, to show an idea or concept. They are not intended to be copied 1:1 and to work out of the box.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: