I’ve started work on porting Crush the Castle from the iPhone/iPod Touch to the iPad. I thought I’d share some of the technical issues I’ve encountered while expanding the Crush the Castle renderer from an OpenGL 1-based system to a system that supports both OpenGL 1 and OpenGL 2.
When my daughter wants the iPad she asks for “the huge iPod.” That’s about right. Inside and out, the iPad is basically an exploding iPod.
One difference, though, is the graphics hardware. Older iPhones and iPod Touches used simpler graphics hardware that’s built on OpenGL ES 1.1. That’s the platform I built Crush the Castle on. The iPad uses a more modern graphics pipeline that’s built on OpenGL ES 2.0. From a programmer’s perspective, the big difference here is programmable shaders.
So my first job in bringing Crush the Castle to the iPad is upgrading the renderer from a fixed function, OpenGL ES 1.1-style system to a programmable, OpenGL ES 2.0-style system. If you’ve ever been interested in learning graphics programming with shaders, follow along with me and perhaps we can learn together.
In the articles that follow I’ll talk about iPhone/iPod Touch/iPad development. But much of what I do would apply to anyone working with OpenGL on any platform—PC, Mac, PS3, whatever. I’ll talk about OpenGL “ES”—the trimmed down, mobile version of OpenGL. But in practice, Crush the Castle runs on non-”ES” versions of OpenGL, so the “ES” is immaterial. I’m also working in C++. If you’re working in a different language, like Java, C#, or Objective-C, you’ll have to read between the lines a bit. But I’m mostly dealing in terms of design patterns that aren’t specific to any particular language, so the leap shouldn’t be too far.
Creating an Abstraction Layer
The first step in bringing Crush the Castle into the world of OpenGL 2 was refactoring my fixed-function renderer to use vertex and pixel shaders. In Crush the Castle, all rendering is handled through a class called—naturally enough—Renderer. This class offers functionality for setting up transforms, creating and setting vertex buffers, setting textures, handling render state (like whether alpha blending is turned on, for example), and of course initiating the actual rendering.
In this initial phase I wanted to keep the interface to the Renderer class as unchanged as possible. I wanted client code—the game code that asks for rendering to be done—to remain untouched wherever possible.
Moreover, I wanted to keep the current fixed function renderer completely intact. After all, Crush the Castle isn’t leaving the iPhone—it’s just gaining new platforms. So my Renderer class should support both OpenGL 1 and OpenGL 2, When you run the game it will ask the hardware whether GL 2 is available. If it is, it will use it. If it isn’t, the game will fall back to GL 1.
The first thing I did was to refactor my Renderer into an abstraction layer. An abstraction layer is a design pattern in which a single class “stands in” for one or more other classes that do the actual work. The “stand in” class is abstract in the technical sense. Although it declares functions, it doesn’t actually implement them. In Java terms, it’s an interface. The “working” classes derive from the abstract class, so they have the same interface. But they actually implement this interface.
The advantage of this setup is that user code can talk to the abstract interface class without bothering about how it’s actually being implemented. The implementation class in the background can even change—so there’s really no telling what it is, from the user’s perspective.
For Crush the Castle what I’ve done is to turn my Renderer class into an abstract interface. I then moved the Renderer implementation into a second, “behind the scenes” class—RendererGLES1. Just to give you a snippet of how this works, the two classes look something like this.
In Renderer.h:
class Renderer
{
public:
// ...
virtual void Clear() = 0;
// ...
};
In RendererGLES1.h:
class RendererGLES1 : public Renderer
{
public:
// ...
virtual void Clear()
{
glClear();
}
};
And now my user code looks something like this.
void main()
{
Renderer* pRenderer = new RendererGLES1();
// ...
pRenderer->Clear();
}
In practice, the process of converting my existing, concrete, OpenGL 1-based Renderer class into an abstraction layer with a concrete class in the background was a matter of simple refactoring.
- First, I copied my Renderer’s implementation files (Renderer.h and Renderer.cpp) to two new files called RendererGLES1.h and RendererGLES1.cpp.
- Next, I gutted the original Renderer files. I stripped almost all the function implementations from Renderer.cpp. I got rid of most member variables from the Renderer class declaration. I converted almost all the method declarations into pure virtual functions.
- With the original renderer gutted, I now made new renderer—RendererGLES1—inherit from Renderer. RendererGLES1 implemented all the functions that Renderer had implemented.
- Finally, in the place where I previously had made a new Renderer, I now made a new RendererGLES1. But I kept all the pointers and references to Renderer the same. The game thought it was talking to a Renderer, but through the magic of virtual functions, it was actually talking to a RendererGLES2.
At this point I was able to test the game to make sure that the refactoring had broken nothing. So far so good. But what—you may be asking—had I really gained? Hadn’t I just made more trouble for myself by turning one perfectly good class into an unwieldy and essentially redundant pair?
The benefit of this work came in the next step, which was to implement my OpenGL ES 2.0-based renderer. But I’m out of time today, so—more on that next time!

6 Comments
This process seems a bit familiar. How long until you create a RendererXNA?
How are you able to use C++ for iPhone development? I was under the impression that it had to be done in Objective-C.
Yes indeed. This is a process we do at the Guildhall when forking our engines between OpenGL and DirectX. Well spotted.
You canuse C++ for iPhone development, as it turns out. Although the UI and operating system API (Cocoa) is in Objective-C, your iPhone projects can use cpp code as well. In fact, source files with the extension .mm can have both Objective-C and C++ code mixed together—quite amazing. Crush the Castle has maybe two core Obj-C files, one for the “app” and the other for the “view,” and both of these are pretty stock (I based them on a project template). Then I have two or three small Obj-C files (.mm extension) that act as adapters: they enable my C++ code to call Cocoa API functions. The vast majority of my source—at least 50 files—is cpp.
Interesting. I used a similar technique for utilizing C++ compiled code within my Android game. Had three basic Java files (application, view and input) with JNI hooks I had to implement as “extern C” functions within the C++ project. From there it was a simple matter of having the Java classes call into my cpp files.
And here I thought the two platforms were wildly different! :]
It sounds like the “hooking” mechanism from the native language to C++ on Android takes a lot more effort than for iPhone. But yes, in general I bet they’re very similar platforms.
C++ on iPhone – there’s even a way to get around the ugly objC base!
A 3rd party SDK, called “Airplay SDK”, is, in it’s iPhone-only version (the regular version spans support over many oher platforms, eg- Android being among them) is free of charge for small businesses (making money not over some certain amount per year) and private people.
Iz’s all C++, with OpenGL.
I personally didn’t have the time to really try it out, but I had the fun to try out some examples coming with it, running on the generic mobile device emulator that’s also provided.
Looked pretty sollid.
Ah,
and thanks for the interesting article,
I have been stuck in the fixed pipeline world and only very recently started to delve into shaderland,
since I’m particularly intrested in smaller, handheld, devices, this article has lots of rlevance to me.