访问代码错误1 glDrawElements

时间:2014-12-21 15:31:48

标签: c++ opengl

我试图通过批处理来绘制每一帧的东西。这意味着我必须使用我不熟悉的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错误的宏。我没有得到任何。

1 个答案:

答案 0 :(得分:1)

缓冲区的大小始终为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));