Many drops make a river
Published October 28, 2011
I recently discovered that simple looking things can really eat a lot of memory. The player graphic in my game project of instance. I got this dude, you have probably seen him before:
He looks rather unremarkable. However, when you begin to count all the frames of animation this guy requires it boils down to these:
- Stand (12 frames)
- Walk (16 frames)
- Run (16 frames)
- Jump (3 frames)
- Parry (8 frames)
- Combat stance (8 frames)
- Attack (12 frames)
- Death (12 frames)
- Dead (1 frame)
Then multiply these animations by eight since I have eight directions on him, I'll do the math really quick.. (12+16+16+3+8+8+12+12+1)*8=704. That is 704 frames of animation for one guy. Well, that's pretty neat. It should look really smooth then and it does. Then we have the equipment that is pasted on top of the guy, these are rendered in the same manner. So that is 704 frames of animation for each item he is going to carry. Right now I have on him these things:
You can see he have a nice helmet, a sword and a shield. So we need to multiply 704 with 4. The main graphic and the three equipment items. That equals... Yes, 2816 frames of animation.
These frames are all pretty trivial to render in a 3D package (blender in my case) but all these frames needs to be stored in a graphic card friendly manner. What that means is a power of two texture. 512x512, 1024x1024, 2048x2048 and so on. I thought that it would work to have each animation of the character in its own texture image as a sprite sheet. So for instance the attack animation is 12 frames x 8 directions. This resulted in a texture size of 2048x2048. Okay, I bind that texture when it's needed... as well as bind and render the equipment. These textures are identical to the character, only that they contain the helmet, sword or shield. That is four textures with each a size of 2048 x 2048 pixels. Hmm, wait a minute 2048x2048x4 each pixel is 4 bytes (rgb+a) that is 16 MB of texture memory for one animation texture! I got 1+3 textures that needs to be bound (1 character texture + 3 equipment textures) 16MB x 4. That is 64MB of texture memory that needs to be bound and rendered during one frame if the player hits the attack button. This revelation came to me when I noticed that there was a slight frame drop when pressing the attack button.
I looked up a review on geforce6600 (pretty much an average card). In that test it could transfer around 8-10mb worth of textures per frame, I needed 64MB! clearly something had to be done.
Now I load the sprite sheet as a single file but then in system memory I chop it up into smaller manageable sizes, 256x256 or 512x512 depending on situation and upload that to the graphics memory. And presto! The frame drop was gone. :-) This change in drawing architecture resulted in more but smaller texture changes/bindings (around 1MB per texture). However, my Asus laptop still get the frame drop. It is equipped with an nvidia8400MB graphics card (mobile graphics chipset). I guess laptops are inherently slow at data transfer, especially my dirt-cheap laptop.
Sorry about the rather lengthy post... I got more things to write but that will have to wait until next time.
Thanks for reading!