OpenGLES2 iOS顶点数组对象在drawElements上导致错误的访问错误

时间:2012-07-04 19:10:23

标签: ios opengl-es 3d opengl-es-2.0

今天下午,当我从使用VBO转到VAO / VBO时,我一直在抨击我的openGLES2.0代码。基本上我正在通过Apple关于openGLES的“专家”建议,并且转向使用Vertex Array Objects是最重要的......

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

我的情况是我在屏幕周围移动了大约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];

}

最后,我的create和bind 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);

我必须对顶点数组对象做一些愚蠢的事情......但有人能弄明白问题是什么吗?

3 个答案:

答案 0 :(得分: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。
  •   

答案 1 :(得分:0)

您应在glVertexAttribPointer函数调用后调用glBindBuffer

答案 2 :(得分:0)

我有类似的问题,不知道是什么导致它。

最终我发现我必须在glDrawArrays中放入一个const int数量的顶点。 sizeof()做得不对。