Optimizations

Before we think about optimizing the game we have to evaluate how well it performs. We put an FPSCounter in the GameScreen class, so let's look at its output on a Hero, a Droid, and a Nexus One.

02-17 00:59:04.180: DEBUG/FPSCounter(457): fps: 25

02-17 00:59:05.220: DEBUG/FPSCounter(457): fps: 26

02-17 00:59:06.260: DEBUG/FPSCounter(457): fps: 26

02-17 00:59:07.280: DEBUG/FPSCounter(457): fps: 26

02-17 01:05:40.679: DEBUG/FPSCounter(577): fps: 41

02-17 01:05:41.699: DEBUG/FPSCounter(577): fps: 41

02-17 01:05:42.729: DEBUG/FPSCounter(577): fps: 41

02-17 01:05:43.729: DEBUG/FPSCounter(577): fps: 40

02-17 01:47:44.096: DEBUG/FPSCounter(1758): fps: 47 02-17 01:47:45.112: DEBUG/FPSCounter(1758): fps: 47 02-17 01:47:46.127: DEBUG/FPSCounter(1758): fps: 47 02-17 01:47:47.135: DEBUG/FPSCounter(1758): fps: 46

The Hero struggles quite a bit, but the game is playable at 25fps. The Nexus One achieves around 47 frames per second, and the Droid also reaches 47, which is pretty playable. Can we do better?

In terms of state changes we are not all that bad. We could reduce some redundant changes here and there, for example some glEnable()/glDisable() calls. But from previous optimization attempts we know that that won't shave off a lot of overhead.

On the Hero there's one thing we could do: disable lighting. Once we remove the respective glEnable()/glDisable() calls in WorldRenderer.render() as well as WorldRenderer.renderShip() and WorldRenderer.renderInvaders(), the Hero achieves the following frame rate:

Hero (Android 1.5) 02-17 01:14:44.580 02-17 01:14:45.600 02-17 01:14:46.610 02-17 01:14:47.630

That's quite a bit of improvement and all we had to do is turn off lighting. Special-casing the rendering code for a certain device is possible but we'd like to avoid that. Is there anything else we can do?

The way we render explosions is a little bit suboptimal in the case of an exploding invader. We change the model and texture bindings in the middle of rendering all invaders, which will make the graphics pipeline a little unhappy. However, explosions don't happen often and don't take a long time (1.6 seconds). The measurements just shown were taking without any explosions on screen, so that's not the culprit.

The truth is that we render too many objects per frame, causing significant call-overhead and stalling the pipeline a little. With our current knowledge of OpenGL ES there's nothing we can really do about that. However, given that the game "feels" rather playable on all devices, it is not an absolute must to try to achieve 60 frames per second. The Droid and Nexus One notoriously have a hard time rendering even mildly complex 3D scenes at 60 frames per second. So the last lesson to take away from this is: do not get crazy if your game does not run at 60 frames per second. If it is smooth visually and plays well, you can do even with 30 frames per second.

NOTE Common other optimization strategies involve using culling, vertex buffer objects, and other more advanced topics we won't look into. I tried adding these as well to our Droid Invaders. The effect: zero. None of the devices could benefit from those optimizations. That does not mean these techniques are useless. That depends on a lot of factors and their side-effects, and it's hard to predict how certain configurations will behave. If you are interested, just search for those terms on the web and try the techniques out yourself!

0 0

Post a comment