How I doubled Android 3D game scene quality with 4 lines of code

Posted on:February 01 2013

The feature to generate Android apps is new in CopperCube, and if you published an Android app with lots of textures, polygons and character data using CopperCube version 4.0, it was possible that you would get something like this instead of a working app:

This happened when the app was running out of memory. Huge scenes with lot of textures need a lot of memory. Imagine, a texture with 512x512 pixels, standard 32 bit depth per pixel takes not 1MB of memory as you would expect, but about 1.4MB of memory, because of all the mipmaps needed (= 1048576 + 262144 + 65536 + 16384 + 4096 + 1024 + 256 + 64 + 16 + 4). With lots of and even bigger textures, this gets very much quickly. You probably already have seen the CopperCube backyard demo scene (Flash or WebGL version):

Creating an android app from that would for example cause that app to crash. No wonder, it is a really big scene with 82 high resultion textures and 4 lightmaps, and additionally an animated 3D character walking in that scene which has 4000 polygons and 36 joints (which is an unneccessary high amount of joints, dear 3D artists, btw) and 2100 animation keys. But since I released CopperCube 4.0.1, even this one runs smoothly on an Android device:

Great, eh? In fact, Android apps generated by CopperCube now start up much faster and require about half the amount of memory needed. How did I manage to do that?
The short answer: Lazy texture loading. It's a very, very small and simple change to the rendering engine, but this causes a major memory bottleneck to go away, and causing a lot of apps to work nicely now.
When starting a game or 3D app, you ususally do this:
  • Load 3D scene data
  • Init 3D engine, create shaders and similar
  • Load textures and sounds
  • In a loop: animate 3D scene, calculate Game AI and draw the current scene.

But I've now changed this to the following:
  • Load 3D scene data
  • Init 3D engine, create shaders and similar
  • In a loop: animate 3D scene, calculate Game AI and draw the current scene, load textures and sounds only when needed to be drawn and not loaded yet.

By this change the loading process of course is much faster, and even better: The textures get loaded later, when there isn't much other stuff at the same time in memory (like currently loaded and transformed other data), cirumventing the memory bottleneck. And should the app run out of memory again, then you are able to put some not recently used textures out into the trash and load them later in when they are used again, if ever, by the same process.
For the Android port of the CopperCube engine, this was a change of 4 lines of code. But apps now start about 4-10 times faster, and can handle about twice as many textures. Everything of course depending on the specific app. But it's a really nice step forward with very little effort. Sometimes its the simple things. :)


Truly awesome! Thanks for such a quick and useful update.
mrm design
2013-02-01 15:19:00

Have you tried texture compression? 1.4MB with mipmaps is pretty high for a 512x512 RGB texture. I wrote an article on my site about doing it if you're interested (link below).
Do you perform any checks to make sure all 82 textures aren't loaded at once, just later on in the program? Or do you unload textures as necessary?
2013-02-01 23:47:00

Yes, already thought about this. ETC1 is the only viable option there, and I'm probably going to add support for that somewhere in the near future.
2013-02-02 07:00:00

This is very helpful. Thanks for this.
2013-02-04 07:32:00

Add comment:

Posted by:

Enter the missing letter in: "Interna?ional"




Possible Codes

Feature Code
Link [url] [/url]
Bold [b]bold text[/b]
Quote [quote]quoted text[/quote]
Code [code]source code[/code]