I am working on my dragon simulation mobile game and I am at the stage of adding a terrain to the game.
I optimized the terrain render for my iOS devices but on my Android device I was getting bad performance.
Understanding texture size and performance is kind of elusive. I was being told many times that big textures are bad but I was never able to find the correlation between texture size and performance.
I am still not sure what is the correlation between texture size, bandwidth and performance on mobile devices and I am sure it’s a complex one.
However, I did find out something else.
As I mentioned, my first attempt to copy the OpenGLES shaders from my iOS code to my Android code gave me poor results. The same scene that ran at 60 FPS on my iPod was running on 25 FPS on my Android phone.
This is how the scene looked like on my Android phone:
For the terrain I am using two 2048×2048 ETC1 compressed textures. One for the grass and one for the rocky mountain.
Maybe my phone’s performance is really not as good as my iPod? But then, something was missing.
On my iPod I was already using mipmapped textures while on the first attempt of the Android version I didn’t use mipmapped textures.
Mipmapped textures are texture which not only contain the texture itself but also all (or some) of the smaller versions of the same texture image.
If you have a texture of size 16×16 pixels then a mipmapped texture will contain both the 16×16 image but also the 8×8, 4×4, 2×2 and 1×1 resolutions of the same image.
This is useful because it’s hard to scale down a texture on the GPU without losing details. The mipmapped images are precalculated offline and may use the best algorithms to reduce the image.
When rendering with mipmapped textures the GPU selects the mipmapped image that is the most suitable for the current scaling in the scene.
But apart from looking better, there is another advantage. Performance.
The same scene using mipmapped version of the 2048×2048 textures runs a lot faster than before. I could get a scene render at about 50 to 60 FPS.
The reason for that is that textures have a 2D spatial cache.
In this scene the mountain and grass textures are scaled down considerabley. This in turn makes the GPU sample the textures in texel(texture pixels) that are far from each other making no use of the cache.
In order to make use of the cache the sampling of the texture must have spatial proximity.
When using the mipmapped version of the texture a much smaller layer of the 2048×2048 texture was sampled and thus it was possible to make use of the cache for this specific image.
For the sake of completion, here is the scene with the mipmapped textures: