SFML community forums

Help => Graphics => Topic started by: deadmau5 on May 21, 2013, 11:02:52 pm

Title: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 21, 2013, 11:02:52 pm
Hi all,

After reading the documentation on the VertexArray class and textures I seem to be stuck.
It all works great.. for one tileset texture.
I have multiple tilesets which consists of 5 by 10 tiles (each tile is 32x32).

Positioning the x and y for both the screen (VertexArray.position) and the tileset (VertexArray.texCoords) is working fine.
I just need some help with how to handle multiple tilesets, I can't put my finger around this issue.

I am using SFML 2.0.
Any help or tips is highly appreciated!
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 21, 2013, 11:06:11 pm
You can't, you must have one vertex array for each tileset (texture).

But 5x10 tiles of 32x32 is not a lot, can't you group your tilesets into a single bigger texture?
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 21, 2013, 11:28:18 pm
You can't, you must have one vertex array for each tileset (texture).

But 5x10 tiles of 32x32 is not a lot, can't you group your tilesets into a single bigger texture?
I suppose it's possible to put them into a bigger texture. But I'm not sure what the maximum dimensions are for sf::RenderTexture (assuming it could be done with this) as I have a lot of tilesets.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Nexus on May 21, 2013, 11:53:30 pm
It should be sf::Texture::getMaximumSize(), of which the result depends on the hardware. But most computers that are a few years old support 1024 and more...
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 12:35:16 am
On my system this value is 16384, but I have no idea what this value is on other systems (will be released).
So I don't think this is much of a solution (I have read sf::RenderTexture had some problems on intel graphic drivers also, no idea where I have read that or what the problems were exactly).
Ill try to create a std::vector of sf::VertexArrays and tileset textures then. Thanks :-)
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 08:00:40 am
You can safely use 512x512 textures (I don't know how large you need the tileset to be, if there's only one).

You can avoid sf::RenderTexture, since you basically just need raw pixel copy. Use sf::Image::copy.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 05:19:32 pm
Faced another problem, the mapdata (tileIDs) are ofcourse spread out over the tileset textures so it wouldn't be possible to use sf::VertexArrays in the first place (I think?).

It seems the only possible solution in my case is either drawing all tile sprites individually (bad performance) or using sf::RenderTexture which is not optimal.

You can avoid sf::RenderTexture, since you basically just need raw pixel copy. Use sf::Image::copy.
Not sure what you mean by this. Could you elaborate?
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: FRex on May 22, 2013, 05:56:58 pm
The idea is that you'd load all Images(not Textures) and then compose them into big Image and load that Image into Texture using loadFromImage(). You can also use few vertex arrays, one for each Texture.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 06:18:18 pm
Quote
Faced another problem, the mapdata (tileIDs) are ofcourse spread out over the tileset textures so it wouldn't be possible to use sf::VertexArrays in the first place (I think?).

It seems the only possible solution in my case is either drawing all tile sprites individually (bad performance)
What problem is there? Sprites are vertex arrays internally, so if you can do it with a sprite you can do it with a vertex array.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 06:40:53 pm
Quote
Faced another problem, the mapdata (tileIDs) are ofcourse spread out over the tileset textures so it wouldn't be possible to use sf::VertexArrays in the first place (I think?).

It seems the only possible solution in my case is either drawing all tile sprites individually (bad performance)
What problem is there? Sprites are vertex arrays internally, so if you can do it with a sprite you can do it with a vertex array.
The problem is putting it all in one draw call in the end.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 06:44:53 pm
Quote
The problem is putting it all in one draw call in the end.
Can you be more specific about what's blocking you?
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 06:57:19 pm
Quote
The problem is putting it all in one draw call in the end.
Can you be more specific about what's blocking you?
My situation:
Multiple tilesets loaded into std::vector<sf::Texture>;
Not being able to put these into one big texture as it is way too much.
No idea how to reference VertexArrays to these tileset textures (std::vector) as each tileID (loaded from a file) is spread out over those textures and thus no idea how to get it so I only have to call draw (VertexArray, multiple textures) once for the entire map.

I hope its a bit more clear now.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 08:32:12 pm
Quote
Not being able to put these into one big texture as it is way too much.
As I said in my first answer, you have to use one vertex array per texture. But it's still a lot better than one sprite per tile.

Quote
Not being able to put these into one big texture as it is way too much.
You still haven't said how much you would need ;)
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 08:59:30 pm
As I said in my first answer, you have to use one vertex array per texture. But it's still a lot better than one sprite per tile.
Yeah I get this.. however I don't know how to link my tileIDs (which are loaded from a file) with those VertexArrays as each tileID could be only be used in one tileset texture.

Quote
Not being able to put these into one big texture as it is way too much.
You still haven't said how much you would need ;)
500+ tilesets. 5 by 10 tiles (each tile is 32x32). Which is too much to cram into a single texture.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 10:00:42 pm
Quote
however I don't know how to link my tileIDs (which are loaded from a file) with those VertexArrays as each tileID could be only be used in one tileset texture.
But what are these tileIDs, and what do they mean at the vertex array level? Is it just another way to refer to specific texture coordinates inside a specific tileset?

