Apple uses OpenGL extensively – their 2D desktop libraries (Quartz, CoreAnimation) are OpenGL-based, and iOS has inherited that link (along with some funky tricks you can pull).
a standalone library on GitHub, with the code from the articles as a Demo app. It uses the ‘latest’ version of the code, so the early articles are quite different – but it’s an easy starting point
iOS developers often don’t have an OpenGL background, and most of the ones I work with like the idea of OpenGL, but feel they don’t have the time to learn and master it. However, the combination of “new API (OpenGL ES 2)” with “Apple’s helper classes (GLKit)” makes OpenGL development on mobile suprisingly fast and easy.
A few years ago, Jeff LaMarche wrote a series of simple, easy tutorials on getting started with OpenGL ES 1. In the same spirit, I’m going to write about GL ES 2. In the land of Khronos (the OpenGL standards group), version “2″ is fundamentally different to version “1″ (this is a good thing: ES 1 was outdated from the start, based on 1990s OpenGL. ES 2 is a modern API, based on 2000′s OpenGL)
I’ll be covering this from an iOS perspective. There are lots of GL ES tutorials out there, but for non-iOS platforms the challenges (and solutions) are different.
Quick links to all posts
- Part 1 – (this one)
- Part 2 – Drawing and Draw calls
- Structuring your OpenGL code to be easy to edit and maintain
- How OpenGL constructs each “frame” while rendering
- Part 3 – Shaders and Geometry
- What is a “Vertex” in OpenGL
- The two kinds of Shader in GL ES 2
- Boilerplate code to compile + link + upload Shaders to the GPU
- Part 4 – Debugging, and refactoring/improving/explaining VAOs and VBOs better
- On second thoughts, this post sucked. Read 4(b) instead
- Part 4b – Multiple objects at once
- (replaces Part 4, is much better)
- Multiple objects: A VAO per draw call
- Multiple Attributes per VBO / Interleaved Vertex data
- A “buffer format”
iOS 5.0, iOS 6.0, and GLKit
With iOS 5.0, Apple introduced a new Framework: GLKit. GLKit’s apparent aim was to fix ES 2.0 to make it simpler and easier for non-OpenGL experts to use.
It’s not live yet, and I’d hoped Apple might update GLKit to fix some of the holes below. I don’t know what will be in the final iOS 7 release, but I get the impression GLKit hasn’t changed yet. If so, everything that follows applies equally to iOS 7.
Summary of Apple’s GLKit and where it helps/hinders
|Porting GL ES 1.x code|
Apple provided a good, easy-to-use set of classes to make it trivial to port GL ES 1.x code. The documentation is very poor, though.
More importantly: it prevents you from using Shaders, which are one of the easiest and most powerful parts of OpenGL (once you get up and running). So, we’ll be ignoring GL ES 1.x
Classes: anything with the text “Effect” in the class name (GLKBaseEffect, GLKEffectProperty, GLKNamedEffect, etc)
Every desktop OpenGL implementation assumes you have access to a good Vector Math library.
Until GLKit, Apple’s iOS was the exception: you had to make your own “vector” classes, you had to write all the Dot Product code, etc. (e.g. c.f. Jeff LaMarche’s first tutorial). Not any more :). Apple’s design here is good, and closely follows the conventions of their other frameworks (works the same way as CGRect, CGPoint etc from Quartz/CoreGraphics)
Structs: GLKVector2, GLKVector3, GLKVector4
Quaternions have a bad rep. Many people find them incomprehensibly hard to understand/code, and yet … they are essential once you start “rotating 3D objects”.
Apple’s implementation of Quaternions is excellent: you don’t need to understand the mathematics, just use the pre-built methods
Like Vector-math, Matrix math is tricky and time consuming to build for yourself and debug.
Apple’s done all of it, with an good set of methods.
Structs: GLKMatrix4, GLKMatrix3
|Partial (almost full)||
OpenGL uses 4-dimensions to deal with 3-dimensional rendering. That could get difficult, fast. Skipping the reasons for it, OpenGL used to be hardcoded to a set of special matries (M, V, and P – model, view, and projection).
GL ES 2 threw away the hard-coded matrices, and says “do it all yourself” (which, as we’ll see later, actually makes things easier in the long run). This is a pain … except Apple’s done it for us. Don’t go writing your own MVP stack code – use Apple’s.
Before GLKit, you had to write long and complex methods, using CoreAnimation and Quartz, to convert “file.png” and upload it to the graphics chip as an “OpenGL texture”.
That code was hard to debug, and most iOS programmers aren’t familiar with CA/Quartz. Apple wrote a proper Objective-C texturing system that does the work of Quartz and y-flipping for you. For most “simple” code, this is perfect.
…but: they screwed up in a few places, some major bugs. When it works, it’s fine – and it only needs two lines of code! – so we’ll use it in the early articles, but we’ll throw it away and write a “fixed” version for the later articles.
Classes: GLKTextureInfo, GLKTextureLoader
|Mixing UIKit with OpenGL|
See post: “Part 2″
There’s a lot of FUD on the web that says this is “impossible” or “slow” or … etc.
Don’t believe it. There are bugs in Apple’s CALayer / Quartz / CoreAnimation classes that make them slow *independent* of whether you’re running OpenGL. It’s just that the things people want to do when using UIKit with OpenGL are usually the ones that show up the bugs in UIKit/Quartz.
We’ll cover the main gotchas, and look at how to avoid or improve them. But for the most part: it works automagically. (there’s a reason for this: UIKit is implemented on top of OpenGL, so it’s already integrated to a high standard. It’s just that Apple hid the integration points)
|Shaders (vertex, fragment)|
See post: Part 3
GLKit pretends that shaders don’t exist. The most important feature of OpenGL ES 2.0 – and Apple ignored it. Sad, but true. We’ll fix that.
OpenGL supports multi-threading, background loading, all sorts of funky stuff.
Although it’s not strictly part of GLKit, Apple has re-used their old EAGLContext class to provide access to all of this. This is probably because it worked fine in the first place. However, to be clear: if you’re used to EAGLContext, it’s still used EVERYWHERE by GLKit.
See post: “Part 2″
You can make a cube appear on screen, textured, using single-pass rendering.
Just about everything else you ever want to do … needs more than one pass.
Apple provides no support for this, so you have to write it yourself (and there’s a surprisingly large amount of boilerplate you need to write here).
|3D models, animation, data formats||Partial (very little)||
See post: Part 3
See post: Part 4b
GLKit does one great thing with 3D data formats: it provides a Vector class that all iOS apps/libraries/source can use, and be fully compatible with each other.
But it provides zero support for the rest: meshes, 3D models, VAOs, VBOs, etc.
|Error handling and state management|
See post: Part 4
When you have a bug in your code, GL does nothing. Nor does Apple. Sooner or later you’ll find yourself weeping in frustration.
Apple makes a lot of noise about how good Instruments is with OpenGL.
This is true, it’s good. But Apple also blocks you from accessing the hardware-manufacturers own performance tools, which may be better.
If you already know Instruments inside-out (e.g. you know about the invisible RHS-panel…), you’ll be right at home.
If you know nothing at all about OpenGL, I recommend skim-reading the first 8 of Jeff LaMarche’s posts on GL ES 1.
NOTE: a *lot* of the detail in Jeffs’ posts is now unnecessary (or superceded). But it all helps with understanding the newer/cleaner GL ES 2 (and GLKit) versions. If you get stuck or struggle, skim that post and move on to the next. Each of his posts works well standalone.
Then head on to Part 2 – Drawing and Draw calls.