我试图通过批处理来绘制每一帧的东西。这意味着我必须使用我不熟悉的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 :(得分: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));