为什么将GL_ELEMENT_ARRAY_BUFFER绑定到0会产生memmove错误?

时间:2012-05-11 04:31:32

标签: ios opengl-es-2.0

我有一个错误,花了我很长时间来修复。 在我评论以下行之前,我一直得到EXC_BAD_ACCESS和对memmove错误的引用而没有任何进一步的描述:

[self loadShaders];

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

// Vertex Buffer
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);

glEnableVertexAttribArray(ATTRIB_TEXTURE);
glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));

// Index Buffer
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);  

////////// COMMENTED THIS ONE //////////////
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);//
////////////////////////////////////////////

glBindVertexArrayOES(0);

我认为将缓冲区绑定到0意味着解除绑定,所以我真的不明白这会让我的应用程序崩溃。

感谢您提供的信息!我只是不关心这个问题...

我的结构:

const Vertex Vertices[4] = {
    {{0.75, -1, 0}, {1, 0, 0, 1},     {0.125, 0.833496}},
    {{0.75, 1, 0}, {0, 1, 0, 1},      {0.125, 1}},
    {{-0.75, 1, 0}, {0, 0, 1, 1},     {0,     1}},
    {{-0.75, -1, 0}, {0, 0, 0, 1},    {0,     0.833496}},
};

const GLushort Indices[6] =
{
    0, 1, 2,
    2, 3, 0
};

1 个答案:

答案 0 :(得分:8)

从你的代码中看,这个函数看起来好像在某个初始化例程中,你初始化你的属性数据,它存储在绑定的VAO中,这样在绘图时你只需要绑定VAO。

VAO反过来封装了绘制VBO所需的所有状态,即属性的启用标志(由gl(En/Dis)ableVertexAttribArray设置),属性源和属性(使用glVertexAttribPointer设置),< strong>和当前绑定的索引缓冲区(使用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)设置)。请注意,它不存储当前绑定的顶点缓冲区,因为此信息存储在属性状态中。

所发生的是,您创建并绑定索引缓冲区,设置其数据,然后取消绑定,VAO仍处于活动状态。因此,VAO状态将存储GL_ELEMENT_ARRAY_BUFFER 0绑定。当你现在用

绘制一些东西时
glBindVertexArrayOES(_vao);
glDrawElements(...);

没有缓冲区绑定且glDrawElements失败,因为VAO不能与客户端阵列一起使用。您必须使用VBO作为索引数据或绘制非索引基元(使用glDrawArrays)。

也不会

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBindVertexArrayOES(_vao);
glDrawElements(...);

工作,因为绑定的索引缓冲区在绑定时会被VAO覆盖(其索引缓冲区为0)。如果您首先绑定VAO然后绑定索引缓冲区,它将起作用,但这只会绕过问题。

从概念上讲,绑定GL_ELEMENT_ARRAY_BUFFER是VAO状态的一部分,因此您不应将其绑定到VAO初始化例程中的0(仅当您不需要任何索引数据时)。在使用VAO时,您也不允许将客户端数组用于索引或顶点数据。如果您不想绘制索引几何,只需使用glDrawArrays而不是glDrawElements,但无论如何索引缓冲区都已过时。