我编写了一个运行良好的 OpenGL 应用程序,我只想提高它的性能。当然,这样做的一个好方法是将多个网格打包在一个唯一的 VBO 中(当然要注意顶点的数量)。所以我不是在谈论巨大的场景,而是在我的例子中是一个只有 2 个网格(一个平面和一个立方体)的简单场景。这是我的场景的快速概述:
现在这里是这 2 个独立网格的一些统计数据(以字节为单位):
Plane mesh :
- Vertex buffer :
- position(size=48)
- texture(size=32)
- normal(size=48)
-> Total = 128 bytes
Box mesh :
- Vertex buffer :
- position(size=312)
- texture(size=208)
- normal(size=312)
-> Total = 832 bytes
目前,我的 2 个网格包含在一个唯一的 VBO 中(当然我有一个唯一的 IBO,其中包含两个网格的索引)。这是我采用的将所有数据存储在单个数组中的模式:
[P(plane)][T(plane)][N(plane)]|[P(cube)][T(cube)][N(cube)]
|0 |48 |80 |128 |440 |648
Caption : P (all position vertices), T (all texture vertices) and N (all normal vertices)
这是一个很好的方法,但它迫使程序员(当然属于我:) 也许它是错误的)为每个网格声明一个特定的 VAO,因为要渲染我的 2 个网格的几何形状,我必须更改缓冲区偏移量以发送数据到着色器程序。
平面网格数据的发送:
glEnableVertexAttribArray(scene::VERTEX_POSITION);
glVertexAttribPointer(scene::VERTEX_POSITION, 3,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(0));
glEnableVertexAttribArray(scene::VERTEX_TEXTURE);
glVertexAttribPointer(scene::VERTEX_TEXTURE, 2,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(48));
glEnableVertexAttribArray(scene::VERTEX_NORMAL);
glVertexAttribPointer(scene::VERTEX_NORMAL, 3,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(80));
Remark : Here, the offsets are 0, 48 and 80
发送立方体网格的数据:
glEnableVertexAttribArray(scene::VERTEX_POSITION);
glVertexAttribPointer(scene::VERTEX_POSITION, 3,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(128));
glEnableVertexAttribArray(scene::VERTEX_TEXTURE);
glVertexAttribPointer(scene::VERTEX_TEXTURE, 2,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(440));
glEnableVertexAttribArray(scene::VERTEX_NORMAL);
glVertexAttribPointer(scene::VERTEX_NORMAL, 3,
GL_FLOAT, GL_FALSE, 0, OFFSET_BUFFER(648));
Remark : Here, the offsets are 128, 440 and 648
正如您使用这种方法所看到的,我需要知道每个网格的 3 个偏移量。因此它意味着 2 个 VAO(每个网格一个)。是真的吗?(我想确保用这种方法不可能用独特的 VAO 绘制这两个网格 - 提前感谢这一点)。
PS:要渲染几何图形,我使用函数 glDrawRangeElements。所以在这个例子中,这个函数在一个循环中被调用了 2 次,当然元素范围不同:
for the plane mesh :
glDrawRangeElements(GL_TRIANGLES, 0, 0, 6, GL_UNSIGNED_INT, OFFSET_BUFFER(0));
And for the cube mesh :
glDrawRangeElements(GL_TRIANGLES, 0, 6, 36, GL_UNSIGNED_INT, OFFSET_BUFFER(0));
现在我提出另一种方法,这次使用独特的 VAO 来渲染所有几何图形。这是新模式:
[P(plane)][P(cube)]|[T(plane)][T(cube)]|[N(plane)][N(cube)]
|0 |48 |360 |392 |600 |648
正如您所看到的这种解决方案,我只需要 3 个偏移量(0、360 和 600)来渲染所有几何图形(当然,IBO 将与前一种方法不同,并将相应地构建)。所以在这里我需要一个独特的 VAO !但这次我需要了解所有场景(所有顶点)才能构建我的 VBO(填充一次),这与之前的情况不同,我可以多次填充我的 VBO 网格。你同意我吗 ?
另一个问题:如果我想移除例如立方体,我无法移除 VBO。那么这里的方法是什么?我是否需要将我的“Mesh”类的布尔值“m_IsVisible”设置为 false?(我的网格将不再可见,但顶点不会是空闲的!)或者我需要释放顶点吗?我怎样才能做到这一点 ?
你觉得我的提议怎么样?哪一个是最好的 ?
在我的示例中是否可以使用独特的 VAO?