4

今天下午,当我从使用 VBO 转移到 VAO / VBO 时,我一直在努力说服我的 openGLES2.0 代码正确执行。基本上,我正在努力通过苹果关于 openGLES 的“专家”建议,并转向使用顶点数组对象是最重要的......

我在这里查看了类似的问题和回复,但这似乎对我没有帮助,除了再次向我保证其他人遇到类似的问题:(

我的场景是我有大约 500 个矩形纹理在屏幕上移动。没有 VAO,代码一切正常,但是当我定义 USE_VAO(我的常量)时,它在第一次绘制元素调用时崩溃。我显然没有正确理解 VAO ......但我看不到我的方式的错误!

setupBeforeRender 方法在进入渲染循环之前作为我设置的最后一部分被调用。

-(void) setupBeforeRender {

glClearColor(0.6, 0.6, 0.6, 1);
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
glEnable(GL_DEPTH_TEST);

glUniform1i(_textureUniform, 0);
glActiveTexture(GL_TEXTURE0); 

glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
glEnableVertexAttribArray(_texCoordSlot);


glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

}

这是渲染方法

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

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Model view matrix and projection code removed for clarity

GLsizei stride = sizeof(Vertex);
const GLvoid* colourOffset = (GLvoid *) sizeof(float[3]);
const GLvoid* textureOffset = (GLvoid *) sizeof(float[7]);

 for (my objectToDraw in objectToDrawArray)
 {

    if (objectToDraw.vertexBufferObject == 0)
    {

        #ifdef USE_VAO

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

        glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
        glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
        glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE,stride, textureOffset);    

        objectToDraw.vertexBufferObject = [objectToDraw createAndBindVBO];
        objectToDraw.vertexArrayObject = _vao;
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArrayOES(0);

        #else

        objectToDraw.vertexBufferObject = [objectToDraw createAndBindVBO];

        #endif
    }

   // Texture binding removed for clarity     

    #ifdef USE_VAO

    // This code crashes with EXC_BAD_ACCESS on the glDrawElements  

    glBindVertexArrayOES(objectToDraw.vertexArrayObject);
    glDrawElements(GL_TRIANGLES, sizeof(Indices) / sizeof(Indices[0]), GL_UNSIGNED_SHORT,0);
    glBindVertexArrayOES(0);                

    #else        

    // This path works fine. So turning VAO off works :(

    glBindBuffer(GL_ARRAY_BUFFER, storyTile.vertexBufferObject);
    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
    glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, stride, textureOffset);

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

    #endif

} // End for each object

[_context presentRenderbuffer:GL_RENDERBUFFER];

}

最后,我的创建和绑定 VBO 方法如下所示;

-(GLuint) createAndBindVBO {

const float* rgba = CGColorGetComponents([self.colour CGColor]);

Vertex Vertices[] = {
    {{0, 1, 0}, {1, 0, 1, 1}, {0,1}},
    {{0, 0, 0}, {1, 0, 1, 1}, {0,0}},
    {{1, 1, 0}, {1, 0, 1, 1}, {1,1}},
    {{1, 0, 0}, {1, 0, 1, 1}, {1,0}}

};

// Code removed for clarity - sets up geometry and colours    

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

return vertexBuffer;
}

我已经尝试了各种排列,并用 glGetError() 散布了代码,看看这是否有助于指出问题出现的地方。唉,除了 drawElements 调用上的 BAD_ACCESS 崩溃之外,我没有收到任何错误。

编辑:正如建议的那样,不幸的是,这也不起作用

objectToDraw.vertexBufferObject = [objectToDraw createVBO];

glGenVertexArraysOES(1,&_vao);
glBindVertexArrayOES(_vao);
glBindBuffer(GL_ARRAY_BUFFER, objectToDraw.vertexBufferObject);

glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE,stride, textureOffset);    

objectToDraw.vertexArrayObject = _vao;
glBindVertexArrayOES(0);

我必须对顶点数组对象做一些愚蠢的事情......但有人能找出问题所在吗?

4

3 回答 3

4

顶点数组启用标志是 VAO 状态的一部分,因此您需要在绑定 VAO 时使用 glEnableVertexAttribArray 启用顶点属性数组。

来自:http ://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt

生成的顶点数组对象是一个新的状态向量,包括所有状态值(在表 6.2 中列出,除了 ARRAY_BUFFER_BINDING):

  • VERTEX_ATTRIB_ARRAY_ENABLED
  • VERTEX_ATTRIB_ARRAY_SIZE,
  • VERTEX_ATTRIB_ARRAY_STRIDE,
  • VERTEX_ATTRIB_ARRAY_TYPE,
  • VERTEX_ATTRIB_ARRAY_NORMALIZED,
  • VERTEX_ATTRIB_ARRAY_POINTER,
  • ELEMENT_ARRAY_BUFFER_BINDING,
  • VERTEX_ATTRIB_ARRAY_BUFFER_BINDING。
于 2012-07-04T20:09:40.610 回答
0

您应该在函数调用glVertexAttribPointer之后glBindBuffer调用。

于 2012-07-04T19:18:20.267 回答
0

我也遇到了类似的问题,不知道是什么原因造成的。

最终结果是我必须在 glDrawArrays 中放入一个 const int 顶点数。sizeof() 做得不对。

于 2012-12-05T17:32:24.970 回答