OpenGL学习- 11. GLSL索引绘图 & 绘制纹理颜色混合立方体

309 阅读5分钟

11. GLSL索引绘图 & 绘制纹理颜色混合立方体

GLSL索引绘图

#import "RenderView.h"
#import <OpenGLES/ES3/gl.h>
#import "GLESMath.h"

@interface RenderView (){
    CAEAGLLayer *glLayer;
    EAGLContext *context;
    GLuint renderBufferID;
    GLuint frameBufferID;
    GLuint vertexID;
    GLuint programID;
}

@end

@implementation RenderView

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (void)layoutSubviews {
    [self configAttribute];
    [self render];
}

/// 配置属性变量
- (void)configAttribute {
    /// layer
    glLayer = (CAEAGLLayer *)self.layer;
    glLayer.opaque = YES;
    [self setContentScaleFactor:[UIScreen mainScreen].scale];//让缩放比例同屏幕显示一致
    glLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @false,
                                   kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8,
    };

    /// context
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    NSAssert(context, @"context 创建失败");
    BOOL configContext = [EAGLContext setCurrentContext:context];
    if (!configContext) {
        NSLog(@"配置上下文失败");
        return;
    }

    /// buffer
    [self deleteBuffer];
    glGenBuffers(1, &renderBufferID);
    glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:glLayer];
    glGenFramebuffers(1, &frameBufferID);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferID);
}

- (void)render {
    glClearColor(0.3, 0.5, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    CGFloat scale = [[UIScreen mainScreen] scale];
    //2.设置视口
    glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, self.frame.size.width * scale, self.frame.size.height * scale);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    /// vertexArray x,y,z,  r,g,b,
    GLfloat vertexArray[] = {
        -0.5, -0.5, -0.5,    1.0, 1.0, 0.0,
        0.5, -0.5, -0.5,     1.0, 0.0, 0.0,
        0.5, 0.5, -0.5,     0.0, 1.0, 0.0,
        -0.5, 0.5, -0.5,     0.0, 0.0, 1.0,
        0.0, 0.0, 0.5,      0.0, 1.0, 1.0,
    };
    /// indexArray
    GLuint indexArray[] = {
        0, 3, 1,
        3, 2, 1,
        0, 4, 3,
        1, 4, 0,
        2, 4, 1,
        3, 4, 2,
    };
    /// vertex buffer
    if (vertexID == 0) {
        glGenBuffers(1, &vertexID);
    }
    glBindBuffer(GL_ARRAY_BUFFER, vertexID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray), vertexArray, GL_DYNAMIC_DRAW);
    /// vertex shader
    GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER);
    NSString *vShaderFilePath = [[NSBundle mainBundle] pathForResource:@"shaderV" ofType:@"glsl"];
    const GLchar *vShaderSource = (GLchar *)[NSString stringWithContentsOfFile:vShaderFilePath encoding:NSUTF8StringEncoding error:nil].UTF8String;
    glShaderSource(vShaderID, 1, &vShaderSource, NULL);//着色器源码附加到着色器对象上
    glCompileShader(vShaderID);//编译
    /// fragment shader
    GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    NSString *fShaderFilePath = [[NSBundle mainBundle] pathForResource:@"shaderF" ofType:@"glsl"];
    const GLchar *fShaderSource = (GLchar *)[NSString stringWithContentsOfFile:fShaderFilePath encoding:NSUTF8StringEncoding error:nil].UTF8String;
    glShaderSource(fShaderID, 1, &fShaderSource, NULL);
    glCompileShader(fShaderID);
    /// program
    if (programID) {
        glDeleteProgram(programID);
        programID = 0;
    }
    programID = glCreateProgram();
    glAttachShader(programID, vShaderID);// 附加着色器
    glAttachShader(programID, fShaderID);
    glDeleteShader(vShaderID); // 释放已经附加到program上去,不再需要的着色器
    glDeleteShader(fShaderID);
    glLinkProgram(programID);
    GLint linkSuccess;
    glGetProgramiv(programID, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetProgramInfoLog(programID, sizeof(messages), 0, &messages[0]);
        NSLog(@"program link error: %@", [NSString stringWithUTF8String:messages]);
        return;
    }
    glUseProgram(programID);
    /// shader attribute
    GLuint position = glGetAttribLocation(programID, "position");
    glEnableVertexAttribArray(position);
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLfloat *)NULL);
    GLuint positionColor = glGetAttribLocation(programID, "positionColor");
    glEnableVertexAttribArray(positionColor);
    glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLfloat *)NULL + 3);
    /// shader uniform
    GLuint projectionMatrixID = glGetUniformLocation(programID, "projectionMatrix");
    KSMatrix4 projectionMatrix;
    ksMatrixLoadIdentity(&projectionMatrix);//获取单元矩阵
    float width = self.frame.size.width;
    float height = self.frame.size.height;
    float aspect = width / height;
    ksPerspective(&projectionMatrix, 30.0, aspect, 5.0f, 20.0f); //获取透视矩阵
    /*
    void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value);
    参数列表:
    location:指要更改的uniform变量的位置
    count:更改矩阵的个数
    transpose:是否要转置矩阵,并将它作为uniform变量的值。必须为GL_FALSE
    value:执行count个元素的指针,用来更新指定uniform变量
    */
    glUniformMatrix4fv(projectionMatrixID, 1, GL_FALSE, (GLfloat*)&projectionMatrix.m[0][0]);
    GLuint modelViewMatrixID = glGetUniformLocation(programID, "modelViewMatrix");
    KSMatrix4 modelViewMatrix;
    ksMatrixLoadIdentity(&modelViewMatrix);
    ksTranslate(&modelViewMatrix, 0.0, 0.0, -10.0);//平移
    KSMatrix4 rotationMatrix;
    ksMatrixLoadIdentity(&rotationMatrix);
    ksRotate(&rotationMatrix, self.xDegree, 1.0, 0.0, 0.0); //绕X轴
    ksRotate(&rotationMatrix, self.yDegree, 0.0, 1.0, 0.0); //绕Y轴
    ksRotate(&rotationMatrix, self.zDegree, 0.0, 0.0, 1.0); //绕Z轴
    ksMatrixMultiply(&modelViewMatrix, &rotationMatrix, &modelViewMatrix);
    glUniformMatrix4fv(modelViewMatrixID, 1, GL_FALSE, (GLfloat *)&modelViewMatrix.m[0][0]);
    /*
    void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices);
    参数列表:
    mode:要呈现的画图的模型
               GL_POINTS
               GL_LINES
               GL_LINE_LOOP
               GL_LINE_STRIP
               GL_TRIANGLES
               GL_TRIANGLE_STRIP
               GL_TRIANGLE_FAN
    count:绘图个数
    type:类型
            GL_BYTE
            GL_UNSIGNED_BYTE
            GL_SHORT
            GL_UNSIGNED_SHORT
            GL_INT
            GL_UNSIGNED_INT
    indices:绘制索引数组
    */
    glDrawElements(GL_TRIANGLES, sizeof(indexArray)/sizeof(indexArray[0]), GL_UNSIGNED_INT, indexArray);
    [context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)deleteBuffer {
    glDeleteBuffers(1, &renderBufferID);
    renderBufferID = 0;
    glDeleteBuffers(1, &frameBufferID);
    frameBufferID = 0;

}



