对OpenGL VBO分配的简单好奇心

时间:2014-05-18 16:29:20

标签: opengl vbo ido vao

我使用OpenGL和GLSL编写了一个简单的图形引擎。在此之前,当我需要创建一个新的网格场景节点时,我为每个网格创建了一个VAO,一个VBO和一个IBO。我以这种方式为每个网格加载了我的顶点属性:

glBufferData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION)
        + this->GetVerticesByteSize(VERTEX_TEXTURE) + this->GetVerticesByteSize(VERTEX_NORMAL), NULL, this->m_Usage);
    glBufferSubData(GL_ARRAY_BUFFER, 0, this->GetVerticesByteSize(VERTEX_POSITION), &this->m_VertexBuffer[VERTEX_POSITION][0]);
    if (!this->m_VertexBuffer[VERTEX_TEXTURE].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION),
            this->GetVerticesByteSize(VERTEX_TEXTURE), &this->m_VertexBuffer[VERTEX_TEXTURE][0]);
    if (!this->m_VertexBuffer[VERTEX_NORMAL].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(
            VERTEX_POSITION) + this->GetVerticesByteSize(VERTEX_TEXTURE),
                this->GetVerticesByteSize(VERTEX_NORMAL), &this->m_VertexBuffer[VERTEX_NORMAL][0]);

但是如果场景由很多网格组成,那么它的性能就不正确(状态变化太多)。所以,我决定为我场景的所有几何体创建一个独特的VAO,VBO和IBO(单例类)。

执行此操作的方法如下:

为每个网格加载特定类中的所有顶点属性(让我们调用它' VertexAttributes')。加载所有网格后,我们可以在一个唯一的VBO中分配大顶点缓冲区。就像上面一样,我先调用函数' glBufferData'使用我场景中所有顶点属性的大小分配整个内存,然后调用函数' glBufferSubData'对于循环中的每种顶点属性。

但是可以多次调用glBufferData(对于每个网格)并在场景加载期间填充VBO(每个网格逐步调用)。所以它看起来像一个realloc。是否可以使用OpenGL执行此操作,或者我的第一种方法是好的?

1 个答案:

答案 0 :(得分:3)

  

但是可以多次调用glBufferData(对于每个网格)   并在场景加载期间填充VBO(每个步骤一步一步   啮合)。所以它看起来像一个realloc。是否可以这样做   OpenGL或我的第一种方法是好的吗?

没有。每当您拨打glBufferData时,都会创建一个新的数据存储(创建新的大小,之前的内容将丢失。

但是,在许多情况下,在同一个VBO中组合多个对象仍然是一种有效的策略,特别是如果很多这些对象可能被绘制在一起。

您无法动态调整缓冲区对象的大小。你可以做的是预先分配更大的缓冲区并更新它的一部分。拥有一堆合理大小的缓冲区并可动态填充可能是一种可行的策略。请注意,还有GL_ARB_copy_buffer(自GL 3.1起核心,因此广泛可用),它将允许您非常高效的服务器端副本,您甚至可以通过分配新的模拟“realloc”行为缓冲并复制旧内容。

哪种策略最好总是取决于具体情况。如果您经常动态加载或销毁对象,则使用一些复杂的缓冲区分配和管理策略可能会获得回报。