Jump to content

  • Log In with Google      Sign In   
  • Create Account





Many drops make a river

Posted by O-san, 28 October 2011 · 1,124 views

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:

Posted Image

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:

Posted Image

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.

Posted Image

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!




Worth noting when making 2D animations. Thanks for the post :)
If this is a single player game, and that model is unique to the player (that is, he won't see NPCs using the same sprite) why not composite the items onto the player graphics once whenever the player changes his equipment, and then just use that one texture?

Player equips helmet, sword, and shield, so you create custom blank texture, layer the player over it, layer the equipment over that, and use that custom texture (entirely unloading the equipment graphics) until the next time the player changes his equipment.

You can do this in addition to the optimization you've already made, if you still need the extra juice.

Nice post! Posted Image
You mention this "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." I wasn't clear about this statement. What do you mean by chop it into smaller pieces? And you mention this "load the sprite sheet as a single file", did you combine all the equipment together with the character make it as one texture and then load it up?
Thanks for the comments, much appreciated :)

huahsin68: Well, by "chop" I mean that I copy a portion of the image file to smaller memory buffer (512x512 px). Then I create a new texture with this content and upload it to the graphics card. I repeat this process until I have the entire image (2048x2048) in many different textures (512x512px sized textures). I don't combine the different equipment images to one single texture.

The problem with this technique is that a "cut" could be in the middle of the sprite graphic.. so this had to be considered when creating the smaller textures. When the cut was on the graphic I stepped back to the last frame of animation and began the new texture there.

An image tells it better than words:
Posted Image

The line squares are cuts. The second cut can't begin inside the character graphic... it needs to go back a bit, at the beginning of frame 4.
Like the first poster said, this is worth noting when aiming for 2D animations with multiple directions. Thanks for posting!

IMHO, these figures suggest that a better result might be had in rendering your model in the engine instead of "pre-rendering". As a bonus, you can face the model at any angle. Obviously this is a design decision for your game though and I don't mean to step on your toes. Just something that I'd be considering if it were me. :)
Yes I have considered that. The reason I pre-render them is that my first idea was to draw each animation by hand in a 2D drawing application. I began working on this but soon realized that the workload would eventually become to big. That's when I decided to make them in a 3D program and pre-render the animations. I played with the thought that I could do them in "real" 3D too... but I have reconsidered. I feel that the style would become a little bit too mixed for my taste. Also I would have to invest much time in a new system for the characters.
Prerendering has that problem, but I guess the looks won't be the same otherwise, if you get me...
That many frames is going to result in ultra-smooth movement, that's for sure!
DinkSmallwood?

Still, looks like there're lots of duplicates (almost) there.
Hope you don't mind if I edit your image, just to exemplify:
http://i43.tinypic.com/xfp1s0.jpg

Why don't you use horizontally flipped sprites for those? Is it impraticable due to the equipment overlay or something?
Thanks for pointing it out.. There is equipment to consider. All characters will not be as symmetrical as the starter-player graphic.

I also haven't rendered the right hand (it is hard to see in these small images). This is because I am pasting equipment onto the base sprite. I want interchangeable equipment in the hand, the fingers should grip around a sword or an axe. If the right hand was part of the base sprite then the sword would either be pasted on top or behind the hand making it look strange. Now the hand is a part of the sword/axe/dagger sprite allowing the fingers to go around the handle of the weapon. I know I can be a bit nitpicky. :-) However, I might rework this later... it isn't final. It might be more practical to have a small basic handle on the base sprite that all the weapons use.

Latest Visitors

PARTNERS