我正在尝试通过批量绘制每个框架。这意味着我必须使用我不熟悉的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/

10-11 00:36