Sign in to follow this  
Thevenin

Sprites on Videocard, GRRrrrr!

Recommended Posts

I'm going in big circles here, I don't know how to store sprites on the video card for my 2D game. I cannot put a "power of 2" constraint on my textures, because most are not even known at compile time, and I cannot restrict proper rendering of the game to people who have top-of-the-line video cards that can handle "non power of two" without issues, because my target audience is not main-stream gamers. What should I do?

Share this post


Link to post
Share on other sites
Quote:
Original post by Funkymunky
I think you want to use a texture atlas, so that you can have all your sprites on as few textures as possible. That way you can use each sprite just based on its texture coordinates, and you can pack all of them into one big power of 2 texture.


No. That extension takes in power-of-two textures, and forms cumulative power-of-two-textures. My sprites are not power-of-two textures to begin with.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thevenin
Quote:
Original post by Funkymunky
I think you want to use a texture atlas, so that you can have all your sprites on as few textures as possible. That way you can use each sprite just based on its texture coordinates, and you can pack all of them into one big power of 2 texture.


No. That extension takes in power-of-two textures, and forms cumulative power-of-two-textures. My sprites are not power-of-two textures to begin with.
It's easy to extend the code to use non-power-of-2 textures though, it just means you have a bit more book keeping. One example way you could do it, is to keep track of what 8x8 texel blocks are in use on the texture, and to search for a large enough free space when adding a new sprite. That'll give you a little wasted space, but will make book keeping much simpler, because you'll be working with a grid system.

This is effectively what I do in my engine (Although I use power-of-2 textures everywhere).

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by Thevenin
Quote:
Original post by Funkymunky
I think you want to use a texture atlas, so that you can have all your sprites on as few textures as possible. That way you can use each sprite just based on its texture coordinates, and you can pack all of them into one big power of 2 texture.


No. That extension takes in power-of-two textures, and forms cumulative power-of-two-textures. My sprites are not power-of-two textures to begin with.
It's easy to extend the code to use non-power-of-2 textures though, it just means you have a bit more book keeping. One example way you could do it, is to keep track of what 8x8 texel blocks are in use on the texture, and to search for a large enough free space when adding a new sprite. That'll give you a little wasted space, but will make book keeping much simpler, because you'll be working with a grid system.

This is effectively what I do in my engine (Although I use power-of-2 textures everywhere).


It becomes a totally different story when you don't use power-of-2 textures.

And no, using 8x8 texal blocks is going to cause too much waste, let alone the performance hit of excess texture binds (since I'd unlikely code the grid system to find optimal slots for placement).

Share this post


Link to post
Share on other sites
It's not too tricky to write some code to pack sprites into a texture atlas dynamically and deal with non-POT sprites. As new sprites are loaded you try and find space in an existing atlas and place it there, or if there isn't enough space you create a new texture atlas and place it in there instead. You'll get some wasted space, but it'll be minimal overall.

Bear in mind that this is 2d bin packing, so it's NP-hard, but there are some simple heristic algorithms that work effectivly. If you load sprites in bursts then "First Fit Decreasing" should work nicely. If you load sprites at various points and not in batches then you might have better results by specifying different bins to deal with different ranges of sprite sizes (eg. a bin for anything under 32x32, a bin for anything with a width < 16, etc. etc.).

Memory allocators often face similar problems (dealing with allocations of varying sizes and avoiding wastage and fragmentation) so googling for algorithms used for those would be a good idea too.

Share this post


Link to post
Share on other sites
No. It's incredibly tricky (alot harder than level 37). Batching cannot be used on my code -- the sprites need to be available as soon as they are allocated. I'm not about to spend the rest of my summer designing a bin-packer that fits my criteria; there is no System.Binpacker already made for me.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thevenin
No. It's incredibly tricky (alot harder than level 37). The sprite sizes are arbitrary -- the only assumption I can make is that they are probably going to be less than 1024x1024 in size.
And they have to be available readily -- meaning no batching.

I think you're over thinking this. Allocate one or more large textures (say, 1024x1024), then after you've loaded your raw pixel data copy it into an unoccupied portion of the texture atlas. If it won't fit in any current atlas because of existing sprites then allocate a new texture and place it in there.

What's wrong with doing this?

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang
I think you're over thinking this. Allocate one or more large textures (say, 1024x1024), then after you've loaded your raw pixel data copy it into an unoccupied portion of the texture atlas. If it won't fit in any current atlas because of existing sprites then allocate a new texture and place it in there.

What's wrong with doing this?


Because finding an unoccupied portion of the texture is astronomically easier said than done.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thevenin
Quote:
Original post by OrangyTang
I think you're over thinking this. Allocate one or more large textures (say, 1024x1024), then after you've loaded your raw pixel data copy it into an unoccupied portion of the texture atlas. If it won't fit in any current atlas because of existing sprites then allocate a new texture and place it in there.

What's wrong with doing this?


Because finding an unoccupied portion of the texture is astronomically easier said than done.

Have you even tried to google for the algorithms involved? If you don't want to write the bin packing yourself there it's quite a common problem so there's lots of code out there. Have you tried implementing anything yourself, or are you just going to sit and complain that it's too hard?

I found this via the first hit on google. Maybe you should grab the source code and read through it. You might learn something.

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang
Have you even tried to google for the algorithms involved? If you don't want to write the bin packing yourself there it's quite a common problem so there's lots of code out there. Have you tried implementing anything yourself, or are you just going to sit and complain that it's too hard?

I found this via the first hit on google. Maybe you should grab the source code and read through it. You might learn something.


Nuclex's binpacker appears to be quite nice; particularly "Cygon". It does an incredible job of encapsulating everything that the user doesn't need to know. I put togethor a quick WinForms app to test the code on the respository, and the results weren't bad:



This should fix the problem. Please post the Google query that led this to be the first result.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this