O'Reilly logo

iPhone 3D Programming by Philip Rideout

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Mixing OpenGL ES and UIKit

Sprites are often used for rendering interactive widgets in a HUD (see Handling the Heads-Up Display). Handling mouse interaction can be a chore when you don’t have a UI framework to stand upon. If you’re developing a 3D application and find yourself yearning for UIKit, don’t dismiss it right away. It’s true that mixing UIKit and OpenGL ES is generally ill-advised for performance reasons, but in many situations, it’s the right way to go. This is especially true with 3D applications that aren’t as graphically demanding as huge, professionally produced games. Figure 7-14 depicts an application that overlays a UISegmentedControl widget with a 3D scene.

The full source code for the application depicted in Figure 7-14 is available from this book’s site under the name CocoaMix. You might also want to check out the PVRTextureLoader sample from Apple’s SDK, which includes a slick sliding animation for a panel of UIKit controls.


The performance of “mixed” rendering has been improving as Apple rolls out new devices and new revisions to the iPhone OS. By the time you read this, using nonanimated UIKit controls in conjunction with OpenGL might be a perfectly acceptable practice.

Mixing UIKit with OpenGL ES

Figure 7-14. Mixing UIKit with OpenGL ES

Recall that all OpenGL rendering takes place in a UIView-derived class; every sample in this book defines a class called GLView for this purpose. Adding a few simple controls to GLView is fairly painless, so let’s try adding a UISegmentedControl that selects a texture minification filter.

First we need to add a field to the GLView class declaration for the new control. See the bold line in Example 7-17.

Example 7-17. Adding a UIKit control to GLView.h

#import "Interfaces.hpp"
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface GLView : UIView {
    IRenderingEngine* m_renderingEngine;
    IResourceManager* m_resourceManager;
    EAGLContext* m_context;
    float m_timestamp;
    UISegmentedControl* m_filterChooser;

- (void) drawView: (CADisplayLink*) displayLink;


Next, we need to instance the control and create a method for event handling; see Example 7-18.

Example 7-18. Adding a UIKit control to GLView.mm


- (id) initWithFrame: (CGRect) frame
    if (self = [super initWithFrame:frame])
        CAEAGLLayer* eaglLayer = (CAEAGLLayer*) self.layer;
        eaglLayer.opaque = YES;

        EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES1;
        m_context = [[EAGLContext alloc] initWithAPI:api];
        // Create and configure the UIKit control:
        NSArray* labels = [NSArray arrayWithObjects:@"Nearest",
                                                    @"Trilinear", nil];
        m_filterChooser = 
          [[[UISegmentedControl alloc] initWithItems:labels] autorelease];
        m_filterChooser.segmentedControlStyle = UISegmentedControlStyleBar;
        m_filterChooser.selectedSegmentIndex = 0;
        [m_filterChooser addTarget:self

        // Add the control to GLView's children:
        [self addSubview:m_filterChooser];
        // Position the UIKit control:
        const int ScreenWidth = CGRectGetWidth(frame);
        const int ScreenHeight = CGRectGetHeight(frame);
        const int Margin = 10;

        CGRect controlFrame = m_filterChooser.frame;
        controlFrame.origin.x = ScreenWidth / 2 - controlFrame.size.width / 2;
        controlFrame.origin.y = ScreenHeight - controlFrame.size.height - Margin;
        m_filterChooser.frame = controlFrame;
    return self;

- (void) changeFilter: (id) sender
    TextureFilter filter = (TextureFilter) [sender selectedSegmentIndex];


Example 7-18 includes some UIKit and Objective-C mechanisms that we haven’t seen before (such as @selector), but it will be familiar to iPhone developers. Check out Jonathan Zdziarski’s iPhone SDK Application Development (O’Reilly) to learn more about UIKit.

Note that you can also use UIKit to render “look-alike” controls, rather than using the actual UIKit controls. For example, you can render some buttons into a CGImage at launch time and then create an OpenGL texture from that (see Generating and Transforming OpenGL Textures with Quartz). This would give your buttons the look and feel of the iPhone’s native UI, plus it wouldn’t suffer from the potential performance issues inherent in mixing the actual UIKit control with OpenGL. The downside is that you’d need to implement the interactivity by hand.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required