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

Login with username, password and session length

 
Advanced search

1401678 Posts in 67940 Topics- by 61496 Members - Latest Member: Lankar5

July 07, 2022, 12:27:28 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Sprite Crammer (might be helpful for HW accelerated 2D games)
Pages: [1]
Print
Author Topic: Sprite Crammer (might be helpful for HW accelerated 2D games)  (Read 2962 times)
SHilbert
Level 0
**



View Profile WWW
« on: May 08, 2008, 02:28:44 PM »

Hey everyone. I've been reading TIGsource for a while, never posted on the forums, but I was working on something for one of my own projects that I thought might be useful to some of you. Basically, it is a program that packs multiple sprite frames onto one or more texture pages, and makes an XML file describing what frames are located where. It can also trim out transparent borders on sprite frames, so you can draw your sprites with nice big frame sizes and still only pay for the video memory you need at runtime, which may be important if you have lots of sprites or are prerendering them from a 3D modeling program. This tool could be useful if you want to reduce texture swaps or save VRAM in your game. (Note that you can only save VRAM if you turn on trimming transparent areas.)

Some other notes:
  • Requires .NET Framework 2.0 or Mono (works on Linux)
  • Fairly good packing heuristic, especially if you allow rotation
  • Sprites that don't fit on one page will overflow to a new page
  • Commandline support for running in a build script
  • Ability to rotate sprite frames to economize on space
  • Ability to colorkey sprite frames "automagically"
  • Can try smaller page sizes for the last page to try to reduce VRAM usage
  • Supports placing borders between sprite frames
  • Can detect duplicate images and let them share space on the output page
  • Source code included, but not particularly well documented Smiley

Here is what the interface looks like (click to enlarge.)



And here are some packed test sprites from Ravuya's game Glow:


The XML file it outputs is pretty simple:
Code:
<?xml version="1.0" encoding="utf-8"?>
<cram-output version="1" pages="2">
  <page id="0" src="cramtest0000.png" size="512,512"/>
  <page id="1" src="cramtest0001.png" size="256,256"/>
  <frame src="0.png" page="0" pos="0,0" size="315,114" offset="2,3" srcSize="320,120" rotated="1"/>
  <frame src="1.png" page="0" pos="459,234" size="13,14" offset="2,1" srcSize="16,16" rotated="0"/>
  <frame src="2.png" page="0" pos="473,186" size="39,64" offset="12,0" srcSize="64,64" rotated="0"/>
  ...
</cram-output>

The only tricky part is the <frame> tag, which has the following attributes:
  • src - Original name of the image file this frame was in
  • page - Index of the page this frame is on
  • pos - Position of top left corner of frame on the page.
  • size - Unrotated, trimmed size of the frame on the page.
  • offset - How much to offset the frame in the X and Y directions when drawing to compensate for trimmed transparent areas.
  • srcSize - Original width and height before trimming
  • rotated - Whether this frame has been rotated to pack better. Rotated frames are rotated counterclockwise.

The current version is here:
http://shilbert.com/files/Cram-1.0b.zip (85 kB)

This is the first release, so please tell me if it's helpful/sucks/has any bugs.  Grin
« Last Edit: May 08, 2008, 03:16:37 PM by SHilbert » Logged

bateleur
Level 10
*****



View Profile
« Reply #1 on: May 09, 2008, 02:32:26 AM »

Do you have any stats on how badly this hurts the compression? (Or does it even improve it in some cases?)
Logged

ravuya
Level 7
**


Yip yip yip yip yip


View Profile WWW
« Reply #2 on: May 09, 2008, 05:34:56 AM »

Depends on how big the sheet is. I'd wager most of the performance improvement comes from not having to change texture batches as often.
Logged

the_dannobot
Level 2
**


View Profile WWW
« Reply #3 on: May 09, 2008, 07:13:57 AM »

Very interesting!  I'm definitely going to take a look at this.

cheers!
Logged

Dannobot on Twitter
SHilbert
Level 0
**



View Profile WWW
« Reply #4 on: May 09, 2008, 09:11:43 AM »

Do you have any stats on how badly this hurts the compression? (Or does it even improve it in some cases?)

If you mean the PNG compression, it appears to take up *less* space after packing because you don't have a hundred duplicate PNG headers anymore, just one.

Here are some tests I just did:

Test #1
Before (100 separate files): 468 KB
After packing: 373 kB + 10.9 kB XML file

Test #2
Before (61 separate files): 334 KB
After packing: 274 kB + 6.2 kB XML file

Test #2
Before (9 separate files): 7.68 KB
After packing: 4.03 kB + 1.1 kB XML file

A better test would be to run PNGCrush on all the PNG files to make sure they're all the minimum size possible first, but this was just a quick first test.

