Last active
August 29, 2015 13:59
-
-
Save Air-Craft/10460238 to your computer and use it in GitHub Desktop.
GLKView Boilerplate #opengles #ios #animation #3d #boilerplate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AC_CoverView.m | |
// AC Cover | |
// | |
// Created by Hari Karam Singh on 11/04/2014. | |
// Copyright (c) 2014 Air Craft. All rights reserved. | |
// | |
#import "AC_CoverView.h" | |
#import "GLKView+AC_Additions.h" | |
///////////////////////////////////////////////////////////////////////// | |
#pragma mark - GL Data & Types | |
///////////////////////////////////////////////////////////////////////// | |
#define BUFFER_OFFSET(i) ((char *)NULL + (i)) | |
// Uniform index. | |
enum | |
{ | |
UNIFORM_MODELVIEWPROJECTION_MATRIX, | |
UNIFORM_NORMAL_MATRIX, | |
NUM_UNIFORMS | |
}; | |
GLint uniforms[NUM_UNIFORMS]; | |
// Attribute index. | |
enum | |
{ | |
ATTRIB_VERTEX, | |
ATTRIB_NORMAL, | |
NUM_ATTRIBUTES | |
}; | |
GLfloat _glCubeVertexData[216] = | |
{ | |
// Data layout for each line below is: | |
// positionX, positionY, positionZ, normalX, normalY, normalZ, | |
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, | |
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, | |
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, | |
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, | |
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, | |
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, | |
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, | |
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, | |
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, | |
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, | |
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, | |
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, | |
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, | |
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, | |
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, | |
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, | |
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, | |
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, | |
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, | |
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, | |
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f | |
}; | |
///////////////////////////////////////////////////////////////////////// | |
#pragma mark - | |
///////////////////////////////////////////////////////////////////////// | |
@implementation AC_CoverView | |
{ | |
GLuint _program; | |
GLuint _vertexArray; | |
GLuint _vertexBuffer; | |
GLKMatrix4 _modelViewProjectionMatrix; | |
GLKMatrix3 _normalMatrix; | |
float _rotation; | |
GLKBaseEffect *_effect; ///< For the lighting | |
CADisplayLink *_updateTimer; | |
} | |
///////////////////////////////////////////////////////////////////////// | |
#pragma mark - Life Cycle | |
///////////////////////////////////////////////////////////////////////// | |
- (void)setup | |
{ | |
///////////////////////////////////////// | |
// CONTEXT SETUP | |
///////////////////////////////////////// | |
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; | |
if (!self.context) { | |
[NSException raise:NSGenericException format:@"Couldn't create GL Context!"]; | |
} | |
[EAGLContext setCurrentContext:self.context]; | |
// Flags | |
self.drawableDepthFormat = GLKViewDrawableDepthFormat24; | |
///////////////////////////////////////// | |
// LIGHTING SETUP | |
///////////////////////////////////////// | |
_effect = [GLKBaseEffect new]; | |
_effect.light0.enabled = GL_TRUE; | |
_effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); | |
///////////////////////////////////////// | |
// DATA & BUFFERS | |
///////////////////////////////////////// | |
glGenVertexArraysOES(1, &_vertexArray); | |
glBindVertexArrayOES(_vertexArray); | |
glGenBuffers(1, &_vertexBuffer); | |
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(_glCubeVertexData), _glCubeVertexData, GL_STATIC_DRAW); | |
// Set position data | |
glEnableVertexAttribArray(GLKVertexAttribPosition); | |
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, BUFFER_OFFSET(0)); | |
glEnableVertexAttribArray(GLKVertexAttribNormal); | |
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, BUFFER_OFFSET(sizeof(GLfloat)*3)); | |
glBindVertexArrayOES(0); | |
///////////////////////////////////////// | |
// SHADERS | |
///////////////////////////////////////// | |
[self _loadShaders]; | |
///////////////////////////////////////// | |
// UPDATE TIMER (TEMP???) | |
///////////////////////////////////////// | |
_updateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(_update:)]; | |
[_updateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; | |
// Clear the context to be polite | |
[EAGLContext setCurrentContext:nil]; | |
} | |
//--------------------------------------------------------------------- | |
- (void)dealloc | |
{ | |
[_updateTimer invalidate]; | |
[EAGLContext setCurrentContext:self.context]; | |
glDeleteBuffers(1, &_vertexBuffer); | |
glDeleteVertexArraysOES(1, &_vertexArray); | |
if (_program) { | |
glDeleteProgram(_program); | |
_program = 0; | |
} | |
if ([EAGLContext currentContext] == self.context) { | |
[EAGLContext setCurrentContext:nil]; | |
} | |
} | |
//--------------------------------------------------------------------- | |
///////////////////////////////////////////////////////////////////////// | |
#pragma mark - Additional Privates | |
///////////////////////////////////////////////////////////////////////// | |
- (void)_update:(CADisplayLink *)sender | |
{ | |
static NSTimeInterval lastTime = -1.0; | |
NSTimeInterval now; | |
now = CACurrentMediaTime(); | |
if (lastTime < 0) { | |
lastTime = now; | |
return; | |
} | |
NSTimeInterval timeSinceLastUpdate = now - lastTime; | |
float aspect = fabsf(self.bounds.size.width / self.bounds.size.height); | |
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); | |
_effect.transform.projectionMatrix = projectionMatrix; | |
GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); | |
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); | |
// Compute the model view matrix for the object rendered with GLKit | |
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); | |
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); | |
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); | |
_effect.transform.modelviewMatrix = modelViewMatrix; | |
// Compute the model view matrix for the object rendered with ES2 | |
modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); | |
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); | |
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); | |
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); | |
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); | |
_rotation += timeSinceLastUpdate * 0.5f; | |
lastTime = now; | |
[self setNeedsDisplay]; | |
} | |
//--------------------------------------------------------------------- | |
- (void)drawRect:(CGRect)rect | |
{ | |
// @TODO Set context?? Hopefully not. Try to prevent dual GL contexts operating in order to save bandwidth | |
glEnable(GL_DEPTH_TEST); | |
glClearColor(0.65f, 0.65f, 0.65f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glBindVertexArrayOES(_vertexArray); | |
// Render the object with GLKit | |
[_effect prepareToDraw]; | |
glDrawArrays(GL_TRIANGLES, 0, 36); | |
// Render the object again with ES2 | |
glUseProgram(_program); | |
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); | |
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); | |
glDrawArrays(GL_TRIANGLES, 0, 36); | |
} | |
//--------------------------------------------------------------------- | |
/** @todo Proper exception types */ | |
- (void)_loadShaders | |
{ | |
GLuint vertShader, fragShader; | |
NSString *vertShaderPathname, *fragShaderPathname; | |
// Create shader program. | |
_program = glCreateProgram(); | |
// Create and compile vertex shader. | |
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; | |
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { | |
[NSException raise:NSGenericException format:@"Failed to compile vertex shader"]; | |
return; | |
} | |
// Create and compile fragment shader. | |
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; | |
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { | |
[NSException raise:NSGenericException format:@"Failed to compile fragment shader"]; | |
return; | |
} | |
// Attach vertex shader to program. | |
glAttachShader(_program, vertShader); | |
// Attach fragment shader to program. | |
glAttachShader(_program, fragShader); | |
// Bind attribute locations. | |
// This needs to be done prior to linking. | |
glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); | |
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); | |
// Link program. | |
if (![self linkProgram:_program]) { | |
if (vertShader) { | |
glDeleteShader(vertShader); | |
vertShader = 0; | |
} | |
if (fragShader) { | |
glDeleteShader(fragShader); | |
fragShader = 0; | |
} | |
if (_program) { | |
glDeleteProgram(_program); | |
_program = 0; | |
} | |
[NSException raise:NSGenericException format:@"Failed to link program: %d", _program]; | |
return; | |
} | |
// Get uniform locations. | |
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); | |
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); | |
// Release vertex and fragment shaders. | |
if (vertShader) { | |
glDetachShader(_program, vertShader); | |
glDeleteShader(vertShader); | |
} | |
if (fragShader) { | |
glDetachShader(_program, fragShader); | |
glDeleteShader(fragShader); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment