我正在尝试通过批量绘制每个框架。这意味着我必须使用我不熟悉的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));
关于c++ - 错误的访问代码1 glDrawElements,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27590842/