Skip to main content
GameDev.net gamedev.net
🔒 Locked

Textures

Started by Tanish1 Oct 18, 2008 at 10:36 PM 7 replies 1.8k views
Original Post
Tanish1
Tanish1
I am working on a 2D iso game and the sprites use textures. For each monster there are 5 animations so 5 textures that have around 64 images per texture. My question is how do you manage all of those? Loading that many textures into memory for the sprites makes the game require about 700MB of ram. I know ram is cheap but my game is tiny compared to many so how do they load all their textures and don't break our machines? I heard of texture caching but I tried it and loading texture during run time didn't work out so well? I am programming in VB with DirectX using sprites and textures.
undead
undead
The simple answer is: if you already didn't you could reduce the amount of memory required by disabling mipmapping. That shouldn't hurt as 2D iso games usually don't scale sprites height according to distance.

As for the detailed one, 64 images per texture can be organized in an 8x8 grid. In we assume a maximum texture size of 4096x4096, the single frame has a size of 4096/8 = 512x512. Do you really need a sprite to be so huge?

As for memory organization If I couldn't fit all animations into a single texture, I'd probably implement a custom sprite class supporting 3D textures. Each animation would point at a different slice of the 3D texture. The formula is easy, suppose you have 5 animations numbered from 0 to 4. The correct slice can be sampled by calculating animation_number/5 and passing this value to the shader.

Another way to diminish the amount of texture memory is to parametrize sprite rendering so that two enemies, a green one and a red one, share the same texture and the different color is somehow calculated in the shader according to a parameter.

Probably I have misunderstood your sentence but texture caching is not about loading textures when you need it, it is about preventing "unused" textures to be stored in video mem. It is simply accomplished by drawing only the things you see from a certain point of view. That wouldn't reduce the memory required to store ALL your texture, it would just ensure that if only a single sprite is visible the amount of memory required to render THAT FRAME will be limited to THAT texture. Since in general each frame is similar to the following one, you get a significant performance improvement, as only a few textures which are "visible" will need to be stored in video mem. If you draw everything and expect the API to do the culling for you, you have to hope all textures fit into video mem otherwise you'll probably waste a lot of time transferring textures you don't see.
Tanish1
Tanish1
the sprites aren't 512x512 the overall action sprite is about that.

Each action is about 64x64 with 8x8 grid so the overall size of that sprites texture is 512x512 but that is for 1 full action. The problem is each monster has 5 animations so 5 textures per creature with 70 total different creatures in the game so 350 textures of 512x512 and that is just the monsters.

Putting all the animations into 1 large texture and loading that into system memory and then slicing each one out, is that really fast enough and saves enough memory?

I know my game is tiny compared to most games and especially 3D games that should have 1000's of texture how in the world do they manage?

I've looked through the D3DPOOL_MANAGED and other pool options but I'm still not coming up with anything solid?
r691175002
r691175002
Would it be possible to mirror some animations (such as walking) so that they can be used for more than one direction?
jorelmb
jorelmb
Well, you could use a compressed format for your textures like DXT. There are five modes for it depending on the needs, but they really save a lot of RAM.

Texture Compresion

And they are supported natively by DirectX...
------------------------------"Carpe Diem!""Failure is the prequel of success".-:Jimbo:-.
swiftcoder
swiftcoder
Quote:
Original post by Tanish1
I am working on a 2D iso game and the sprites use textures. For each monster there are 5 animations so 5 textures that have around 64 images per texture. Loading that many textures into memory for the sprites makes the game require about 700MB of ram.

Each action is about 64x64 with 8x8 grid so the overall size of that sprites texture is 512x512 but that is for 1 full action. The problem is each monster has 5 animations so 5 textures per creature with 70 total different creatures in the game so 350 textures of 512x512 and that is just the monsters.
You seem to have doubled you total size, I only get about 350 MB - a 512x512 image @ 8-bit RGBA is 1 MB

Do you ever have all those images on screen at once? If not, the simple solution is to only load the creatures you will encounter in each level/area.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
undead
undead
Swiftcoder is right, a full 32bit RGBA (not mipmapped) texture is "only" 1MB.

DXT compression can help but sometimes there's a visible loss of quality, being a 2D game I don't know if it's acceptable for you.

As swiftcoder suggested load only the sprites you can see in that level, and as I said in my first reply cull enemies outside screen.
Ashaman73
Ashaman73
Whenever I have to handle large amounts of data I use caches combined with dynamic loading. In this case I would suggest the following:

1. create a list of "texture_proxies", each texture proxy contains the name of the real texture and a reference to a "loaded" texture (could be null).
2. Reserve X(=100,200...) textures of your target size (512x512) , depends on hardware and/or configuration, we call this set of textures our "texture pool".
3. We need an in_use_list, which contains all texture proxies which refers a loaded texture (this list is empty at the beginning).
4.1. whenever you want to access a texture you access its proxy first, if the proxy refers a loaded texture , use it and move your texture proxy to the first position of your in_use_list.
4.2. If your proxy doesnt contain a texture do the following:
4.2.1 texture pool still contains textures:
- remove one texture from pool
- assign it to your proxy
- load your texture data and copy it into the texture
- add this texture proxy to your in_use_list (as first element in list)
4.2.2. texture pool is empty:
in this case we reuse the least recent used proxy (LRU cache):
- remove the last texture proxy in your in_use_list
- remove the texture from the texture proxy
- assign the texture to your new texture proxy
- load your texture data and copy it into the texture
- add your new texture proxy to your in_use_list (as first element in list)

The idea is, that you didn't need all your textures in memory all the time (will you see your 70 monster in one area, or will you encounter just a few monsters at each area/level ?). With this approach you could handle 1000 of monsters as long as the don't appear in one area.
Last tip: don't make your texture pool size too small, else you will encounter cache trashing.

--
Ashaman
Tanish1
Tanish1
Thanks for all the answers and help.

I have begun working on the caching system to only load what is needed in general areas.

On a side the 756x756 texture was taking about 2-3 MB. I thought the formula was wxhx4(for 32 bit)/1000 = kb of RAM needed for that texture?

I thought I turned off mipmapping by setting the value in the LoadTexture function to 1 since the guide said 0 would default it to what was needed? Is that not the right way to turn off mipmapping?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.