GL 错误:尝试使用 VBO 渲染时内存不足

Posted

技术标签:

【中文标题】GL 错误:尝试使用 VBO 渲染时内存不足【英文标题】:GL Error: Out of Memory when trying to render with VBO 【发布时间】:2014-02-16 00:13:34 【问题描述】:

我一直在尝试使用顶点缓冲区对象在 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);


【问题讨论】:

我在您的代码中找不到任何glGetError。你实际上在哪里检查?您是否在创建缓冲区后直接检查?难道你只是看到之前操作的错误吗? 另外,我不明白你是如何让 buf 从你的 createBuffer 函数中“逃脱”的。 感谢@Dolda2000 的关注,我编辑了这篇文章以展示我对 buf 的处理并解释了我何时调用 glGetError。 【参考方案1】:

这是你的问题:

model->vertexNormalBuffer = &buf;
/* ... */
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);

您存储的是 buf 变量的地址,而不是其内容,然后当 createBuffer 返回时它超出范围,并且很可能被其他数据覆盖,因此当您稍后渲染时,您'正在使用未初始化的缓冲区。只需将buf内容 存储在您的vertexNormalBuffer 字段中即可。

我承认我不知道为什么 OpenGL 认为仅仅因为这个而说它“内存不足”是恰当的,但也许你只是在调用未定义的行为。但是,它确实解释了为什么在重新绑定后用数据重新填充缓冲区时它开始工作,因为您随后隐式初始化了刚刚绑定的缓冲区。

【讨论】:

谢谢!我来自 Java,对 c++ 非常陌生。这就是解决方案! @user3021593:仅供参考,您介意告诉我您使用的是什么 OpenGL 实现吗?就是司机。 不确定,但如果您要问的话,我的显卡驱动程序是 Nvidia 9.18.13.3221。我在哪里可以找到我正在使用的实现? 谢谢,这正是我的意思。 @AndonM.Coleman:因为我一开始看错了代码,以为他在绑定缓冲区时使用了变量的地址。删除和重写答案比编辑它更容易(特别是考虑到有人可能已经阅读它并在编辑过程中感到困惑)。

以上是关于GL 错误:尝试使用 VBO 渲染时内存不足的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES VBO 奇怪的内存影响

Android OpenGL 1.1 FBO 和 VBO 支持

opengl vbo 纹理

使用 VBO 渲染顶点的问题 - OpenGL

glVertexAttribPointer GL_INVALID_OPERATION 无效 vao vbo 指针使用

OpenGL ES 2.0:似乎无法渲染第二个 VBO?