Quote
500+ tilesets. 5 by 10 tiles (each tile is 32x32). Which is too much to cram into a single texture.
That's a lot, indeed.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 22, 2013, 10:08:48 pm
But what are these tileIDs, and what do they mean at the vertex array level? Is it just another way to refer to specific texture coordinates inside a specific tileset?
Yes it is. And I have no idea how to go with it in terms of VertexArrays and a vector of tileset textures.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 22, 2013, 11:24:56 pm
Associate a sf::Texture and a sf::VertexArray to each tileset. Then for every tile, add a quad to the vertex array that matches the tileset. That's it.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 23, 2013, 02:00:30 am
Associate a sf::Texture and a sf::VertexArray to each tileset. Then for every tile, add a quad to the vertex array that matches the tileset. That's it.
I still fail to see how this could be done in one draw call to render the entire map to the screen.

Example:
Mapdata from file contains tileIDs (seperated by spaces): "1 50 51 100 101 200"
1 = first tile in first tileset.
50 = last tile in first tileset.
51 = first tile in second tileset.
100 = last tile in second tileset.
etc.

I could add quads to the VertexArray containing all tile coordinates of the textures. No problem, these are just vertices that have nothing to do with the actual texture until you decide to render it?

But my problem is that I need an alternative way to draw the entire map with one window.draw call like its supposed to with one tileset texture but instead with multiple. But as stated before this is not possible with multiple textures:
window.draw(VertexArray, &vTilesetTextures[0]);// <- Here one texture. (vTilesetTextures = std::vector<sf::Texture>)
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 23, 2013, 08:07:39 am
Ok, I think I was not clear enough. When I say "one vertex array per texture", it implies "one draw call per vertex array". You won't be able to draw everything in one call. Just iterate over your array of sf::VertexArray and draw them one by one using the corresponding tileset.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 23, 2013, 05:10:25 pm
Ok, I think I was not clear enough. When I say "one vertex array per texture", it implies "one draw call per vertex array". You won't be able to draw everything in one call. Just iterate over your array of sf::VertexArray and draw them one by one using the corresponding tileset.
Wouldn't this be as inefficient as drawing the sprites individually?
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 23, 2013, 06:03:33 pm
No, because you obviously have less tilesets than tiles. Thus you have less draw calls with vertex arrays. To be more precise, if you have 50 tiles per tileset, that's 50x less calls, so approximately 50x more performant.

By the way, out of curiosity, what kind of map requires more than 25000 different tiles (500 tilesets * 5x10 tiles) to be loaded at the same time? It seems really huge.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 23, 2013, 06:40:50 pm
No, because you obviously have less tilesets than tiles. Thus you have less draw calls with vertex arrays. To be more precise, if you have 50 tiles per tileset, that's 50x less calls, so approximately 50x more performant.

By the way, out of curiosity, what kind of map requires more than 25000 different tiles (500 tilesets * 5x10 tiles) to be loaded at the same time? It seems really huge.
It's not one map of 25000 different tiles but multiple maps. Every map will be loaded when needed (which can range from 10x25 or 45x10 tiles for example). The map dimensions are dynamic but tiles of different tilesets are needed for each map.
My window resolution is 800x600, which can store 475 visible tiles ( (800 / 32) = 25 x (600 / 32) = 18,75 = 19 ). And will only draw the visible tiles.

Now when I understand correctly I would need 500 draw calls with using VertexArrays and 475 draw calls for sprites individually.

Which is inefficient. Your (and anyone elses) help is ofcourse appreciated :-)
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 23, 2013, 06:54:16 pm
Quote
Now when I understand correctly I would need 500 draw calls with using VertexArrays and 475 draw calls for sprites individually.
How can you need more textures (tilesets) than sprites (tiles)... ??? There's at most one different texture per tile, not more.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: deadmau5 on May 23, 2013, 07:03:42 pm
How can you need more textures (tilesets) than sprites (tiles)... ??? There's at most one different texture per tile, not more.
You won't be able to draw everything in one call. Just iterate over your array of sf::VertexArray and draw them one by one using the corresponding tileset.
Meaning that I need to iterate through all tilesets (500) for my map to draw? Or do I completely miss the point here.
Title: Re: sf::VertexArray for multiple Tilesets.
Post by: Laurent on May 23, 2013, 07:07:36 pm
But you obviously don't need the whole set of 500 tilesets to draw 475 tiles. Some tilesets (at least 25) will never be used in this case.

I think you should play with what SFML has to offer, to find the best solution for your specific case. This discussion is getting too long, actually trying something, and understanding vertex arrays would probably be more efficient for you now. What I say will always be too abstract for you until you get your hands into it ;)

That's just an advice, of course I'll continue to answer your questions.