SFML community forums

Help => Graphics => Topic started by: Brodal on November 10, 2012, 11:04:01 am

Title: [Solved]Possible to reuse pixels?
Post by: Brodal on November 10, 2012, 11:04:01 am
I'm having a really big problem at the moment. I have a large tile based map that is being pre-rendered onto textures at the start of the map. 8x8 Tiles fit onto one chunk and one chunk is one texture. The up side of this? I reduce the amount of draw calls made by 64, that is #tiles/64. The downside is that the tiles are not being reused so huge amounts of memory is being gobbled up by the textures. So my question to you guys is, is it possible to reuse pixels so that i dont make copies of every pixel all the time, instead i have something like a pixelpool which holds 1 unique copy of each used pixel and then use pointers or references to these and build up my chunk textures from? Or is there some other way to limit the memory usage but still keep the draw calls at a low number?
Thank you for taking the time to read this! :)
Title: AW: Possible to reuse pixels?
Post by: eXpl0it3r on November 10, 2012, 11:14:00 am
What do you mean by 'pixels'?
A pixel in SFML is a sf::Uint8 (iirc) and you can draw thoase onto a sf:Image, but I don't think that's what you want...
Can you maybe rephrase the question and define what your idea of pixel is?
Title: Re: Possible to reuse pixels?
Post by: Laurent on November 10, 2012, 11:43:02 am
He wants the best of both worlds: less draw calls, and less video memory consumption.

The answer is in vertex arrays ;)
Title: Re: Possible to reuse pixels?
Post by: Brodal on November 10, 2012, 12:17:26 pm
Im allready using the vertex arrays. And i am referring to sf::uint8 pixels, that is a pixel consisting of R,G,B and A values. Right now i am using an array of vertexes to create a tile, that is one tile is an sf::Vertex Tile[4]; However what i do is i render 64 different ( depending on how the map looks ) tiles onto 1 texture, so that i group 64 tiles into one texture making it a chunk of tiles rendered to one texture. Therefore i can't reuse this texture as every texture has the possibility to be different and probably will be. Therefore i am wondering if it is possible to look up the pixels (pixelarray?) that a tile consists of and reuse these pixels if they have allready been used once. Making the larger chunk texture into a texture consisting of reused pixels and therefore saving alot of memory by not duplicating pixels allready existing. I want to reuse the pixels, NOT make a copy of them and using that copy.
Title: Re: Possible to reuse pixels?
Post by: Laurent on November 10, 2012, 12:41:43 pm
I think you didn't understand what I meant:
- use one single vertex array for your whole map
- use one single texture (that contains all your tiles)

You don't have to pre-render chunks of tiles into bigger textures. Each tile is exactly once in video memory so there's no waste, and since your map fits in a single vertex array, there's only one draw call. The only drawback is that you can't discard parts of the map that are not visible, but you probably won't need this optimization.
Title: Re: Possible to reuse pixels?
Post by: Brodal on November 10, 2012, 12:44:56 pm
But how do i cull tiles that are outside camera view if i do things this way? And won't it iterate all tiles of the map every draw call? I'm not really sure how you mean that i should structure my tiles within this vertex array for it to become efficient. I would be really thankfull if you could elaborate a little :)
Title: Re: Possible to reuse pixels?
Post by: Laurent on November 10, 2012, 12:47:47 pm
You replied before I finished to edit my message:
Quote
The only drawback is that you can't discard parts of the map that are not visible, but you probably won't need this optimization.

Don't worry about how many quads are rendered, the graphics card can handle millions of polygons. What's important is the number of draw calls. What's slow is the amount of OpenGL calls that SFML has to make everytime you call the draw function. But whether this call sends 4 or 40000 quads to the graphics card doesn't make a big difference.
Title: Re: Possible to reuse pixels?
Post by: Brodal on November 10, 2012, 12:50:34 pm
I did not know that, thanks for the help :) one last thing, is this only applicable for static tiles, or is there some way to imeplement this for tiles that move around/change too?
Title: Re: Possible to reuse pixels?
Post by: Laurent on November 10, 2012, 01:01:14 pm
Quote
is there some way to imeplement this for tiles that move around/change too?
Why not? You can change anything in your vertex array at any time.
Title: Re: Possible to reuse pixels?
Post by: Brodal on November 10, 2012, 01:02:22 pm
Allrighty! thanks for the help! :) Time to scrap my level rendering ;D
Title: Re: [Solved]Possible to reuse pixels?
Post by: Nekroze on November 10, 2012, 11:08:04 pm
Would this be safe or even sane however for a pseudo-infinite world? I imagine, as efficient as it is, that after say hours of moving over large distances that it would *eventually* reach some diminishing returns or some limit because of the lack of culling. I suppose this could be mitigated by after some arbitrary amount of time, scrapping the entire vertex array and starting it again at the last position in the "players" current "chunk" which may be a little tricky.

Also sorry to inject a newbie question to a solved thread but, with a vertex array could that be used with all its benefits to draw tiles from a tileset texture. I see that vertices have texcoords but i see no way to define a texture to use for the vertex/array or even how to define the rectangle (i get the coords may be the x/y of a texture but how many pixels across or high?) of that texture to use or some such. Although i may well be misunderstanding them entirely as i came from a very limited sdl background and some things are just un-natural for me to think of just from reading a little bit of documentation.

