错误的访问代码 1 glDrawElements

Bad access code 1 glDrawElements

本文关键字:glDrawElements 代码 访问 错误      更新时间:2023-10-16

我正在尝试通过批处理来绘制每一帧的内容。这意味着我必须使用我不熟悉的glBufferSubData()。我认为我在替换数据时做错了什么,导致调用glDrawElements时访问冲突。

我的设置代码:

GL_TRY(glGenVertexArrays(1, &mVao));
GL_TRY(glBindVertexArray(mVao));
GL_TRY(glGenBuffers(1, &mEbo));
GL_TRY(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo));
GL_TRY(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glGenBuffers(1, &mVbo));
GL_TRY(glBindBuffer(GL_ARRAY_BUFFER, mVbo));
GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GLint posAttrib;
GL_TRY(posAttrib = glGetAttribLocation(mShader.getProgram(), "position"));
GL_TRY(glEnableVertexAttribArray(posAttrib));
GL_TRY(glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0));
GLint texAttrib;
GL_TRY(texAttrib = glGetAttribLocation(mShader.getProgram(), "texCoords"));
GL_TRY(glEnableVertexAttribArray(texAttrib));
GL_TRY(glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))));
GL_TRY(glBindVertexArray(0));

我的绘图代码:

GL_TRY(glBindVertexArray(mVao));
GL_TRY(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEbo));
GL_TRY(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(GLuint), &indices[0]));
GL_TRY(glBindBuffer(GL_ARRAY_BUFFER, mVbo));
GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));
GL_TRY(glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, 0));
GL_TRY(glBindVertexArray(0));

我一直在检查所有内容并尝试调试一段时间,但我就是找不到我做错了什么。

为了记录,GL_TRY是一个报告任何 OpenGL 错误的宏。我什么都没有得到。

缓冲区

的大小始终为 0:

GL_TRY(glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));

glBufferData()的第二个参数指定缓冲区的大小,在本例中为 0。

顾名思义,glBufferSubData()只能替换缓冲区的子部分。它无法更改大小。所以在此调用后大小仍然是 0。您实际上应该从此调用中得到一个GL_INVALID_VALUE错误。

查看这些入口点的一种方法是:

  • glBufferData()分配缓冲区内存,并选择性地用数据填充它。当使用 NULL 作为数据指针调用时,对 CPU 内存的类似调用是 malloc()
  • glBufferSubData()将数据写入已分配的缓冲区内存。它不会更改分配的内存量。对 CPU 内存的类似调用是 memcpy()

要完成这项工作,您需要将大小传递给 glBufferData()

GL_TRY(glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), NULL, GL_STREAM_DRAW));
GL_TRY(glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), &vertices[0]));

在这种情况下,使用 glBufferSubData() 并没有多大意义。您也可以将数据传递给此处glBufferData()glBufferSubData()主要在只想替换部分缓冲区时有用。

若要在机箱中使用glBufferSubData(),只需在设置过程中调用glBufferData()一次。只要大小恒定,这将很好地工作,或者您至少可以建立一个良好的上限。否则,当大小更改时,您将不得不再次调用它。但是,如果您想有效地使用glBufferSubData(),这仍然必须比每次绘制调用的频率低得多。否则,最好将数据指定为glBufferData()调用的一部分:

GL_TRY(glBufferData(GL_ARRAY_BUFFER,
                    vertices.size() * sizeof(Vertex), &vertices[0]), GL_STREAM_DRAW));