Hi, I’m having memory issues with my game, it has a lot of images so I created them in 8 bits to reduce memory but I realized that all the images are stored on memory with much more size than the original. There is any way to reduce it?
OpenFL decompresses your images because the renderer needs each individual pixel’s RGBA values. You can’t draw a pixel without knowing what color to use! Which means the image needs to be in bitmap (uncompressed) format, with the full 32 bits of information for every single pixel.
Actually… if you really wanted to store the compressed image in memory, you could try decompressing it on a per-pixel basis. But given how many pixels you’re drawing (potentially millions for a fullscreen app), that would be super slow. Better just to do it once and store the results.
Well, it would be slow for most compression schemes. Decompressing an 8-bit color palette is literally just one extra lookup. This is fast enough to render efficiently, and in fact that’s exactly how many old video game consoles worked. I don’t think OpenFL has an option for this, but you could probably do it with a custom shader.
But before getting into that, here’s the important question: do all of your images use the same palette? If not, then palette-based rendering won’t work.
Hi! Thanks for the answer. I understand that the images have to be decompressed, but the difference its very big, for example for a 63KB image the space in memory is 13MB, perhaps I am doing something wrong. Maybe there’s another way to store them?
We do not support 8-bit in-memory textures currently, but this optimization could be done for OpenGL targets. It would not work for software targets without taking care, because canvas (for example) expects
drawImage to work with ARGB data, otherwise you need to copy pixel-by-pixel, which is very slow.
But there is any way to show the images without keeping all that data in memory? I just realized that if I make a swf with the image inside and add the movie clip, the memory does not increase.
Out of curiosity, what are the dimensions (width + height) of the image? And how did you find the 13mb memory increase? If you are just using the taksmanager as a reference then be aware that there are other things allocated beside your image.
The image is very big because it is an animation (11000 x 300 approx) I found the memory increase making memory dumps using the chrome developer tool.
Having in mind the image dimensions the 13mb increase its totally reasonable (assuming 32 bits per pixel). But I don’t understand the difference using the image directly or loading a movieclip from a swf.
SWF files are compressed, perhaps it is able to render the compressed version, or does not decompress until specific frames are used
There are a couple of swf compiler flags listed here: https://haxe.org/manual/compiler-usage-flags.html ones that may be useful are:
Perhaps play around with them and see if singmajestry is right!
Thanks! So if there is no way to use compressed images, perhaps the best way to reduce memory is using the images within a sfw?
You can use DXT format (with ATF). It will upload your graphic into your GPU without using your RAM.
I’m open to supporting compressed
BitmapData types as well, I think we’re closer to making that work now
Sorry for the late reply
Is this option available for openfl/HTML5?
That would be awesome
I think something like this may be possible:
var context3D = stage.stage3Ds.context3D; var atfData = Assets.getBytes ("assets/texture-dxt5.atf"); var texture = context3D.createTexture (256, 256, Context3DTextureFormat.COMPRESSED_ALPHA, false); texture.uploadCompressedTextureFromByteArray (atfData, 0); var bitmapData = BitmapData.fromTexture (texture);
This doesn’t work on the Flash target, but should work on other OpenFL targets running an OpenGL renderer.
The key is that you cannot read/write pixels in this instance, or
bitmapData.draw or use other software rendering, but it should be compressed for the GPU
Excellent thank you! I will try that and I will post the result of the memory usage!