Important: OpenGL ES was deprecated in iOS 12. To create high-performance code on GPUs, use the Metal framework instead. See Metal.
The Open Graphics Library (OpenGL) is used for visualizing 2D and 3D data.
It is a multipurpose open-standard graphics library that supports applications for 2D and 3D digital content creation, mechanical and architectural design, virtual prototyping, flight simulation, video games, and more.
You use OpenGL to configure a 3D graphics pipeline and submit data to it. Vertices are transformed and lit, assembled into primitives, and rasterized to create a 2D image.
OpenGL is designed to translate function calls into graphics commands that can be sent to underlying graphics hardware. Because this underlying hardware is dedicated to processing graphics commands, OpenGL drawing is typically very fast.
OpenGL ES is a low-level, hardware-focused API. Though it provides the most powerful and flexible graphics processing tools, it also has a steep learning curve and a significant effect on the overall design of your app. For apps that require high-performance graphics for more specialized uses, iOS provides several higher-level frameworks:
- The Sprite Kit framework provides a hardware-accelerated animation system optimized for creating 2D games. (See SpriteKit Programming Guide.)
- The Core Image framework provides real-time filtering and analysis for still and video images. (See Core Image Programming Guide.)
- Core Animation provides the hardware-accelerated graphics rendering and animation infrastructure for all iOS apps, as well as a simple declarative programming model that makes it simple to implement sophisticated user interface animations. (See Core Animation Programming Guide.)
- You can add animation, physics-based dynamics, and other special effects to Cocoa Touch user interfaces using features in the UIKit framework.
OpenGL ES Is a Platform-Neutral API Implemented in iOS
Because OpenGL ES is a C-based API, it is extremely portable and widely supported.
As a C API, it integrates seamlessly with Objective-C Cocoa Touch apps.
The OpenGL ES specification does not define a windowing layer; instead, the hosting operating system must provide functions to create an OpenGL ES rendering context, which accepts commands, and a framebuffer, where the results of any drawing commands are written to.
Working with OpenGL ES on iOS requires using iOS classes to set up and present a drawing surface
and using platform-neutral API
to render its contents.
GLKit Provides a Drawing Surface and Animation Support
Views and view controllers, defined by the UIKit framework, control the presentation of visual content on iOS.
The GLKit framework provides OpenGL ES–aware versions of these classes.
When you develop an OpenGL ES app, you use a GLKView
object to render your OpenGL ES content. You can also use a GLKViewController
object to manage your view and support animating its contents.
iOS Supports Alternative Rendering Targets
Besides drawing content to fill an entire screen or part of a view hierarchy, you can also use OpenGL ES framebuffer
objects for other rendering strategies.
iOS implements standard OpenGL ES framebuffer objects, which you can use for rendering to an offscreen buffer
or to a texture
for use elsewhere in an OpenGL ES scene.
In addition, OpenGL ES on iOS supports rendering to a Core Animation layer (the CAEAGLLayer
class), which you can then combine with other layers to build your app’s user interface or other visual displays.
Apps Require Additional Performance Tuning
Graphics processors are parallelized devices optimized for graphics operations.
To get great performance in your app, you must carefully design your app to feed data and commands to OpenGL ES so that the graphics hardware runs in parallel with your app.
A poorly tuned app forces either the CPU or the GPU to wait for the other to finish processing commands.
You should design your app to efficiently use the OpenGL ES API. Once you have finished building your app, use Instruments to fine tune your app’s performance. If your app is bottlenecked inside OpenGL ES, use the information provided in this guide to optimize your app’s performance.
OpenGL ES May Not Be Used in Background Apps
Apps that are running in the background may not call OpenGL ES functions.
If your app accesses the graphics processor while it is in the background, it is automatically terminated by iOS.
To avoid this, your app should flush any pending commands previously submitted to OpenGL ES prior to being moved into the background and avoid calling OpenGL ES until it is moved back to the foreground.
OpenGL ES Places Additional Restrictions on Multithreaded Apps
Designing apps to take advantage of concurrency can be useful to help improve your app’s performance.
If you intend to add concurrency to an OpenGL ES app, you must ensure that it does not access the same context from two different threads
at the same time.
Drawing With a GLKit View
1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)drawRect:(CGRect)rect
{
// Clear the framebuffer
glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw using previously configured texture, shader, uniforms, and vertex array
glBindTexture(GL_TEXTURE_2D, _planetTexture);
glUseProgram(_diffuseShading);
glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, _modelViewProjectionMatrix.m);
glBindVertexArrayOES(_planetMesh);
glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT);
}
The GLKView
class is able to provide a simple interface for OpenGL ES drawing because it manages the standard parts of the OpenGL ES rendering process:
- Before invoking your drawing method, the view:
- Makes its
EAGLContext
object the current context - Creates a framebuffer object and renderbuffers based on its current size, scale factor, and drawable properties (if needed)
- Binds the framebuffer object as the current destination for drawing commands
- Sets the OpenGL ES viewport to match the framebuffer size
- Makes its
- After your drawing method returns, the view:
- Resolves multisampling buffers (if multisampling is enabled)
- Discards renderbuffers whose contents are no longer needed
- Presents renderbuffer contents to Core Animation for caching and display
Rendering Using a Delegate Object
Many OpenGL ES apps implement rendering code
in a custom
class. An advantage of this approach is that it allows you to easily support multiple rendering algorithms
by defining a different renderer class
for each. Rendering algorithms that share common functionality can inherit it from a superclass. For example, you might use different renderer classes to support both OpenGL ES 2.0 and 3.0.
GLKit is well suited to this approach—you can make your renderer object the delegate of a standard GLKView
instance. Instead of subclassing GLKView
and implementing the drawRect:
method, your renderer class adopts the GLKViewDelegate
protocol and implements the glkView:drawInRect:
method.
Choosing a renderer class based on hardware features
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create a context so we can test for features
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:context];
// Choose a rendering class based on device features
GLint maxTextureSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
if (maxTextureSize > 2048)
self.renderer = [[MyBigTextureRenderer alloc] initWithContext:context];
else
self.renderer = [[MyRenderer alloc] initWithContext:context];
// Make the renderer the delegate for the view loaded from the main storyboard
GLKView *view = (GLKView *)self.window.rootViewController.view;
view.delegate = self.renderer;
// Give the OpenGL ES context to the view so it can draw
view.context = context;
return YES;
}