The above question does pre-surpose my assumtion that a vertex array is essentially a large array of "windows" into a section of a texture that is grouped as one.
Title: Re: [Solved]Possible to reuse pixels?
Post by: eXpl0it3r on November 10, 2012, 11:26:05 pm
Would this be safe or even sane however for a pseudo-infinite world?
Obviously not, but your graphics card can handle quite a huge VertexArray with ease. And the thread here was never about pseudo-infinite worlds. ;)

Also sorry to inject a newbie question to a solved thread but, with a vertex array could that be used with all its benefits to draw tiles from a tileset texture. I see that vertices have texcoords but i see no way to define a texture to use for the vertex/array or even how to define the rectangle (i get the coords may be the x/y of a texture but how many pixels across or high?) of that texture to use or some such.
The texture coordinates get edited for each vertex of the vertex array (note a sf::Vertex is a element of the sf::VertexArray). The texture itself then gets passed via the sf::RenderState as second argument for the draw call. The conversion happens implicitly. ;)
Title: Re: [Solved]Possible to reuse pixels?
Post by: Brodal on November 11, 2012, 01:12:41 am
I found myself encountering lag quite quickly even with vertex arrays ( at 90k tiles i was at 20 fps ), so i changed my tactics a little. Made bigger chunks, each chunk has its own vertex array. Each chunk is 2048 x 1024 big and the tiles are 32x32. Now I'm at really high FPS with 4 million tiles on the screen, as I'm culling every chunk that my camera is not touching. This however does not either allow for infinite worlds as the number of chunks you have to iterate to find the ones you are intersecting increases with the amount of tiles on the screen although your memory will run out before the chunk amount causes any lag. Just wanted to give a hint to anyone else wanting to use huge amounts of tiles. If it lags even with vertex arrays, make several vertex arrays and only draw the ones on screen :)
Title: Re: [Solved]Possible to reuse pixels?
Post by: eXpl0it3r on November 11, 2012, 01:20:06 am
If it lags even with vertex arrays, make several vertex arrays and only draw the ones on screen :)
Or change the content of the vertex array accordingly. ;)

This however does not either allow for infinite worlds as the number of chunks you have to iterate to find the ones you are intersecting increases with the amount of tiles on the screen although your memory will run out before the chunk amount causes any lag.
It's just a bad/slow algorithm(/datastructure) you're using to determine what should get displayed and what not. ;)
Title: Re: [Solved]Possible to reuse pixels?
Post by: Brodal on November 11, 2012, 01:33:25 am
could you please elaborate on both of the things you said? :) How do you mean change the content accordingly? And, what would be a better algorithm for handling this?  I'm not using any heavy data type for storing my tiles, i only insert vertices into the vertex arrays. So there's no unnecessary stored data ( i hope ). Thanks for all the replies by the way! :)
Title: Re: [Solved]Possible to reuse pixels?
Post by: Nekroze on November 13, 2012, 05:31:46 am
I don't know the normal way of figuring out of buffering and culling chunks so here is what i do at the moment:

Firstly i get the position of the current chunk that the center screen pixel is in, each chunk has its own global coordinate (they also store a screen coordinate because i move the world around the player not the player around the world (not sure if that's normal bu it has worked well so far)) then i use that to make a sfIntRect based on the chunk load range i am currently using (radius of chunks to be pre-loaded around the center current chunk. then i loop over the x and y of positions within that fsIntRect and if those coordinates in my hashmap of chunks are null or not already loaded then i add the coordinates to a list of chunks to be loaded in (one chunk is created from this lists coordinates per frame, loading all required chunks as they were found to be needed caused a slight stutter when it did so all at once) then i loop over each chunk currently in the hashmap of chunks and use its coordinate/key to use the sfIntRect contains function, if it is false then i add that to a list to be unloaded same as the loading list works pretty much.

Using this so far has been pretty good and fast for me but i don't know why if your tiles are 32x32 you would need 4 million of them, i suppose zooming out enough could warrant that, in which case you would just have to change the load range according to the zoom level... interesting thought.

Also i would like more details about changing the vertex array accordingly as well, as far as i can see doing the vertex array in chunks is a solid idea. and i don't see why it couldn't be used for pseudo infinite worlds.
Title: Re: [Solved]Possible to reuse pixels?
Post by: Brodal on November 14, 2012, 10:38:24 am
The reason for 4 million tiles is cause I do not know exactly how big our designers are planning to make the map. And because if it can manage that many tiles or even more then it shouldn't be a problem when more stuff is added into the game. I figured out a better way to cull chunks that has the complexity O(1) instead of O(N) which mine has now, taking advantage of the constant time random access takes. Instead of iterating anything at all I just keep my chunks sorted and divide the cameras current position by the size of a chunk. I then store this number in an int to truncate it ( if value after division is 1.3245 it is truncated to 1, or if value is 13.5323 U get 13 ). Then I multiply this int by the size of a chunk to get an integer value which is also the index in the vector ( when the vector is sorted ) for the chunk I'm in. This way culling of chunks should not be affected by the the number of chunks that the vector contains. Someone please correct me if I'm wrong :)