Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# or C++ game: many 16 color images loaded into RAM. Efficient solution?

I am in the planning stages of creating a fighting game and am unsure how to handle one issue relating to memory.

Background info:
- Still debating whether to use C# (XNA) or C++. We do not want to commit to either until we have explored how to solve this problem in both languages.
- Using a max of 256MB RAM would be great if possible.
- Two characters will be present at a time, and these characters can only change between battles. There is time to load/free memory between battles, but the game needs to run at a constant 60 drawn frames per second during combat. Each frame is 16.67ms
- The total number of images per character is in the low hundreds. Each image is roughly 200x400 pixels. Only one image from each character will be displayed at any given moment.

Uncompressed, each image takes roughly 300kb from my calculations; upwards of 100MB for a whole character. This is pushing too close to the 256MB limit given that memory will be needed for some other resources as well.

Since each image can be made with a total of 16 colors. Theoretically I should be able to use 1/8th the space if I can take advantage of this. I've looked around but haven't found any word of native support for paletted images. (Storing each pixel using fewer bits that each map to a 32-bit RGBa color)

We tried using DXT compression, however, the compression artifacts are quite noticeable.

I was considering making my own file format with 4 bits per pixel (and some extra palette info), loading all the images of this new format into RAM before battle, and then when drawing any specific image, decompress only that image into a raw image so it can be rendered properly. I don't know if it's realistic to perform so many assignment operations (appx 200x400 for each character = 160k) each frame. It sounds very hacky to me.

Does anyone have advice on whether my solution sounds reasonable, and if there is perhaps a better one available?

Thanks so much!

(I also attempted to use an image with only 1 channel, then use a shader to perform a series of if statements to translate various values into other colors. Unfortunately, there were too many lines of code for the shader. It is also rather hacky and does not scale well.)

like image 568
Codin' Wolf Avatar asked Jan 03 '11 01:01

Codin' Wolf


2 Answers

Use S3 Texture Compression (aka DXTn) instead. S3TC lets you store textures at 4 bits/pixel or 8 bits/pixel, and it's supported natively by graphics cards. You don't have to worry about decompressing it on the fly, since the graphics card does that.

DirectX has very good support for S3TC, in both C++ and C#.

like image 60
Adam Rosenfield Avatar answered Sep 27 '22 16:09

Adam Rosenfield


If you want to target the XBox 360 and don't have a proper (full blown) devkit, then C# is your only option. When starting out XNA certainly makes doing things a lot easier for you, especially if you're just doing 2D for now (and takes care of a lot of other things you don't need to worry about right now).

As for the memory constraints issue, suggestions to get it down:

  • Use the 1555 texture format to halve the size (although you'll only have 1 bit of alpha)
  • Do the different images have any common sections? Could you render the character using a number of smaller tiles rather than one large one (i.e. a grid of 2x4 or more). Most likely you'll have a lot of empty space in the corners that could be shared between most images and this will yield a good saving (I've just spotted someone already mentioned this via spritesheets - although this should be a lossless option to save memory).
  • You mention already trying to fake palletised textures. Instead of IF statements, you could have a 2nd texture that contains the palette colours and use the value you get from the first texture as a texture co-ordinate to lookup into the 2nd texture via a pixel shader (the 2nd texture is just a 1D texture of 32-bit colour values).
  • Given the power of modern processors and depending on what else your doing at the time, you may well have enough spare resources to decompress frames on the fly for the two characters into textures ready for rendering (especially with multi-core). You'll need to at least double-buffer the textures to stop the CPU blocking waiting for the GPU to finish using them from the previous frame though.

You could also combine some of these options to save more.

like image 40
Roger Perkins Avatar answered Sep 27 '22 16:09

Roger Perkins