From Robots to Superheroes: Content

28th October 2014 Joseph Zupko

At Demiurge Studios, we first created a game engine to power a PC/PSN/XBLA 3D run'n gun (Shoot Many Robots). Since then, our engine has evolved into a broad internal core technology with support for seven platforms. Recently it has expanded with "Games as a Service" features such as content patching and just-in-time content delivery to drive our flagship 2D match 3 (Marvel Puzzle Quest). What follows are some observations and lessons learned on the journey of one part of this technology, our content pipeline, from robot meshes to comic book covers.

Texture Compression

Android texture compression is the most complicated piece of our content processing on mobile due to the hardware specific nature of most available texture compression formats. For Marvel Puzzle Quest, we chose to avoid these formats (PVRTC, ATC, and S3TC) and use the (mostly) standard ETC1 format for texture compression exclusively. To support textures with alpha (ETC1 does not support an alpha channel), textures below a certain resolution are stored uncompressed as GL_RGBA. For textures above that resolution, we use two ETC1 textures, one that contains color data and a second that contains alpha data.

To allow for a unified shader for all texture possibilities (uncompressed, ETC1 opaque, ETC1 + ETC1 alpha), we construct the final texture color as:

    vec4 color_texture = texture2D(color_texture_sampler, tex_coords.xy);
    vec4 alpha_texture = texture2D(alpha_texture_sampler, tex_coords.xy);
    return vec4(color_texture.rgb, color_texture.a * alpha_texture.g);

For uncompressed or ETC1 opaque, alpha_texture_sampler is sampled from a 1x1 pixel white opaque (255, 255, 255, 255) texture.

Texture Resolution

A naive expectation in our move to mobile was that content would be “less complex” and our content pipeline would be taxed less. We’ve found the opposite to be true. A 2048 x 2048 background texture for a 720p Xbox 360 game is still 2048 x 2048 (or larger) on a 1080p phone (or a tablet with all the pixels).

PVRTC compressors are slow (and our only texture compression option for iOS) and we often generate two ETC1 textures for our Android builds (see our usage of ETC1 + ETC1 alpha). This initially caused a spike in our texture build times. To address this, we switched from nvidia-texture-tools to crunch for our DXTn (PC) and ETC1 (Android) compression. crunch has a very fast multithreaded compressor, which more or less compensated for the extra time we spent generating two ETC1 textures on Android.

There is (as of this writing) no “lighting fast” PVRTC compressor, so we addressed our iOS texture build times by compressing as infrequently as possible. On Shoot Many Robots, our pipeline required a full content cook at various stages and in various situations. For Marvel Puzzle Quest, we eliminated the bits and baubles that required this. Now, all texture builds are done incrementally, only in response to a change to the source image.