OpenGL ES 2 for Android – A Quick Start Guide

A few months ago, Kevin Brothaler approached me via e-mail and asked if i could give him a quote for the book (yes, i feel like a “rockstar”). I ended up doing a tech-review and write the foreword for the book.

Kevin did an excellent job at condensing the somewhat beginner-unfriendly OpenGL ES 2.0 API into a nice little book, with a special focus on Android. While you won’t be able to write the next Crysis, it’s certainly a nice introduction to the subject matter, and i can recommend purchasing it. Kevin’s also a splendid guy and put out many free tutorials on OpenGL ES on his site learnopengles.com. You should support his book for this fact alone!

The books not yet on Amazon, but you can get it at The Pragmatic Bookshelf.

Finally, i’d like to highlight the fact that the publisher had no problem putting my name and the name of my book on the cover of Kevin’s book. I did not ask for that at all, they just did it. Awesome!

Libgdx 2012

Time for a review of what happened in libgdx land in 2012!

It all started off with me coming back from San Francisco and having a bit off a cool down period. The first thing i did was rework the entire build system, cause i like pain, and create a way to more easily write JNI bindings manually. The end result was gdx-jnigen, a project that let’s you add C/C++ code directly to your Java source, does some parameter transformations for you (e.g. get pointers to direct Buffers, arrays and so on) and create build files for multiple platforms based on Ant instead of make or cmake. The code inlining is largely inspired by GWT’s JSNI. Here’s an example of how it looks:

   public static native void mulVec (float[] mat, float[] vecs, int offset, int numVecs, int stride) /*-{ }-*/; /*
      float* vecPtr = vecs + offset;
      for(int i = 0; i < numVecs; i++) {
         matrix4_mulVec(mat, vecPtr);
         vecPtr += stride;
      }
   */

Nasty, eh?

Next, i translated all our native code to gdx-jnigen and created a couple of extension projects. The first one was gdx-audio, including decoders for MP3, Ogg and Wav, to get raw PCM data, Soundtouch to do time stretching and pitch manipulation and KissFFT for fourier transforms. gdx-jnigen turned out to help tremendously with this and made working on the bindings almost effortless.

After the excourse into native land it was time to work on battery saving a little. We introduced non-continuous rendering and i reviewed the battery usage of one of my apps to give some insight into what to expect.

Rapid development was one of the biggest reasons why i started working on libgdx. Tools like texturepacker that run offline hinder me a little. Always having to start a preprocessing process before being able to view the results isn’t fun. That’s why i implemented PixmapPacker, allowing me to pack textures on the fly during runtime. This of course has a few downsides, e.g. worse packing behaviour and additional loading times, but for rapid prototyping it helps a lot.

Freetype support, to load arbitrary TTF fonts at runtime, was next on my list of things to add. With gdx-jnigen and the PixmapPacker that was a rather simple task, even though there where initial hiccups in terms of memory leaks and similar issues.

We also extended our file handling with a new file type, called local. Don’t ask…

I finally had time to work on the HTML5/WebGL backend based on GWT, triggered by PlayN’s availibility on that platform (can’t have them steal our wind! :). It took a lot of pain and tears, e.g. i had to add reflection to GWT for Nate’s fancy UI stuff to work, among other things. Ultimately it turned out to work pretty well, and there are already a couple of games running on WebGL and libgdx and few of them made it to facebook.

We didn’t discover any big Android issues this year, the platform seems to be rather stable now, safe for some device manufacturers incapability of providing working MP3 and OGG decoders. Well, and this little nasty bugger. Android counts direct Buffers against the Java heap, which means Java based games have a clear disadvantage compared to native code games when it comes to available RAM. We “fixed” that in libgdx.

We started the documentation initiative and are rather happy with it’s outcome so far. Our wiki has grown considerably and we also received quite a few pull requests for Javadoc additions. Documentation is an on-going effort, and we strive to improve it all the time.

In May we discovered that AppBrain reports us to be the #1 game development framework on Android. All of these numbers are of course to be taken with a grain of salt, but we seem to make an impact. Unity has closed the gap somewhat. I’d attribute this to the Unity guys offering the mobile licenses for free for a limited time. I guess there’s room for both.

In the light of our growing user base, i felt it necessary to overhaul our website. The end result is as good as i can make it with my limited web development skills. Not stellar, but functional. And most of all, all information is gathered in a single place, including Twitter and the blog.

