OSX OpenGL核心配置文件的问题以及使用预构建的VBO构建VAO

时间:2015-03-20 12:50:49

标签: objective-c xcode macos opengl

所以我在过去几天里一直从遗留配置文件转移到Core Profile。我已经将我的大部分功能用于使用VBO和着色器,所以我认为它不需要那么多工作。

但是,我无法使用glDrawElements获取我的新核心配置文件上下文。我的应用程序在应用程序范围的背景openglContext中操作纹理,GUI使用与背景上下文共享上下文的OpenGL视图显示其中的各个阶段。

每个纹理对象根据需要为纹理坐标和颜色构建自己的VBO,这样我只能提供新的顶点VBO以便在视图中显示。顶点数量及其绘图是标准化的,因此我可以共享索引缓冲区。

这是我在所有上下文之间共享的Pixel格式:

+ (NSOpenGLPixelFormat *) defaultPixelFormat
{
    NSOpenGLPixelFormatAttribute attrs[] =
    {
        kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core,
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFABackingStore,
        NSOpenGLPFAAllowOfflineRenderers,
        NSOpenGLPFAStencilSize, 8,
        NSOpenGLPFAColorSize, 32,
        NSOpenGLPFADepthSize, 24,
        0
    };
    NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
    return pixFmt;
}

这是我如何在不使用纹理的情况下设置VAO的简短示例,我只是想画一些东西!

