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 graphics engine, from red robot eyes to synthetic spider webs.
Optimize like it’s 1999
Most mobile graphics hardware uses tiling. On a tiled GPU, it is important to avoid conditions that force a copy from slow GPU memory to fast. These operations can include: render-to-texture, high shader variation, high state variation, or high vertex counts. In particular, it is important to avoid rapid switching between alpha blending, alpha testing, and opaque rendering. Shoot Many Robots used a deferred rendering engine, which lent itself to these requirements (e.g. our rendering was already bucketed into alpha blended and opaque), although we did need to drop our post-processing pipeline for Marvel Puzzle Quest.
A smaller “stuff” count on mobile (e.g. 60 draw calls instead of 600, 100 particles instead of 10,000) also lends itself to graphics processing on the CPU. For Marvel Puzzle Quest, this meant a rewrite of our GPU heavy particle engine to a particle engine with most transformations on the CPU.
The Shoot Many Robots lighting and rendering pipeline was sRGB gamma correct from end-to-end. Unfortunately, sRGB gamma hardware support is not available (without extensions) in OpenGL ES 2.0 and sRGB correction in a fragment shader is too expensive for mobile. We dropped our sRGB pipeline completely for Marvel Puzzle Quest, though a viable alternative is an approximate gamma of 2 (color * color in the shader) or the EXT_sRGB extension, if you can target it.
The more things change
Like most platforms and graphics APIs, draw call overhead in the Open GL ES 2.0 API is high, so batching can be a huge win. For a 2D game like Marvel Puzzle Quest, it is practical to batch exclusively on the CPU. For 3D games or 2D games with high vertex counts, shader instancing or hardware instancing are viable options (if you can target Open GL ES 3.0 or the EXT_draw_instanced extension).
About the author: Dr. JZ can hack a trie and a pine. He prefers C# for the former and a chainsaw for the latter.