glBufferData不会删除现有的数据存储

时间:2017-02-17 17:34:56

标签: opengl

documentation

  

glBufferData当前为缓冲区对象创建一个新的数据存储   绑定目标。将删除任何预先存在的数据存储。新数据   使用指定的字节和用法大小创建存储。

所以我编码

    // allocate storage in GPU and copy data
    glBufferData(
      GL_ARRAY_BUFFER,
      myData.VertexCount()*sizeof(GL_FLOAT),
      myData.Vertex(),
      GL_STREAM_DRAW);
    ...
    glDrawArrays(
      GL_TRIANGLES,
      0,
      myData.VertexCount() );
每当我需要刷新场景时执行

顶点的数量会不时变化很大。当顶点数量下降时,旧数据似乎仍然存在,并且出现旧数据的乱码渲染。

我可以通过在每次刷新开始时创建缓冲区索引,然后在之后删除它来解决此问题

    // construct buffer index
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);

   ...

   glDeleteBuffers(1,&vertexbuffer);

目前这很好,但我想稍后重新调整大小,包括重复使用缓冲区中的一些顶点而不需要在每次刷新时制作新的副本。

问题并没出现在我的所有机器上。看起来具有更好显卡的机器没有问题

供参考,以下是整个渲染代码:

    void Render()
    {
        // Background color
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

        glUseProgram( myShaderID );

        // Send our transformation to the currently bound shader,
        // in the "MVP" uniform
        glUniformMatrix4fv(myMatrixID, 1, GL_FALSE, &MVP[0][0]);

        // enable vertices attribute buffer
        glEnableVertexAttribArray(0);

        // make current
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

        // allocate storage in GPU and copy data
        glBufferData(GL_ARRAY_BUFFER, myData.VertexCount()*sizeof(GL_FLOAT),
                     myData.Vertex(), GL_STREAM_DRAW);

        // let shaders access buffer
        glVertexAttribPointer(
            0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void*)0            // array buffer offset
        );

        // 2nd attribute buffer : colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
        glBufferData(GL_ARRAY_BUFFER, myData.VertexCount()*sizeof(GL_FLOAT),
                     myData.Color(), GL_STREAM_DRAW);
        glVertexAttribPointer(
            1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            (void*)0                          // array buffer offset
        );

        glDrawArrays(GL_TRIANGLES, 0, myData.VertexCount() );

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glFlush();
        myCanvas->SwapBuffers();
}

这是最终的固定生产代码。 VertexCount()现在返回实际的顶点数,而不仅仅是顶点向量中的浮点数。

/** Update GL display */
void Render()
{
    // Background color
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

    glUseProgram( myShaderID );

    // Send our transformation to the currently bound shader,
    // in the "MVP" uniform
    glUniformMatrix4fv(
        myMatrixID,
        1,
        GL_FALSE,
        myCamera.ModelViewProjection() );

    // enable vertices attribute buffer
    glEnableVertexAttribArray(0);

    // make current
    glBindBuffer(GL_ARRAY_BUFFER, myVertexBufferID);

    // allocate storage in GPU and copy data
    glBufferData(
        GL_ARRAY_BUFFER,
        3 * myData.VertexCount()*sizeof(GL_FLOAT),
        myData.Vertex(),
        GL_STREAM_DRAW);

    // let shaders access buffer
    glVertexAttribPointer(
        0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // 2nd attribute buffer : colors
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, myColorBufferID);
    glBufferData(
        GL_ARRAY_BUFFER,
        3 * myData.VertexCount()*sizeof(GL_FLOAT),
        myData.Color(),
        GL_STREAM_DRAW);
    glVertexAttribPointer(
        1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
        3,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

    glDrawArrays(GL_TRIANGLES, 0, myData.VertexCount() );

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    glFlush();
    myCanvas->SwapBuffers();

}

2 个答案:

答案 0 :(得分:2)

您的代码不正确。您设置顶点attrib指针以读取每个顶点3 GLfloat s,并使用myData.VertexCount()作为绘制调用中的顶点数,但是您只将myData.VertexCount()*sizeof(GL_FLOAT)个字节上传到VBO。因此,您将读取超过缓冲区末尾的方式,结果只是未定义的行为。

答案 1 :(得分:0)

当您拨打glBufferData时,GL驱动程序会在内存中为您提供一个可能与之前位置相同的位置。您认为可以使用glBufferData更新整个事物的一部分,但事实并非如此。其余的可能与旧数据一致,也可能不一致。

我认为您最好使用glBufferSubData而不是glBufferData来更新新数据(或部分数据)而不删除和重新创建数据存储。

您需要在newSize>时删除并重新创建。 oldSize。