Welcome back followers of the fearsome!
It’s week 17! This time we get technical with our very own Nick Waanders who’s here to tell us a bit of development wisdom and show all you nice people how we get this game made! Thanks for taking some time out of your coding schedule to fill us all in!
Hey all. It’s been a while since I’ve written a technical blog post. The last time was all about our 3D stuff, but ShellRazer is obviously a 2D game with a lot of things moving on screen. On iOS it can be challenging to make this run smoothly, so today I’ll describe one trick we’ve been using to speed things up: Texture Atlas Generation.
So, the problem is that drawing a ton of different sprites on an iPhone can be really slow, depending on how you do it. If you have separate textures for each sprite, it means that for each sprite you need to set up your vertices, set the active texture, do a draw call. This gets really slow if you have hundreds of things moving on screen. So it would be better if you could combine all these calls into ONE call, wouldn’t it? Well, this is where Texture Atlases come in. The idea of texture atlases is not new, it’s even recommended by Apple. There are many links on the internetz about how to efficiently pack textures into a larger texture, and I pack the textures using this method.
Now, obviously Jesse wouldn’t like to work with large texture atlases and manually picking the correct UV’s for each sprite part, so I had to come up with a way to do all this stuff behind the scenes. For that purpose I created a texture tool that enables me to put textures into a specific texture atlas, resize them, change the compression, etc. The tool spits out an XML file that knows the settings for each texture file in the data directory, and when I build the game, the texture atlases get generated based on these settings.
In this screenshot you can see the texture atlas for the world map (hi-lighted), and the settings. It uses a n RGBA8888 format, and it’s 512×512 in size. As you can see we have many different texture atlases, and they get loaded into memory at different stages in the game. One 2048×2048 texture atlas with an RGBA8888 format is quite big actually (16Mb), but loading on iOS devices is crazy fast, so it’s no problem. I’ll talk more about how to load data quickly in a separate blog post, but if you can’t wait, just look up one of Carmack’s posts about mmap.
Now, one thing I (as a programmer) like is that even in the code the texture atlases are ‘behind the scenes’. The engine only handles texture atlases in the very low-level rendering routines, and everywhere else in the code, I just work with a Texture Resource. All the art assets that refer to the texture atlas already have their UV’s adjusted during the build process, so there is no difficult stuff going on in the engine. Everything complicated happens in the build process and in the editors. I love optimizations like this, all the complexity is moved out of the game into the tools, everything becomes faster, yet all the inputs to the system remain the same.
Ok, so that’s a little bit about the things we had to do in the code to get Jesse’s art running at a decent pace. I could talk about a lot more topics, such as how we sped up our alpha blended sprites by over 400%, how all our loading times are below a second, and how we can change the tuning of the game while playing it, but those are for another time!