我使用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执行此操作,或者我的第一种方法是好的?
答案 0 :(得分:3)
但是可以多次调用glBufferData(对于每个网格) 并在场景加载期间填充VBO(每个步骤一步一步 啮合)。所以它看起来像一个realloc。是否可以这样做 OpenGL或我的第一种方法是好的吗?
没有。每当您拨打glBufferData
时,都会创建一个新的数据存储(创建新的大小,之前的内容将丢失。
但是,在许多情况下,在同一个VBO中组合多个对象仍然是一种有效的策略,特别是如果很多这些对象可能被绘制在一起。
您无法动态调整缓冲区对象的大小。你可以做的是预先分配更大的缓冲区并更新它的一部分。拥有一堆合理大小的缓冲区并可动态填充可能是一种可行的策略。请注意,还有GL_ARB_copy_buffer(自GL 3.1起核心,因此广泛可用),它将允许您非常高效的服务器端副本,您甚至可以通过分配新的模拟“realloc
”行为缓冲并复制旧内容。
哪种策略最好总是取决于具体情况。如果您经常动态加载或销毁对象,则使用一些复杂的缓冲区分配和管理策略可能会获得回报。