/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end

15857952140063.jpg 15857952019369.jpg 索引绘图可以简化构建图元的顶点数组的创建。通用顶点不用重复添加了。但是这样顶点颜色和顶点纹理坐标都是固定的,如果在不同图元里同一个顶点的颜色和纹理坐标不一致,那么需要在顶点数组里再添加一个同顶点不同颜色和纹理坐标的数据。

纹理颜色混合

#import "RenderView.h"
#import <OpenGLES/ES3/gl.h>
#import "GLESMath.h"

@interface RenderView ()

@property (nonatomic, strong) EAGLContext *context;
@property (nonatomic, strong) CAEAGLLayer *glLayer;
@property (nonatomic, assign) GLuint renderBuffer;
@property (nonatomic, assign) GLuint frameBuffer;
@property (nonatomic, assign) GLuint program;
@property (nonatomic, assign) GLuint vertices;

@end

@implementation RenderView

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (void)layoutSubviews {

    /* Context */
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    if (!self.context) {
        NSLog(@"context create error");
        return;
    }
    [EAGLContext setCurrentContext:self.context];

    /* Layer */
    self.glLayer = (CAEAGLLayer *)self.layer;
    [self setContentScaleFactor:[UIScreen mainScreen].scale];
    self.glLayer.opaque = YES;
    self.glLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @(NO),
                                        kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8
    };

    /* render buffer & frame buffer */
    [self deleteBuffer];
    glGenRenderbuffers(1, &_renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, self.renderBuffer);
    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.glLayer];
    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.renderBuffer);

    [self render];
}

- (void)deleteBuffer {
    glDeleteRenderbuffers(1, &_renderBuffer);
    self.renderBuffer = 0;
    glDeleteFramebuffers(1, &_frameBuffer);
    self.frameBuffer = 0;
}

- (void)render {
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glViewport(self.frame.origin.x*[UIScreen mainScreen].scale, self.frame.origin.y*[UIScreen mainScreen].scale, self.frame.size.width*[UIScreen mainScreen].scale, self.frame.size.height*[UIScreen mainScreen].scale);
    /* vertice shader*/
    GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
    NSString *vFile = [[NSBundle mainBundle] pathForResource:@"shaderV" ofType:@"glsl"];
    NSString *vContent = [NSString stringWithContentsOfFile:vFile encoding:NSUTF8StringEncoding error:nil];
    const GLchar *vSource = (GLchar *)vContent.UTF8String;
    glShaderSource(vShader, 1, &vSource, NULL);
    glCompileShader(vShader);
    GLint vLink;
    glGetShaderiv(vShader, GL_COMPILE_STATUS, &vLink);
    if (vLink == GL_FALSE) {
        GLchar vMessages[256];
        glGetShaderInfoLog(vShader, sizeof(vMessages), 0, &vMessages[0]);
        NSString *error = [NSString stringWithUTF8String:vMessages];
        NSLog(@"vertice shader Compile error: %@", error);
        return;
    }
    /* fragment shader*/
    GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
    NSString *fFile = [[NSBundle mainBundle] pathForResource:@"shaderF" ofType:@"glsl"];
    NSString *fContent = [NSString stringWithContentsOfFile:fFile encoding:NSUTF8StringEncoding error:nil];
    const GLchar *fSource = (GLchar *)fContent.UTF8String;
    glShaderSource(fShader, 1, &fSource, NULL);
    glCompileShader(fShader);
    GLint fLink;
    glGetShaderiv(fShader, GL_COMPILE_STATUS, &fLink);
    if (fLink == GL_FALSE) {
        GLchar fMessages[256];
        glGetShaderInfoLog(fShader, sizeof(fMessages), 0, &fMessages[0]);
        NSString *error = [NSString stringWithUTF8String:fMessages];
        NSLog(@"fragment shader Compile error: %@", error);
        return;
    }
    /* program */
    self.program = glCreateProgram();
    glAttachShader(self.program, vShader);
    glAttachShader(self.program, fShader);
    glDeleteShader(vShader);
    glDeleteShader(fShader);
    glLinkProgram(self.program);
    GLint pLink;
    glGetProgramiv(self.program, GL_LINK_STATUS, &pLink);
    if (pLink == GL_FALSE) {
        GLchar pMessages[256];
        glGetProgramInfoLog(self.program, sizeof(pMessages), 0, &pMessages[0]);
        NSString *error = [NSString stringWithUTF8String:pMessages];
        NSLog(@"program link error: %@", error);
        return;
    }
    glUseProgram(self.program);
    /* 顶点 x,y,z, r,g,b, s,t*/
    GLfloat vertices[] = {
        -0.5, 0.5, 0.0,     1.0, 0.0, 0.0,    0.0, 1.0,
        0.5, 0.5, 0.0,      0.0, 1.0, 0.0,    1.0, 1.0,
        -0.5, -0.5, 0.0,    0.0, 0.0, 1.0,    0.0, 0.0,
        0.5, -0.5, 0.0,     1.0, 1.0, 0.0,    1.0, 0.0,
        0.0, 0.0, 1.0,      0.0, 1.0, 1.0,    0.5, 0.5,
    };
    /* 索引 */
    GLint index[] = {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3,
    };
    if (self.vertices == 0) {
        glGenBuffers(1, &_vertices);
    }
    glBindBuffer(GL_ARRAY_BUFFER, self.vertices);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
    /* texture */
    CGImageRef image = [UIImage imageNamed:@"kkk.png"].CGImage;
    if (!image) {
        NSLog(@"纹理图片不存在");
        return;
    }
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    GLubyte *imageData = (GLubyte *)calloc(width * height * 4, sizeof(GLubyte));
    CGContextRef imageContext = CGBitmapContextCreate(imageData, width, height, 8, width * 4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
    CGRect rect = CGRectMake(0, 0, width, height);
    CGContextDrawImage(imageContext, rect, image);
    CGContextRelease(imageContext);

    glBindTexture(GL_TEXTURE_2D, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (float)width, (float)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
    free(imageData);
    /* shader data input */
    GLuint position = glGetAttribLocation(self.program, "position");
    glEnableVertexAttribArray(position);
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL);
    GLuint positionColor = glGetAttribLocation(self.program, "positionColor");
    glEnableVertexAttribArray(positionColor);
    glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);
    GLuint textureCoor = glGetAttribLocation(self.program, "textureCoor");
    glEnableVertexAttribArray(textureCoor);
    glVertexAttribPointer(textureCoor, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);
    GLuint colorMap = glGetUniformLocation(self.program, "colorMap");
    glUniform1i(colorMap, 0);
    GLuint projectionMatrix = glGetUniformLocation(self.program, "projectionMatrix");
    KSMatrix4 _projectionMatrix;
    ksMatrixLoadIdentity(&_projectionMatrix);
    ksPerspective(&_projectionMatrix, 30.0, self.frame.size.width/self.frame.size.height, 5.0f, 20.0f);
    glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
    GLuint modelViewMatrix = glGetUniformLocation(self.program, "modelViewMatrix");
    KSMatrix4 _modelViewMatrix;
    ksMatrixLoadIdentity(&_modelViewMatrix);
    ksTranslate(&_modelViewMatrix, 0.0, 0.0, -7.0);
    KSMatrix4 _rotationMatrix;
    ksMatrixLoadIdentity(&_rotationMatrix);
    ksRotate(&_rotationMatrix, self.xDegree, 1.0, 0.0, 0.0); //绕X轴
    ksRotate(&_rotationMatrix, self.yDegree, 0.0, 1.0, 0.0); //绕Y轴
    ksRotate(&_rotationMatrix, self.zDegree, 0.0, 0.0, 1.0); //绕Z轴
    ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix);
    glUniformMatrix4fv(modelViewMatrix, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
    /* render */
    glDrawElements(GL_TRIANGLES, sizeof(index)/sizeof(index[0]), GL_UNSIGNED_INT, index);
    [self.context presentRenderbuffer:GL_RENDERBUFFER];

}

@end

GLKit

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) EAGLContext *context;
@property (nonatomic, strong) GLKBaseEffect *effect;
@property(nonatomic,assign)int count;
//旋转的度数
@property(nonatomic,assign)float XDegree;
@property(nonatomic,assign)float YDegree;
@property(nonatomic,assign)float ZDegree;

//是否旋转X,Y,Z
@property(nonatomic,assign) BOOL XB;
@property(nonatomic,assign) BOOL YB;
@property(nonatomic,assign) BOOL ZB;

@end

@implementation ViewController
{
    dispatch_source_t timer;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    [EAGLContext setCurrentContext:self.context];
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    GLfloat verticeArray[] = {
        -0.5f, 0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       0.0f, 1.0f,
        0.5f, 0.5f, 0.0f,       0.0f, 0.5f, 0.0f,       1.0f, 1.0f,
        -0.5f, -0.5f, 0.0f,     0.5f, 0.0f, 1.0f,       0.0f, 0.0f,
        0.5f, -0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       1.0f, 0.0f,
        0.0f, 0.0f, 1.0f,       1.0f, 1.0f, 1.0f,       0.5f, 0.5f,
    };
    GLuint indexArray[] = {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3,
    };
    self.count = sizeof(indexArray) /sizeof(GLuint);

    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticeArray), verticeArray, GL_STATIC_DRAW);

    GLuint index;
    glGenBuffers(1, &index);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexArray), indexArray, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL);
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6);

    NSString *file = [[NSBundle mainBundle] pathForResource:@"kkk" ofType:@"png"];
    NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES),
    };
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:file options:options error:nil];

    self.effect = [[GLKBaseEffect alloc]init];
    self.effect.texture2d0.enabled = GL_TRUE;
    self.effect.texture2d0.name = textureInfo.name;
    CGSize size = self.view.bounds.size;
    float aspect = fabs(size.width / size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 10.f);
    projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0f, 1.0f, 1.0f);
    self.effect.transform.projectionMatrix = projectionMatrix;
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

    double seconds = 0.1;
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0);
    dispatch_source_set_event_handler(timer, ^{

        self.XDegree += 0.02f * self.XB;
        self.YDegree += 0.02f * self.YB;
        self.ZDegree += 0.02f * self.ZB ;

    });
    dispatch_resume(timer);
}

-(void)update
{
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);

    modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.XDegree);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.YDegree);
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.ZDegree);

    self.effect.transform.modelviewMatrix = modelViewMatrix;

}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    [self.effect prepareToDraw];
    glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);

}

- (IBAction)XClick:(id)sender {
    _XB = !_XB;
}
- (IBAction)YClick:(id)sender {
    _YB = !_YB;
}
- (IBAction)ZClick:(id)sender {
    _ZB = !_ZB;
}

@end

代码示例见:Github