我一直在尝试使用顶点缓冲区对象来保存GPU上的顶点数据并减少开销,但我无法让它工作。代码如下。
根据我的理解,您使用glGenBuffers
生成缓冲区,然后将缓冲区与glBindBuffer
绑定,以便可以使用它,然后使用glBufferData
将数据写入其中已完成,可以解除绑定,以后再使用,只需再次绑定即可。
然而,最后一部分是我遇到的问题,当我在创建并加载数据并尝试使用它之后绑定它时,它给了我很多GL Error: Out of Memory.
我怀疑我的简单网格内存不足,所以我一定做错了。
感谢。
编辑1:我在每一帧之后调用glGetError,但由于这是我在整个程序中唯一的OpenGL,它应该不是问题
//when loading the mesh we create the VBO
void createBuffer()
{
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ARRAY_BUFFER, buf);
glBufferData(GL_ARRAY_BUFFER, vertNormalBuffer->size() * sizeof(GLfloat), (GLvoid*) bufferData, GL_STATIC_DRAW);
//EDIT 1: forgot to show how I handle the buffer
model->vertexNormalBuffer = &buf;
//Unbinds it
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::doRedraw(GLuint shaderProgram)
{
glm::mat4 transformationMatrix = getTransform();
GLuint loc = glGetUniformLocation(shaderProgram,"modelviewMatrix");
glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*) &transformationMatrix);
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
//If I uncomment this line below all works wonderfully, but isnt the purpose of VBO of not uploading the same data again and again?
//glBufferData(GL_ARRAY_BUFFER, model->vertAndNormalArraySize * sizeof(GLfloat), model->vertAndNormalArray, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
renderChild(model, model);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::renderChild(ModelObject* model, ModelObject* parent)
{
//Recursively render the mesh children
for(int i = 0; i < model->nChildren; i++)
{
renderChild( dynamic_cast<ModelObject*>(model->children[i]), parent);
}
//Vertex and normal data are interlieved
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat),(void*)(model- >vertexDataPosition*sizeof(GLfloat)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (void*)((model->vertexDataPosition + 4)*sizeof(GLfloat)));
//Draws using two sets of indices
glDrawElements(GL_QUADS, model->nQuads * 4, GL_UNSIGNED_INT,(void*) model->quadsIndices);
glDrawElements(GL_TRIANGLES, model->nTriangles * 3, GL_UNSIGNED_INT, (void*) model->trisIndices);
}
答案 0 :(得分:5)
这是你的问题:
model->vertexNormalBuffer = &buf;
/* ... */
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
您正在存储buf变量的地址,而不是其内容,然后在createBuffer
返回时超出范围,并且很可能被其他数据覆盖,因此当您稍后渲染时,你正在使用一个未初始化的缓冲区。只需在buf
字段中存储vertexNormalBuffer
的内容。
我会承认,我不知道为什么OpenGL认为它只是因为它而“缺乏内存”,但也许你只是在调用未定义的行为。但是,它确实解释了为什么在重新绑定数据后用数据重新填充缓冲区时它开始工作,因为然后隐式初始化刚刚绑定的缓冲区。