In June i started working on our iOS backend. Instead of Avian, i now took the same road as PlayN, using Michael Bayne’s IKVM fork and MonoTouch. This became a real team effort, with Gemserk (Arielsan, Ruben), Noblemaster Games and others chiming in and providing tons of improvements and fixes. A couple of games have already been published to the App store. I’m currently working on getting things integrated in the gdx-setup-ui.

Nate started his great refucktoring of the scene2d API in June. A little later we had the “GREAT MERGE”, when we released 0.9.6 stable with the old scene2d, and switched our trunk to the new API. Initial reactions where mixed, but after a while the dust settled and the overall sentiment seems to be in favor of all the nice new things. Shiny wins.

In August we had our diaspora to Git/Github, much to the joy of Nate who had to correct his workflow. On the upside, we received around

We also deprecated our Jogl backend in august. It was based on the old 1.1 release and a big maintenance burden. Given the completeness and stability of the LWJGL backend we decided to kill it. Sorry Jogl, maybe we’ll meet again in the future.

One of the biggest helpers in getting libgdx out to the people is the gdx-setup-ui. It makes setting up the multiple projects for Eclipse extremely simple. Our good soul and Swing magician Obli is constantly improving the app, showing that you can actually create nice UIs with Swing. Obli’s also been contributing other things like the box2d editor.

I was invited to Apps World 2012 to speak on HTML5 and mobile gaming, as well as my book and libgdx. It was a blast! I meet with a few libgdx folks there, including Badly Drawn Rod and Exobyte. Nate and me have been invited to Istanbul earlier next year, maybe there will be more speaking oportunities coming up. If you are an organizer, feel free to ping us. We like talking without end!

We also extended our functionality on Android by adding a Livewallpaper backend as well as a Daydream backend. Ouya is sending us a dev kit so we can get some Ouya specific things into our APIs as well. Good times.

To round things off, we (almost) finished Maven integration for libgdx. I actually prefer using Maven myself for various reasons, so this is not good for our users but good for myself as well. Stay tuned for more updates on this in the coming weeks.

Of course, there’s a lot more that happened, from new contributors joining the project, to tons of bug fixes, sleepless nights, hangouts and so on. I guess the above gives a good indication of how much we achieved this year.

Happy new year, and let’s make 2013 even more successful!

AssetManager explained

A long time ago i promised to write an article on our AssetManager. Well, today i finally found the time, so here we go.

Why would i want to use the AssetManager?

If your game is very simple, and loading resources doesn’t take a lot of time you don’t want to use the AssetManager. In all other cases i’d recomend using it due to the following nice behaviours:

  • Loading of most resources is done asnychronously, so you can display a reactive loading screen while things load
  • Assets are reference counted. If two assets A and B both depend on another asset C, C won’t be disposed until A, B and C have been disposed. This also means that if you load an asset multiple times, it will actually be shared and only take up memory once!
  • A single place to store all your assets.
  • Allows to transparently implement things like caches (see FileHandleResolver below)

Still with me? Then read on.

Creating an AssetManager

This part is rather simple:

AssetManager manager = new AssetManager();

This sets up a standard AssetManager, with all the loaders libgdx has in store at the moment. Let’s see how the loading mechanism works.

Loading Assets

To load assets, the AssetManager needs to know how to load a specific type of asset. This functionality is implemented via AssetLoaders. There’s two variants, SynchronourAssetLoader and AsynchronousAssetLoader. The former loads everything on the rendering thread, the later loads parts of the asset on another thread, e.g. the Pixmap needed for a Texture, and then loads the OpenGL dependent part on the rendering thread. The following resources can be loaded out of the box with the AssetManager as constructed above.

  • Pixmaps via PixmapLoader
  • Textures via TextureLoader
  • BitmapFonts via BitmapFontLoader
  • TextureAtlases via TextureAtlasLoader
  • TiledAtlases via TiledAtlasLoader
  • TileMapRenderers via TileMapRendererLoader
  • Music instances via MusicLoader
  • Sound instances via SoundLoader

Loading a specific asset is simple:

manager.load("data/mytexture.png", Texture.class);
manager.load("data/myfont.fnt", BitmapFont.class);
manager.load("data/mymusic.ogg", Music.class);

These calls will enqueue those assets for loading. The assets will be loaded in the order we called the AssetManager#load() method. Some loaders allow you to also pass parameters to them via AssetManager#load(). Say we want to specify a non-default filter and mipmapping setting for loading a texture:

TextureParameter param = new TextureParameter();
param.minFilter = TextureFilter.Linear;
param.genMipMaps = true;
manager.load("data/mytexture.png", Texture.class, param);

Look into the loaders mentioned above to find out about their parameters.