If you mean how much does it increase VRAM usage by packing, that depends a lot on what sprites you have and whether they happen to fit neatly into the sheet, and what options you are using. If you turn on trimming (which removes the redundant transparent borders around frames), then you can actually achieve a reduction in memory usage. But if you don't turn on trimming, it absolutely has to take up more video memory because things are bound to not use every pixel on the texture page due to packing problems. However, it will allow you to draw more in one batch without switching textures in either case.

I don't have enough different sprite sets right now to really get any data that would be useful in predicting how well it does in the "general case." If anyone wants to donate some to test that would be lovely Kiss
« Last Edit: May 09, 2008, 09:20:27 AM by SHilbert » Logged

Sar
Level 3
***


Likes Violins


View Profile WWW
« Reply #5 on: May 09, 2008, 02:11:08 PM »

If you mean the PNG compression, it appears to take up *less* space after packing because you don't have a hundred duplicate PNG headers anymore, just one.

I suspect there's more to it than that. For example, I seem to recall that PNG uses deflate compression, which copes with repeated blocks of data very well. So if you have an animation of ten frames in which only 50% of the sprite changes, then you have 50% of the sprite remaining the same from frame to frame; if you're packing all those frames into the same image, then it can back-reference the previous frame's data when it gets to some of that similar data and not repeat it; something it can't do if the repeated section is in an entirely different file.

But if you don't turn on trimming, it absolutely has to take up more video memory because things are bound to not use every pixel on the texture page due to packing problems.

Not necessarily! OpenGL tends to demand texture sizes are powers of 2, for example - so it you have a 65x65 sprite, then OGL will need a 128x128 texture to keep it in, 'cause it's just too big for the next size down, 64x64. If you use a 512 texture size and pack as many 65x65 textures as you can, you get 49 sprites on that one texture (7 < 512/65 < Cool. 49 sprites as separate textures would normally occupy (49*128*128=) 802816 * bpp bytes of memory; a single 512x512 texture occupies (512*512=) 262144 * bpp bytes of memory. That's a two-thirds saving!

Of course, that's an extreme example, a sprite one pixel too large in each direction to fit into a power-of-two size, but it illustrates the point nicely. ;-)
Logged

Currently working on: Chronicle of Mars
Previous Projects: [Käfer|Tristan and Iseult(TIGS)]
SHilbert
Level 0
**



View Profile WWW
« Reply #6 on: May 09, 2008, 03:33:58 PM »

I suspect there's more to it than that. For example, I seem to recall that PNG uses deflate compression, which copes with repeated blocks of data very well. So if you have an animation of ten frames in which only 50% of the sprite changes, then you have 50% of the sprite remaining the same from frame to frame; if you're packing all those frames into the same image, then it can back-reference the previous frame's data when it gets to some of that similar data and not repeat it; something it can't do if the repeated section is in an entirely different file.
Yeah, that's absolutely true. If you had very redundant sprites you could easily see huge savings from that. I haven't really quantified how much savings is due to capitalizing on redundancy on the sprite sets I tested with, but in any case packing seems to modestly reduce the space used for images on disk, not increase it. Of course, this isn't really a side effect of packing as much as just putting all of your images in one PNG file.

Not necessarily! OpenGL tends to demand texture sizes are powers of 2, for example - so it you have a 65x65 sprite, then OGL will need a 128x128 texture to keep it in, 'cause it's just too big for the next size down, 64x64. If you use a 512 texture size and pack as many 65x65 textures as you can, you get 49 sprites on that one texture (7 < 512/65 < Cool. 49 sprites as separate textures would normally occupy (49*128*128=) 802816 * bpp bytes of memory; a single 512x512 texture occupies (512*512=) 262144 * bpp bytes of memory. That's a two-thirds saving!

Of course, that's an extreme example, a sprite one pixel too large in each direction to fit into a power-of-two size, but it illustrates the point nicely. ;-)
Yes. if you're padding your frames to be able to load them into a power-of-two textures you can stop doing that with this. I was assuming the sprites were already in some square power-of-two format like 64x64 -- i.e., you were previously loading them directly into textures without padding, and then switched over to this. Basically, any runtime memory savings will come from reducing redundant padding, whether it's being excised from the source frames, or whether you're removing the need to pad textures out to power-of-two sizes.

That said, modern graphics cards cope well with rectangular, non-power-of-two textures, from what I understand, but you have to fiddle with extensions (in GL at least) and maybe get a runtime performance hit -- I'm not sure what the cost is since I've managed to avoid having to use them. I think the support is mainly there for things like video rendering.

Anyway, thanks, you just gave me a couple more "marketing" bullet points Smiley
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic