OpenGL ES 2.0绘制的简单三角形没有显示任何内容

时间:2012-12-23 16:53:34

标签: ios opengl-es opengl-es-2.0 glkit

我完全没有想法。

我有OpenGL ES 2.0编程指南书,我有Apple的模板OpenGL ES 2.0代码,我已经按照这个页面:http://open.gl/drawing

我似乎无法得到一个简单的三角形,我不确定我做错了什么。

注意:我也有一个GameViewController.xib文件,它是GLKView的子类,就像Apple的模板代码一样。

我的顶点着色器:

attribute vec4 position;

void main()
{
    gl_Position = position;
}

我的片段着色器:

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

我的GameViewController标题文件:

#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>

@interface GameViewController : GLKViewController

@end

我的GameViewController实现文件:

#import "GameViewController.h"

const GLfloat vertices[] =
{
    0.0f, 0.5f,
    -0.5f, -0.5f,
    0.5f, -0.5f
};

// Class extension to keep data private
@interface GameViewController()
{        
    // vertex buffer object
    GLuint vbo;

    // vertex array object
    GLuint vao;

    // shader program
    GLuint shaderProgram;
}

@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

@end

@implementation GameViewController

// setup our OpenGL context
-(void)viewDidLoad
{
    [super viewDidLoad];

    [self setupContext];

    // -------------------------------------------------------------
    // create a vertex array object that will hold
    // all the linking between attributes and vertex data
    // -------------------------------------------------------------
    [self createVertexArrayObject];

    [self createVertexBufferObject];

    [self loadShaders];

    [self checkErrors];
}

-(void)checkErrors
{
    GLenum error = glGetError();

    switch (error) {
        case GL_NO_ERROR:
            NSLog(@"No errors");
            break;
        case GL_INVALID_ENUM:
            NSLog(@"An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_VALUE:
            NSLog(@"A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_OPERATION:
            NSLog(@"The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            NSLog(@"The frameBuffer object is not complete. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_OUT_OF_MEMORY:
            NSLog(@"There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.");
            break;
        case GL_STACK_UNDERFLOW:
            NSLog(@"An attempt has been made to perform an operation that would cause an internal stack to underflow.");
            break;
        case GL_STACK_OVERFLOW:
            NSLog(@"An attempt has been made to perform an operation that would cause an internal stack to overflow.");
            break;
        default:
            break;
    }
}

#pragma mark - Setup Context -

-(void)setupContext
{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if(!self.context)
    {
        NSLog(@"Failed to create OpenGL ES Context");
    }

    // tell our view the context is an OpenGL context
    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [EAGLContext setCurrentContext:self.context];

    self.effect = [[GLKBaseEffect alloc] init];

    glEnable(GL_DEPTH_TEST);
}

#pragma mark - Vertex Array Object Methods -

-(void)createVertexArrayObject
{
    glGenVertexArraysOES(1, &vao);
    glBindVertexArrayOES(vao);
}

#pragma mark - Create Vertex Buffer Object Method -

-(void)createVertexBufferObject;
{
    glGenBuffers(1, &vbo); // Generate 1 memory buffer for the VBO

    // Make our VBO the current buffer object to receive data
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // -------------------------------------------------------------
    // Start copying data to our VBO
    //
    // GL_STATIC_DRAW will upload once and drawn many times
    // -------------------------------------------------------------
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

}

#pragma mark - Shader Code -

-(void)loadShaders
{
    // load both vertex shader and fragment shader
    GLuint vertexShader = [self compileVertexShader];
    GLuint fragmentShader = [self compileFragmentShader];

    // create a shader program from the vertex shader and fragment shader
    shaderProgram = [self combineVertexShader:vertexShader AndFragmentShader:fragmentShader];

    // linking vertex data and attributes
    GLint positionAttrib = glGetAttribLocation(shaderProgram, "position");

    glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(positionAttrib);
}

-(GLuint)compileVertexShader
{
    // get the path to the shader file as a C string
    const GLchar *vertexShaderPath = (GLchar *)[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]
                                                                          encoding:NSUTF8StringEncoding
                                                                             error:nil] UTF8String];

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderPath, NULL);
    glCompileShader(vertexShader);

    // Checking if shader compiled properly
    GLint status;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Vertex shader compiled correctly");
    }
    else
    {
        NSLog(@"Vertex shader compiled failed");
    }

    GLint logLength;
    glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(vertexShader, logLength, &logLength, log);
        NSLog(@"Vertex Shader compile log:\n%s", log);
        free(log);
    }

    return vertexShader;
}

-(GLuint)compileFragmentShader
{
    // get the path to the shader as a C string
    const GLchar *fragmentShaderPath = (GLchar *)[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]
                                                                          encoding:NSUTF8StringEncoding
                                                                             error:nil] UTF8String];

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderPath, NULL);
    glCompileShader(fragmentShader);

    // Checking if shader compiled properly
    GLint status;
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Fragment shader compiled correctly");
    }
    else
    {
        NSLog(@"Fragment shader compiled failed");
    }

    GLint logLength;
    glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(fragmentShader, logLength, &logLength, log);
        NSLog(@"Fragment Shader compile log:\n%s", log);
        free(log);
    }

    return fragmentShader;
}

-(void)linkProgram:(GLuint)paramShaderProgram
{
    // link shader to program now and become active shader program
    glLinkProgram(paramShaderProgram);

    GLint status;
    // test if the program linked correctly
    glGetProgramiv(paramShaderProgram, GL_LINK_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Shader program linked correctly");
    }
    else
    {
        NSLog(@"Shader program linked failed");
    }
}

-(void)validateProgram:(GLuint)paramShaderProgram
{
    GLint status, logLength;

    glValidateProgram(paramShaderProgram);

    glGetProgramiv(paramShaderProgram, GL_VALIDATE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Shader program validated correctly");
    }
    else
    {
        NSLog(@"Shader program validate failed");
    }

    glGetProgramiv(paramShaderProgram, GL_INFO_LOG_LENGTH, &logLength);

    if(logLength > 0)
    {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(paramShaderProgram, logLength, &logLength, log);
        NSLog(@"Program validate log:\n%s", log);
        free(log);
    }
}

-(GLuint)combineVertexShader:(GLuint)paramVertexShader AndFragmentShader:(GLuint)paramFragmentShader
{
    GLuint newShaderProgram = glCreateProgram();

    glAttachShader(newShaderProgram, paramVertexShader);
    glAttachShader(newShaderProgram, paramFragmentShader);

    [self linkProgram:newShaderProgram];

    [self validateProgram:newShaderProgram];

    // start using shader now, will use the active shader program
    glUseProgram(newShaderProgram);

    return newShaderProgram;
}

#pragma mark - GLKViewController Render Delegate Methods -

-(void)setupViewport
{
    glViewport(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);

    self.effect.transform.projectionMatrix = GLKMatrix4MakeOrtho(-3, 3, -2, 2, 1, -1);
}

-(void)update
{
    [self setupViewport];
}

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    [self.effect prepareToDraw];

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

#pragma mark - Cleanup Memory -

-(void)tearDownContext
{
    [EAGLContext setCurrentContext:self.context];

    // delete vertex buffer object and vertex array object
    glDeleteBuffers(1, &vbo);
    glDeleteVertexArraysOES(1, &vao);

    // delete shader program
    if(shaderProgram)
    {
        glDeleteProgram(shaderProgram);
        shaderProgram = 0;
    }

    // unset OpenGL context
    if ([EAGLContext currentContext] == self.context)
    {
        [EAGLContext setCurrentContext:nil];
    }

    self.context = nil;
}

-(void)dealloc
{
    [self tearDownContext];
}

-(void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    if([self isViewLoaded] && self.view.window == nil)
    {
        self.view = nil;

        [self tearDownContext];

        if([EAGLContext currentContext] == self.context)
        {
            [EAGLContext setCurrentContext:nil];
        }

        self.context = nil;
    }

    // Dispose of any resources that can be recreated
}

@end

我所看到的只是我的灰色背景屏幕,我清除了颜色。

如果有人能指出我哪里出错了,那就太好了。

修改

我决定把我个人不喜欢Ray的网站放在一边,只是咬紧牙关,完成了这个教程:

http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial

本教程不使用GLKit这是一个额外的奖励,因为学习者编写自己的帧缓冲区和渲染缓冲区,将它们呈现给屏幕。

我觉得这比使用GLKit更接近OpenGL ES 2.0管道。

正如里卡多所说,使用GLKit需要更多的努力来理解它的价值。

我还强烈建议使用上面Ray的网站教程链接来获取正在运行的程序,而不是试图遵循Apple的模板代码。

在我的情况下,Apple的模板代码与书籍有太多矛盾,造成许多浪费时间。

我还使用GLKit解决了那些仍然对使用GLKit方法感兴趣的人。

解决方案是设置我的投影矩阵和绑定正确的顶点着色器位置属性位置。

我想指出的一个非常重要的注意事项是:

确保目标复制捆绑资源有VERTEX和碎片阴影!

我正处于三角形是黑色的点,无论我在片段着色器文件中输入什么,我都无法改变三角形的颜色。问题是这些着色器文件默认情况下不会复制到捆绑包资源。

无论如何,我的工作更新代码完全在下面提供:

#import "GameViewController.h"

#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
};


const GLfloat vertices[] =
{
    0.0f, 0.5f,
    -0.5f, -0.5f,
    0.5f, -0.5f
};

// Class extension to keep data private
@interface GameViewController()
{
    // vertex buffer object
    GLuint vbo;

    // vertex array object
    GLuint vao;

    // shader program
    GLuint shaderProgram;

    GLKMatrix4 modelViewProjectionMatrix;
    GLKMatrix3 normalMatrix;
}

@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;

@end

@implementation GameViewController

// setup our OpenGL context
-(void)viewDidLoad
{
    [super viewDidLoad];

    [self setupContext];

    [self loadShaders];

    // -------------------------------------------------------------
    // create a vertex array object that will hold
    // all the linking between attributes and vertex data
    // -------------------------------------------------------------
    [self createVertexArrayObject];

    [self createVertexBufferObject];

    [self linkAttributes];

    [self checkErrors];
}

-(void)checkErrors
{
    GLenum error = glGetError();

    switch (error) {
        case GL_NO_ERROR:
            NSLog(@"No errors");
            break;
        case GL_INVALID_ENUM:
            NSLog(@"An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_VALUE:
            NSLog(@"A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_OPERATION:
            NSLog(@"The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            NSLog(@"The frameBuffer object is not complete. The offending command is ignored and has no other side effect than to set the error flag.");
            break;
        case GL_OUT_OF_MEMORY:
            NSLog(@"There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.");
            break;
        case GL_STACK_UNDERFLOW:
            NSLog(@"An attempt has been made to perform an operation that would cause an internal stack to underflow.");
            break;
        case GL_STACK_OVERFLOW:
            NSLog(@"An attempt has been made to perform an operation that would cause an internal stack to overflow.");
            break;
        default:
            break;
    }
}

#pragma mark - Setup Context -

-(void)setupContext
{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if(!self.context)
    {
        NSLog(@"Failed to create OpenGL ES Context");
    }

    // tell our view the context is an OpenGL context
    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [EAGLContext setCurrentContext:self.context];

    self.effect = [[GLKBaseEffect alloc] init];

    //glEnable(GL_DEPTH_TEST);
}

#pragma mark - Vertex Array Object Methods -

-(void)createVertexArrayObject
{
    glGenVertexArraysOES(1, &vao);
    glBindVertexArrayOES(vao);
}

#pragma mark - Create Vertex Buffer Object Method -

-(void)createVertexBufferObject;
{
    glGenBuffers(1, &vbo); // Generate 1 memory buffer for the VBO

    // Make our VBO the current buffer object to receive data
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // -------------------------------------------------------------
    // Start copying data to our VBO
    //
    // GL_STATIC_DRAW will upload once and drawn many times
    // -------------------------------------------------------------
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}

-(void)linkAttributes
{
    /*
    // linking vertex data and attributes
    GLint positionAttrib = glGetAttribLocation(shaderProgram, "position");
    glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(positionAttrib);
    */

    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(GLKVertexAttribPosition);

    glBindVertexArrayOES(0);
}

#pragma mark - Shader Code -

-(void)loadShaders
{
    shaderProgram = glCreateProgram();

    // load both vertex shader and fragment shader
    GLuint vertexShader = [self compileVertexShader];
    GLuint fragmentShader = [self compileFragmentShader];

    // create a shader program from the vertex shader and fragment shader
    [self combineVertexShader:vertexShader AndFragmentShader:fragmentShader];

    [self linkProgram:shaderProgram];


    // Release vertex and fragment shaders.
    if (vertexShader) {
        glDetachShader(shaderProgram, vertexShader);
        glDeleteShader(vertexShader);
    }
    if (fragmentShader) {
        glDetachShader(shaderProgram, fragmentShader);
        glDeleteShader(fragmentShader);
    }

    //NSLog(@"uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] before = %d", uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX]);

    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(shaderProgram, "modelViewProjectionMatrix");

    //NSLog(@"uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] after = %d", uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX]);
}

-(GLuint)compileVertexShader
{
    // get the path to the shader file as a C string
    const GLchar *vertexShaderPath = (GLchar *)[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]
                                                                          encoding:NSUTF8StringEncoding
                                                                             error:nil] UTF8String];

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderPath, NULL);
    glCompileShader(vertexShader);

    // Checking if shader compiled properly
    GLint status;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Vertex shader compiled correctly");
    }
    else
    {
        NSLog(@"Vertex shader compiled failed");
    }

    GLint logLength;
    glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(vertexShader, logLength, &logLength, log);
        NSLog(@"Vertex Shader compile log:\n%s", log);
        free(log);
    }

    return vertexShader;
}