- (void) genTestVao
    {
    // Generate buffers first to simulate app environment
    GLfloat verts[] = {
        0.0, 0.0, 0.0, 0.0,
        100.0, 0.0, 0.0, 0.0,
        0.0, 100.0, 0.0, 0.0,
        100.0, 100.0, 0.0, 0.0
    };
    GLfloat colors[] = {
        1.0, 1.0, 1.0, 0.0,
        1.0, 1.0, 1.0, 0.0,
        1.0, 1.0, 1.0, 0.0,
        1.0, 1.0, 1.0, 0.0
    };

    GLushort indices[] = {0, 1, 2, 3};
    if (_testVBuffer) {
        glDeleteBuffers(1, &_testVBuffer);
    }
    if (_testCBuffer) {
        glDeleteBuffers(1, &_testCBuffer);
    }
    if (_testIBuffer) {
        glDeleteBuffers(1, &_testIBuffer);
    }
    glGenBuffers(1, &_testVBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _testVBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW);

    glGenBuffers(1, &_testCBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _testCBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    // vert and colors buffers done

    glGenBuffers(1, &_testIBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _testIBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    // Index buffer done

    // Generate VAO with pre stored buffers
    if (_testVAO) {
        glDeleteVertexArrays(1, &_testVAO);
    }
    glGenVertexArrays(1, &_testVAO);
    glBindVertexArray(_testVAO);
    // Vertex
    glBindBuffer(GL_ARRAY_BUFFER, _testVBuffer);
    glEnableVertexAttribArray(kSCGLVertexAttribPosition);
    glVertexAttribPointer(kSCGLVertexAttribPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 4, 0);
    // Colors
    glBindBuffer(GL_ARRAY_BUFFER, _testCBuffer);
    glEnableVertexAttribArray(kSCGLColorAttribPosition);
    glVertexAttribPointer(kSCGLColorAttribPosition, 4, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 4, 0);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

设置视图矩阵:

    _mvpMatrix = GLKMatrix4Multiply(
                                    GLKMatrix4MakeOrtho(0.0, self.bounds.size.width, 0.0, self.bounds.size.height, -1.0, 1.0),
                                    GLKMatrix4Identity);

绘图代码:

    glUseProgram(self.testShader.shaderProgram);
    glUniformMatrix4fv(self.testShader.mvpMatrixLocation, 1, GL_FALSE, self.mvpMatrix.m);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _testIBuffer);
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glBindTexture(GL_TEXTURE_RECTANGLE, 0);

    glUseProgram(0);

顶点着色器:

#version 150

in vec4 position;
in vec4 color;

uniform mat4 mvpMatrix;

out vec4 vertex_color;

void main()
{
    // perform standard transform on vertex
    gl_Position = position * mvpMatrix;
    vertex_color = color;
}

片段着色器:

#version 150

in vec4 vertex_color;

out vec4 colourout;

void main()
{
    colourout = vertex_color;
}

最后是链接着色器和顶点并绑定属性位置的代码:

- (BOOL) createProgramObjectWithVertexShader:(GLuint) vertShader withFragShader:(GLuint) fragShader
{
    _shaderProgram = glCreateProgram();
    glAttachShader(_shaderProgram, vertShader);


    glBindAttribLocation(_shaderProgram, kSCGLVertexAttribPosition, "position");
    GLenum error = glGetError();
    if (error != GL_NO_ERROR) {
        NSLog(@"Error generated getting position!");

        if (error == GL_INVALID_VALUE) {
            NSLog(@"Invalid value");
        } else if (error == GL_INVALID_OPERATION) {
            NSLog(@"Invalid operation");
        } else {
            NSLog(@"unexpected error");
        }
    }
    glBindAttribLocation(_shaderProgram, kSCGLColorAttribPosition,  "color");
    error = glGetError();
    if (error != GL_NO_ERROR) {
        NSLog(@"Error generated getting color!");

        if (error == GL_INVALID_VALUE) {
            NSLog(@"Invalid value");
        } else if (error == GL_INVALID_OPERATION) {
            NSLog(@"Invalid operation");
        } else {
            NSLog(@"unexpected error");
        }
    }

    //glBindAttribLocation(_shaderProgram, kSCGLNormalAttribPosition, "normal");
    //glBindAttribLocation(_shaderProgram, kSCGLTexCoordPosition,     "texcoord");
    error = glGetError();
    if (error != GL_NO_ERROR) {
        NSLog(@"Error generated getting texcoord!");

        if (error == GL_INVALID_VALUE) {
            NSLog(@"Invalid value");
        } else if (error == GL_INVALID_OPERATION) {
            NSLog(@"Invalid operation");
        } else {
            NSLog(@"unexpected error");
        }
    }

    glAttachShader(_shaderProgram, fragShader);

    glLinkProgram(_shaderProgram);

    glDeleteShader(vertShader);
    glDeleteShader(fragShader);
    GLint result = GL_FALSE;
    GLint infoLogLength = 0;

    glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
    if (infoLogLength > 0) {
        char errMsg[infoLogLength];
        glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, errMsg);
        NSString *msg = [NSString stringWithUTF8String:errMsg];
        NSLog(@"Self = %@", self);
        NSLog(@"Validate program failed with %@", msg);
        if (![msg hasPrefix:@"WARNING:"]) {
            NSLog(@"Fatal");
            glDeleteProgram(_shaderProgram);
            return NO;
        }

    }
    if (![self getUniformLocations]) {
        NSLog(@"Failed getting uniform variables for %@", self.shaderName);
        glDeleteProgram(_shaderProgram);
        return NO;
    }

    return YES;
}

我确信这很简单,但我看不出它是什么,它让我发疯。 opengl视图设置正确,如果我用颜色清除它,它显示正确,它只是不会绘制我的元素....

我转向核心配置文件的部分原因是与iOS应用程序共享代码,除了一些简单的更改,我的大多数opengl代码都兼容。

编辑1: 我创建了一个粗略的,准备好的XCode project that shows the basics on GitHub。应用程序委托持有基本共享的openglContext并加载测试着色器。 openGLView基于App委托的共享上下文:

编辑2: 我通过一些更正来更新项目,现在有些东西可以吸引,但这不是我所期望的。这是我用过的单色,当我预计它在左下角时,它在右上角。

1 个答案:

答案 0 :(得分:0)

一位苹果小伙子在苹果devforums上发布了我的问题的答案。

我无法得到任何东西的原因是矩阵和位置乘法的顺序在顶点着色器中很重要。这一行:

gl_Position = position * mvpMatrix;

应该是:

gl_Position = mvpMatrix * position;

编辑:根据Reto的评论删除了第二部分答案。