So far we only enqueued assets to be loaded. The AssetManager does not yet load anything. To kick this off we have to call AssetManager#update() continuously, say in our ApplicationListener#render() method:

public MyAppListener implements ApplicationListener {
 
   public void render() {
      if(manager.update()) {
         // we are done loading, let's move to another screen!
      }
 
      // display loading information
      float progress = manager.getProgress()
      ... left to the reader ...
   }
}

As long as AssetManager#update() returns false you know it’s still loading assets. To poll the concrete state of loading you can use AssetManager#getProgress(), which returns a number between 0 and 1 indicating the percentage of assets loaded so far. There are other methods in AssetManager that give you similar information, like AssetManager#getLoadedAssets() or AssetManager#getQueuedAssets(). You have to call AssetManager#update() to keep loading!

If you want to block and make sure all assets are loaded you can call:

manager.finishLoading();

This will block until all the assets that have been enqueued are actually done loading. Kinda defeats the purpose of asynchronous loading, but sometimes one might need it (e.g. loading the assets needed to display the loading screen itself).

Getting Assets

That’s again easy:

Texture tex = manager.get("data/mytexture.png", Texture.class);
BitmapFont font = manager.get("data/myfont.fnt", BitmapFont.class);

This of course assumes that those assets have been successfully loaded. If we want to poll whether a specific asset has been loaded we can do the following:

if(manager.isLoaded("data/mytexture.png")) {
   // texture is available, let's fetch it and do do something interesting
   Texture tex = manager.get("data/mytexture.png", Texture.class);
}

Disposing Assets

Easy again, and here you can see the real power of the AssetManager:

manager.unload("data/myfont.fnt");

If that font references a Texture that you loaded manually before, the texture won’t get destroyed! It will be reference counted, getting one reference from the bitmap font and another from itself. As long as this count is not zero, the texture won’t be disposed.

Assets managed via the AssetManager shouldn’t be disposed manually, instead call AssetManager#unload()!

If you want to get rid of all assets at once you can call:

manager.clear();

or

manager.dispose();

Both will dispose all currently loaded assets and remove any queued and not yet loaded assets. The AssetManager#dispose() method will also kill the AssetManager itself. After a call to this method you should not use the manager anymore.

And that’s pretty much everything there is. Now for the nitty gritty parts.

I only supply Strings, where does the AssetManager load the assets from?

Every loader has a reference to a FileHandleResolver. That’s a simple interface looking like this:

public interface FileHandleResolver {
   public FileHandle resolve(String file);
}

By default, every loader uses an InternalFileHandleResolver. That will return a FileHandle pointing at an internal file (just like Gdx.files.internal(“data/mytexture.png”). You can write your own resolvers! Look into the assets/loaders/resolvers package for more FileHandleResolver implementation. One use case for this would be a caching system, where you check if you have a newer version downloaded to the external storage first, and fall back to the internal storage if it’s not available. The possibilities are endless.

You can set the FileHandleResolver to be used via the second constructor of AssetManager:

AssetManager manager = new AssetManager(new ExternalFileHandleResolver());

This will make sure all default loaders listed above will use that loader.

Writting your own Loaders

I can’t anticipate which other types of resources you want to load, so at some point you might want to write your own loaders. There are two interfaces called SynchronousAssetLoader and AsynchronousAssetLoader you can implement. Use the former if your asset type is fast to load, use the later if you want your loading screen to be responsive. I suggest basing your loader on the code of one of the loaders listed above. Look into MusicLoader for a simple SynchronousAssetLoader, look into PixmapLoader for a simple AsynchronousAssetLoader. BitmapFontLoader is a good example of an asynchronous loader that also has depdendencies that need to be loaded before the actual asset can be loaded (in that case it’s the texture storing the glyphs). Again, you can do pretty much anything with this.

Once you are done writting your loader, tell the AssetManager about it:

manager.setLoader(MyAssetClass.class, new MyAssetLoader(new InternalFileHandleResolver()));
manager.load("data/myasset.mas", MyAssetClass.class);

Resuming with a Loading Screen

On Android your app can be paused and resumed. Managed OpenGL resources like Textures need to be reloaded in that case, which can take a bit of time. If you want to display a loading screen on resume, you can do the following after you created your AssetManager.

Texture.setAssetManager(manager);

In your ApplicationListener#resume() method you can then switch to your loading screen and call AssetManager#update() again until everything is back to normal.

If you don’t set the AssetManager as shown in the last snippet, the usual managed texture mechanism will kick in, so you don’t have to worry about anything.

And this concludes the long awaited article on the AssetManager.