-(GLuint)compileFragmentShader
{
    // get the path to the shader as a C string
    const GLchar *fragmentShaderPath = (GLchar *)[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]
                                                                            encoding:NSUTF8StringEncoding
                                                                               error:nil] UTF8String];

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderPath, NULL);
    glCompileShader(fragmentShader);

    // Checking if shader compiled properly
    GLint status;
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Fragment shader compiled correctly");
    }
    else
    {
        NSLog(@"Fragment shader compiled failed");
    }

    GLint logLength;
    glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(fragmentShader, logLength, &logLength, log);
        NSLog(@"Fragment Shader compile log:\n%s", log);
        free(log);
    }

    return fragmentShader;
}

-(void)combineVertexShader:(GLuint)paramVertexShader AndFragmentShader:(GLuint)paramFragmentShader
{
    glAttachShader(shaderProgram, paramVertexShader);
    glAttachShader(shaderProgram, paramFragmentShader);

    glBindAttribLocation(shaderProgram, GLKVertexAttribPosition, "position");

    //[self validateProgram:shaderProgram];
}

-(void)linkProgram:(GLuint)paramShaderProgram
{
    // link shader to program now and become active shader program
    glLinkProgram(paramShaderProgram);

    GLint status;
    // test if the program linked correctly
    glGetProgramiv(paramShaderProgram, GL_LINK_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Shader program linked correctly");
    }
    else
    {
        NSLog(@"Shader program linked failed");
    }

    GLint logLength;
    glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(shaderProgram, logLength, &logLength, log);
        NSLog(@"Program link log:\n%s", log);
        free(log);
    }
}

-(void)validateProgram:(GLuint)paramShaderProgram
{
    GLint status, logLength;

    glValidateProgram(paramShaderProgram);

    glGetProgramiv(paramShaderProgram, GL_VALIDATE_STATUS, &status);

    if(status == GL_TRUE)
    {
        NSLog(@"Shader program validated correctly");
    }
    else
    {
        NSLog(@"Shader program validate failed");
    }

    glGetProgramiv(paramShaderProgram, GL_INFO_LOG_LENGTH, &logLength);

    if(logLength > 0)
    {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(paramShaderProgram, logLength, &logLength, log);
        NSLog(@"Program validate log:\n%s", log);
        free(log);
    }
}

#pragma mark - GLKViewController Render Delegate Methods -

-(void)setupViewport
{
    //float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);

    //GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 1.0f, -10.0f);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1, 1, -1, 1, 1, -1);
    self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

    modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
    normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, GL_FALSE, modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, normalMatrix.m);
}

-(void)update
{
    [self setupViewport];
}

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArrayOES(vao);

    [self.effect prepareToDraw];

    glUseProgram(shaderProgram);

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

#pragma mark - Cleanup Memory -

-(void)tearDownContext
{
    [EAGLContext setCurrentContext:self.context];

    // delete vertex buffer object and vertex array object
    glDeleteBuffers(1, &vbo);
    glDeleteVertexArraysOES(1, &vao);

    // delete shader program
    if(shaderProgram)
    {
        glDeleteProgram(shaderProgram);
        shaderProgram = 0;
    }

    // unset OpenGL context
    if ([EAGLContext currentContext] == self.context)
    {
        [EAGLContext setCurrentContext:nil];
    }

    self.context = nil;
}

-(void)dealloc
{
    [self tearDownContext];
}

-(void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    if([self isViewLoaded] && self.view.window == nil)
    {
        self.view = nil;

        [self tearDownContext];

        if([EAGLContext currentContext] == self.context)
        {
            [EAGLContext setCurrentContext:nil];
        }

        self.context = nil;
    }

    // Dispose of any resources that can be recreated
}

@end

希望能帮助其他人。

1 个答案:

答案 0 :(得分:2)

忘记Apple的OpenGL ES 2.0模板代码。如果你是一个初学者,那里有太多的东西可以正确理解,它混合了OpenGL ES 1.1(GLKBaseEffect)和2.0(着色器)。

最好从头开始创建应用程序并了解GLKit和着色器的优缺点。

本教程使用GLKBaseEffect的固定管道功能对GLKit进行了很好的介绍:

如果你想要更深入的知识并学习如何在iPhone环境中使用着色器,我强烈推荐这本书:

最终,您希望将GLKView组合在一起以绕过所有缓冲池样板代码,并使用着色器来最好地控制程序。 OpenGL ES有一个困难的学习曲线,但是一旦你克服了第一个驼峰,事情会变得更加清晰。