iPhone OpenGL Retina Support

When Steve Jobs introduced the Retina Display feature for iPhone 4 and iPod Touch, he mentioned media content should be now adapted to the new devices, in order to make the most out of the high resolution available.

The introduction of Retina Displays took the resolution of the iPhone and iPod Touch devices from a 320×480 pixel screen up to a whooping 640×960 canvas. That’s 4 times more pixels to render. You can see the difference it produces in the following image: notice the area around the silhouette of the Gunner model.

A Retina Display-enabled OpenGL viewer (left) vs a Non-Retina Display Viewer (right).

While listening to the Keynote, I didn’t think OpenGL applications would have to be adapted, as OpenGL renders “on the fly” and I would’ve thought it would be enough just to set a bigger viewport.¬†After testing one of my Apps on a Retina-enabled iPod touch however, I realized my Vortex-Engine Apps were not making use of the Retina Display, falling back to a low-res display mode.

After a little Googl’ing, I found the problem. It seems the EAGLView class I was using to create and manage my OpenGL contexts (taken from the Xcode OpenGL ES template) was accounting for the higher resolution by making every pixel 4 times as big! I guess this is something necessary to prevent content that would work fine on older devices to be shown using 1/4th of the screen size on Retina-enabled devices. On the other hand, it was wasting 3/4 of the pixels available on the newer devices, so something had to be made for this special case.

I found the solution to this problem in David Amador’s blog, (here’s the link: http://www.david-amador.com/2010/09/setting-opengl-view-for-iphone-4-retina-hi-resolution/). The idea he presents is to make use of the extra available pixels in Retina Displays by scaling the content up to 2X the size, that way we get rid of this “backwards-compatible” display mode. I rather think about it more like “halfing the pixels” in both directions.

In any case, here’s the code snippet needed to do that. Once we know the screen width and height (using the UIScreen singleton), we can add the following snippet to the EAGLView initWithCoder: method:

if (width == 640 && height == 960)
    // We have a Retina Display:
    self.contentScaleFactor = 2.0f;
    eaglLayer.contentsScale = 2.0f;

This will automatically make your OpenGL application take advantage of the extra pixels available in Retina Display devices. No further changes in your OpenGL code are needed, as long as you keep the binding from the EAGLLayer instance to your Viewport and RenderBuffer(s).

You can notice the difference these three lines make in the image above. Click on the image to see it in full size and prevent browser smoothing; you will notice the difference between Retina Display enabled OpenGL content (left) and non-Retina content (right).

Vortex-Engine has been patched and now happily supports newer and older generation devices ; )