【问题标题】:Use of VAO around VBO in Open ES iPhone app Causes EXC_BAD_ACCESS When Call to glDrawElements在 Open ES iPhone 应用程序中在 VBO 周围使用 VAO 导致调用 glDrawElements 时出现 EXC_BAD_ACCESS
【发布时间】:2011-06-05 03:40:22
【问题描述】:

我正在尝试将我的代码提升到一个新的水平。遵循 Apple 的一些最佳实践,我正在尝试围绕我的顶点缓冲区对象 (VBO) 实现顶点数组对象。我这样设置我的 VBO 和 VAO:

- (void)setupVBOs {  
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArrayOES(0);
    {
        glGenVertexArraysOES(1, &directArrayObject);
        glBindVertexArrayOES(directArrayObject);

    //    GLuint texCoordBuffer;
        glGenBuffers(1, &texCoordBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(DirectVertices), DirectVertices, GL_STATIC_DRAW);

        glVertexAttribPointer(directPositionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(DirectVertex), (GLvoid*)offsetof(DirectVertex, position));
        glEnableVertexAttribArray(directPositionSlot);
        glVertexAttribPointer(texCoordSlot, 2, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(DirectVertex), (GLvoid*)offsetof(DirectVertex, texCoord));
        glEnableVertexAttribArray(texCoordSlot);

        glGenVertexArraysOES(1, &arrayObject);
        glBindVertexArrayOES(arrayObject);

    //    GLuint vertexBuffer;
        glGenBuffers(1, &vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
        glEnableVertexAttribArray(positionSlot);
        glVertexAttribPointer(colorSlot, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Color));
        glEnableVertexAttribArray(colorSlot);

    //    GLuint indexBuffer;
        glGenBuffers(1, &indexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArrayOES(0);
}

我从http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=287977 拿来的,然后像这样使用它:

- (void) render:(CADisplayLink*)displayLink {

    glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, backingWidth, backingHeight);

    [directProgram use];
    glBindVertexArrayOES(directArrayObject);
    glDisable(GL_DEPTH_TEST);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, videoFrameTexture);

//  // Update uniform values
    glUniform1i(videoFrameUniform, 0);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    [program use];
    glBindVertexArrayOES(arrayObject);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);

    CC3GLMatrix *projection = [CC3GLMatrix matrix];
    float h = 4.0f * self.frame.size.height / self.frame.size.width;
    [projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
    glUniformMatrix4fv(projectionUniform, 1, 0, projection.glMatrix);

    CC3GLMatrix *modelView = [CC3GLMatrix matrix];
    [modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
    currentRotation += displayLink.duration * 90;
    [modelView rotateBy:CC3VectorMake(currentRotation, currentRotation, 0)];
    glUniformMatrix4fv(modelViewUniform, 1, 0, modelView.glMatrix);

    glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);

    glBindVertexArrayOES(0);

    BOOL success = [context presentRenderbuffer:GL_RENDERBUFFER];
    if(!success)
        NSLog(@"present failed");
}

对 glDrawArrays 的调用有效,它填充了我的纹理,但是,对 glDrawElements 的调用失败并出现 EXC_BAD_ACCESS。我的着色器程序(我使用了两个)包装在一个 GLProgram 对象中,该对象来自http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html

【问题讨论】:

    标签: ios iphone opengl-es


    【解决方案1】:

    从设置函数的末尾删除glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    根据OES_vertex_array_object 的规范,顶点数组对象封装了所有状态除了数组缓冲区绑定1,因此当时没有元素缓冲区绑定你正在画画,而你大概希望indexBuffer 被绑定。通过在绑定离开顶点数组对象时将 indexBuffer 绑定,您可以确保在返回该顶点数组对象时它会被重新绑定。


    1 如果您想知道为什么在顶点数组对象中没有跟踪数组缓冲区绑定,这可能是因为在读取顶点数据时没有直接使用当前绑定的数组缓冲区数组——相反,每个顶点属性都有自己的缓冲区绑定,由其各自的gl*Pointer 函数通过在函数调用时查看数组缓冲区绑定来填充。

    【讨论】:

    • 太棒了。那成功了。现在,当我分析我的应用程序时,Instruments 建议我使用 glDrawElements 和索引来代替渲染代码顶部的 glDrawArrays。如果是这样,我将有两个元素数组缓冲区。这有关系吗?他们都会被束缚吗?
    • 如果您只是使用 glDrawArrays 来绘制单个四边形并且没有实际重用顶点的可能性,那么切换到 glDrawElements 是没有意义的。即便如此,您正在更改绘制之间绑定的顶点数组对象,所以没问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多