# OpenGL Tutorial for iOS: OpenGL ES 2.0

**URL:** <https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372>\
**Category:** 🎓 Courses & Articles\
**Created:** [March 4, 2016, 10:40am UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372 "2016-03-04T10:40:44Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![rwenderlich](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/rwenderlich/32/108604_2.png) [@rwenderlich](https://forums.kodeco.com/u/rwenderlich)\
**Post date:** [March 4, 2016, 10:40am UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/1 "2016-03-04T10:40:44Z")

</div>

In this OpenGL tutorial you'll get hands-on experience with OpenGL ES 2.0 and will create a simple "Hello, World" app that displays some simple geometry.

* * *
 This is a companion discussion topic for the original entry at [https://www.raywenderlich.com/3063-opengl-tutorial-for-ios-opengl-es-2-0](https://www.raywenderlich.com/3063-opengl-tutorial-for-ios-opengl-es-2-0)

---

<div class="post-metadata">

**Author:** ![drouck](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/drouck/32/10111_2.png) [@drouck](https://forums.kodeco.com/u/drouck)\
**Post date:** [March 20, 2016, 3:00pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/2 "2016-03-20T15:00:08Z")

</div>

A Swift implementation of the code can be found here:

[https://github.com/drouck/HelloOpenGL\_Swift](https://github.com/drouck/HelloOpenGL_Swift)

---

<div class="post-metadata">

**Author:** ![rwenderlich](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/rwenderlich/32/108604_2.png) [@rwenderlich](https://forums.kodeco.com/u/rwenderlich)\
**Post date:** [March 22, 2016, 5:39pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/3 "2016-03-22T17:39:45Z")

</div>

Cool, thanks @drouck! :]

---

<div class="post-metadata">

**Author:** ![saadplatini](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/saadplatini/32/12246_2.png) [@saadplatini](https://forums.kodeco.com/u/saadplatini)\
**Post date:** [March 29, 2016, 12:08pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/4 "2016-03-29T12:08:00Z")

</div>

I tried the same code with Xcode 7. It builds successfully but crashes during execution. I always get the following error: ‘Application windows are expected to have a root view controller at the end of application launch’

---

<div class="post-metadata">

**Author:** ![saadplatini](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/saadplatini/32/12246_2.png) [@saadplatini](https://forums.kodeco.com/u/saadplatini)\
**Post date:** [March 29, 2016, 12:19pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/5 "2016-03-29T12:19:33Z")

</div>

Problem solved! I added the following line of code inside the function "- (BOOL)application:(UIApplication \*)application didFinishLaunchingWithOptions:(NSDictionary \*)launchOptions

NSArray \*windows = [[UIApplication sharedApplication] windows];  
for(UIWindow _window in windows) {  
NSLog(@“window: %@”,window.description);  
if(window.rootViewController == nil){  
UIViewController_ vc = [[UIViewController alloc]initWithNibName:nil bundle:nil];  
window.rootViewController = vc;  
}  
}

---

<div class="post-metadata">

**Author:** ![dahlin](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/dahlin/32/30735_2.png) [@dahlin](https://forums.kodeco.com/u/dahlin)\
**Post date:** [April 15, 2016, 11:05am UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/6 "2016-04-15T11:05:01Z")

</div>

> Start up Xcode, and go to File\New\New Project. Select iOS\Application\Window-based Application, and click Next.

There is no longer such a template in Xcode. What should you use instead? Also, the tutorial says nothing about what language you should specify under the “Language” dropdown during the new project wizard.  
Also there is no info on how to compile things.

Tutorial looks promising, however I’m sure that people just drop out because they cannot progress further. I don’t have the time or energy to learn XCODE (since I’m not even using it for learning shaders - my shaders will be previewed in another application).

---

<div class="post-metadata">

**Author:** ![jeremyhu](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/jeremyhu/32/36164_2.png) [@jeremyhu](https://forums.kodeco.com/u/jeremyhu)\
**Post date:** [July 3, 2016, 10:45pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/7 "2016-07-03T22:45:53Z")

</div>

There are tons of tutorials about OpenGL ES 2.0, but this one is the best. Thank you Ray, I use what I learned from your tutorial and made a RPG game render example, if someone who also learned OpenGL ES 2.0 from this article and want to make a game based on this tutorial but have no idea how to start, maybe can have a look at my example: [https://github.com/huxingyi/libphone/tree/master/samples/rpggame#overview](https://github.com/huxingyi/libphone/tree/master/samples/rpggame#overview)

---

<div class="post-metadata">

**Author:** ![fra](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/fra/32/36727_2.png) [@fra](https://forums.kodeco.com/u/fra)\
**Post date:** [July 11, 2016, 9:04pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/8 "2016-07-11T21:04:01Z")

</div>

Great tutorial Ray!  
Is there an updated version for Xcode 7+? I’m not able render into the window. I just get a white screen.

---

<div class="post-metadata">

**Author:** ![bmauter](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/bmauter/32/38413_2.png) [@bmauter](https://forums.kodeco.com/u/bmauter)\
**Post date:** [August 6, 2016, 8:23pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/9 "2016-08-06T20:23:27Z")

</div>

Thanks Ray!

I just completed the tutorial with Xcode 7. There were a few gotchas, so I hope this saves someone the trouble next time.

1. There is no Window-based application template. Use the single view template.
2. Delete the `Main.storyboard` file.
3. Clear the reference on the project’s target’s **Main Interface** field.
4. Delete `ViewController.h` and `ViewController.m`.
5. Replace your app delegate’s `application:didFinishLaunchingWithOptions:` method with the code at the bottom of this post.
6. Use Ray’s zipped Cocos3D file, but you’re going to have to fix a few things.
7. Add `#import <UIKit/UIColor.h>` at the top of `CC3Foundation.h`.
8. Change the calls to `abs` in `CC3Kazmath.c` to `fabs`.
9. Add `-fno-objc-arc` to `CC3Kazmath.c`, `CC3Foundation.m`, `CC3GLMatrix.m`, `CC3Math.m` in the project’s target’s **Build Phases**  **Compile Sources** section.

Here’s the code for `AppDelegate.m`.

```
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    UIViewController *vc = [[UIViewController alloc] init];
    [vc setView:[[OpenGLView alloc] initWithFrame:[_window bounds]]];
    
    [_window setRootViewController:vc];
    [_window makeKeyAndVisible];
    return YES;
}

```

---

<div class="post-metadata">

**Author:** ![kenmrph](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/kenmrph/32/88690_2.png) [@kenmrph](https://forums.kodeco.com/u/kenmrph)\
**Post date:** [May 23, 2017, 8:53pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/10 "2017-05-23T20:53:10Z")

</div>

Great tutorial! It all worked great for me (with some of the mods mentioned in the prior comments), right up until adding the depth buffer, at which point I get a white screen on execution. Commenting out the call to [self setupDepthBuffer] from initWithFrame restores the functionality (a rotating cube that you can “see inside of”).

xcode 8.3.2  
iOS 10.3.1 (real device)

---

<div class="post-metadata">

**Author:** ![emorling](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/emorling/32/69221_2.png) [@emorling](https://forums.kodeco.com/u/emorling)\
**Post date:** [June 11, 2017, 3:14pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/11 "2017-06-11T15:14:47Z")

</div>

Thanks for sharing this excellent tutorial. Do you have any examples on how to dynamically render text? E.g. “Hello World”

---

<div class="post-metadata">

**Author:** ![tomisacat](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/tomisacat/32/102075_2.png) [@tomisacat](https://forums.kodeco.com/u/tomisacat)\
**Post date:** [June 12, 2017, 7:33am UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/12 "2017-06-12T07:33:46Z")

</div>

Thanks Ray! I’ve followed the tutorial using Swift but stuck with the `Creating Vertex Buffer Objects` and `Updated Render Code`, here is my OpenGLView.swift code:

> //  
> // OpenGLView.swift  
> // LearnOpenGLES  
> //  
> // Created by tomisacat on 08/06/2017.  
> // Copyright © 2017 tomisacat. All rights reserved.  
> //

> import Foundation  
> import OpenGLES  
> import GLKit  
> import QuartzCore

> struct Vertex {  
> var Position:(Float, Float, Float)  
> var Color: (Float, Float, Float, Float)  
> }

> var vertices = [  
> Vertex(Position: (1, -1, 0), Color: (1, 0, 0, 1)),  
> Vertex(Position: (1, 1, 0) , Color: (0, 1, 0, 1)),  
> Vertex(Position: (-1, 1, 0) , Color: (0, 0, 1, 1)),  
> Vertex(Position: (-1, -1, 0), Color: (0, 0, 0, 1))  
> ]

> var indices: [GLubyte] = [  
> 0, 1, 2,  
> 2, 3, 0  
> ]

> class OpenGLView: UIView {  
> fileprivate var eaglLayer: CAEAGLLayer!  
> fileprivate var context: EAGLContext!  
> fileprivate var colorRenderBuffer: GLuint = 0  
> fileprivate var positionSlot: GLuint = 0  
> fileprivate var colorSlot: GLuint = 0
> 
> ```
> override init(frame: CGRect) {
> super.init(frame: frame)
>     
> callSetups()
> }
> 
> required init?(coder aDecoder: NSCoder) {
> super.init(coder: aDecoder)
>     
> callSetups()
> }
> 
> override class var layerClass: AnyClass {
> return CAEAGLLayer.self
> }
> 
> // MARK: private setup
> 
> private func compileShaders() {
> let vertexShader: GLuint = compile(shader: "SimpleVertex", withType: GLenum(GL_VERTEX_SHADER))
> let fragmentShader: GLuint = compile(shader: "SimpleFragment", withType: GLenum(GL_FRAGMENT_SHADER))
>     
> let programHandle: GLuint = glCreateProgram()
> glAttachShader(programHandle, vertexShader)
> glAttachShader(programHandle, fragmentShader)
> glLinkProgram(programHandle)
>     
> var linkSuccess: GLint = GL_FALSE
> glGetProgramiv(programHandle, GLenum(GL_LINK_STATUS), &linkSuccess)
> if linkSuccess == GL_FALSE {
> let messages: UnsafeMutablePointer<GLchar> = UnsafeMutablePointer.allocate(capacity: 256 * MemoryLayout<GLchar>.size)
> var length: GLsizei = 0
> glGetProgramInfoLog(programHandle, GLsizei(MemoryLayout.size(ofValue: messages)), &length, messages)
> if let log = NSString(utf8String: messages) {
> print(log)
> }
> }
>     
> glUseProgram(programHandle)
>     
> positionSlot = GLuint(glGetAttribLocation(programHandle, "Position"))
> colorSlot = GLuint(glGetAttribLocation(programHandle, "SourceColor"))
> glEnableVertexAttribArray(positionSlot)
> glEnableVertexAttribArray(colorSlot)
> }
> 
> private func compile(shader: String, withType type: GLenum) -> GLuint {
> guard let shaderPath = Bundle.main.path(forResource: shader, ofType: "glsl") else {
> return 0
> }
>     
> do {
> let shaderString = try String(contentsOfFile: shaderPath)
>         
> let shaderHandle = glCreateShader(type)
> var shaderStringUTF8 = UnsafePointer(shaderString.cString(using: .utf8))
> var shaderStringLength = GLint(shaderString.characters.count)
>         
> glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength)
> glCompileShader(shaderHandle)
>         
> var compileSuccess: GLint = GL_FALSE
> glGetShaderiv(shaderHandle, GLenum(GL_COMPILE_STATUS), &compileSuccess)
> if compileSuccess == GL_FALSE {
> let messages: UnsafeMutablePointer<GLchar> = UnsafeMutablePointer.allocate(capacity: 256 * MemoryLayout<GLchar>.size)
> var length: GLsizei = 0
> glGetShaderInfoLog(shaderHandle, GLsizei(MemoryLayout.size(ofValue: messages)), &length, messages)
> if let log = NSString(utf8String: messages) {
> print(log)
> }
>             
> return 0
> }
>         
> return shaderHandle
> } catch {
> return 0
> }
> }
> 
> //
> 
> private func setupVBOs() {
> var vertexBuffer: GLuint = 0
> glGenBuffers(1, &vertexBuffer)
> glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
> glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size(ofValue: vertices), vertices, GLenum(GL_STATIC_DRAW))
>     
> var indexBuffer: GLuint = 0
> glGenBuffers(1, &indexBuffer)
> glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
> glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), MemoryLayout.size(ofValue: indices), indices, GLenum(GL_STATIC_DRAW))
> }
> 
> private func render() {
> glClearColor(0, 104/255, 55/255, 1)
> glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
>     
> glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
>     
> glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<Vertex>.size), nil)
> glVertexAttribPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<Vertex>.size), UnsafePointer<Float>(bitPattern: 3 * MemoryLayout<Float>.size))
>     
> glDrawElements(GLenum(GL_TRIANGLES), GLsizei(indices.count), GLenum(GL_UNSIGNED_BYTE), nil)
>     
> context.presentRenderbuffer(Int(GL_RENDERBUFFER))
> }
> 
> // private func render() {
> // glClearColor(0, 104/255, 55/255, 1)
> // glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
> // context.presentRenderbuffer(Int(GL_RENDERBUFFER))
> // }
> 
> //
> 
> private func callSetups() {
> setupLayer()
> setupContext()
> setupRenderBuffer()
> setupFrameBuffer()
>     
> compileShaders()
> setupVBOs()
>     
> render()
> }
> 
> private func setupLayer() {
> eaglLayer = self.layer as! CAEAGLLayer
> eaglLayer.isOpaque = true
> }
> 
> private func setupContext() {
> context = EAGLContext(api: .openGLES3)
> if context == nil {
> context = EAGLContext(api: .openGLES2)
> }
>     
> EAGLContext.setCurrent(context)
> }
> 
> private func setupRenderBuffer() {
> glGenRenderbuffers(1, &colorRenderBuffer)
> glBindRenderbuffer(GLenum(GL_RENDERBUFFER), colorRenderBuffer)
> context.renderbufferStorage(Int(GL_RENDERBUFFER), from: eaglLayer)
> }
> 
> private func setupFrameBuffer() {
> var frameBuffer: GLuint = 0
> glGenFramebuffers(1, &frameBuffer)
> glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer)
> glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), colorRenderBuffer)
> }
> 
> ```
> 
> }

What I hope is exactly like your tutorial, a gradient image show on screen, but I just got a green image like the previous step. What’s wrong with my code?

If there is an update version for Swift will be awesome!

---

<div class="post-metadata">

**Author:** ![kirstone](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/kirstone/32/68839_2.png) [@kirstone](https://forums.kodeco.com/u/kirstone)\
**Post date:** [June 22, 2017, 9:24am UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/13 "2017-06-22T09:24:02Z")

</div>

Thanks for great tutorial! Here is project for Objective-C, using XCode 8.2.1 [https://gitlab.com/kirstone/OpenGL-ES-Tutorial-RayWenderlich](https://gitlab.com/kirstone/OpenGL-ES-Tutorial-RayWenderlich)

---

<div class="post-metadata">

**Author:** ![shogunkaramazov](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/shogunkaramazov/32/108826_2.png) [@shogunkaramazov](https://forums.kodeco.com/u/shogunkaramazov)\
**Post date:** [November 15, 2017, 7:19pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/14 "2017-11-15T19:19:49Z")

</div>

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]

---

<div class="post-metadata">

**Author:** ![shogunkaramazov](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/shogunkaramazov/32/108826_2.png) [@shogunkaramazov](https://forums.kodeco.com/u/shogunkaramazov)\
**Post date:** [November 15, 2017, 7:19pm UTC](https://forums.kodeco.com/t/opengl-tutorial-for-ios-opengl-es-2-0/6372/15 "2017-11-15T19:19:51Z")

</div>


