在我的程序流程中的某个时刻,我生成0到300个网格之间的任何位置,每个网格都是这样的:
public Mesh(float[] vertices, byte[] indices, float[] textureCoordinates)
{
vao = glGenVertexArrays();
glBindVertexArray(vao);
vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(vertices), GL_STATIC_DRAW);
glVertexAttribPointer(ShaderProgram.VERTEX_ATTRIB, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(ShaderProgram.VERTEX_ATTRIB);
tbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(textureCoordinates), GL_STATIC_DRAW);
glVertexAttribPointer(ShaderProgram.TCOORD_ATTRIB, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(ShaderProgram.TCOORD_ATTRIB);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferUtils.createByteBuffer(indices), GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
当用户按下按钮时,需要再次删除这些网格,因此我对每个网格对象运行一个清理方法:
public void cleanup()
{
glDeleteBuffers(vbo);
glDeleteBuffers(tbo);
glDeleteBuffers(ibo);
glDeleteVertexArrays(vao);
}
问题是我试图以60 fps运行并删除70个这些网格对象需要大约30 ms(并删除其中的110个需要75 ms)。这会在性能上产生明显的打嗝,因为一帧最多需要16毫秒。
这不是处理VBO和VAO的正确方法吗?我读了一个不同的问题(glDeleteBuffers slower than glBufferData)
glGenBuffers和glDeleteBuffers分别只在初始化和清理时运行。在运行时调用它们很糟糕。
但我不知道如何在不调用上述功能的情况下摆脱这些VBO和VAO。
我曾想过将所有要删除的网格添加到队列中,并且每帧只删除其中几个,慢慢清空队列,但这不是正确的解决方案。我想到的另一个(可能的)解决方案是使用实例化渲染,但据我所知,当我每帧进行1000次绘制调用时,非实例渲染也应该正常工作。我的程序在任何给定时间都不会有超过1000个Mesh对象,我甚至不确定这会解决我的问题。
更新:除了下面的答案指向我正确的方向,我还发现我实际上并没有删除〜0-300 VBO,而是多了48倍!难怪表演被杀死了。因此,如果其他人遇到同样的问题,请彻底检查代码执行的glDeleteBuffers的数量。
你在那里遇到了一些心理障碍。你似乎认为“per mesn:{one vertex attribute == one VBO}”,但这并不是它应该如何工作的。你应该做的是使用一个单独的大型VBO并用作一个内存池,你可以从中分配块,每个块都包含一些数据。
因此,您不仅将单个网格的所有顶点属性放入一个公共VBO中,还将几个网格放入一个VBO中。
此外,您似乎在每次渲染迭代中创建和删除VBO和VAO。为什么?网格在每一帧之间都会发生戏剧性的变化吗?如果是这样,那一定是癫痫诱发观察;烘焙到几何数据中的网格变形不需要重新创建缓冲区,只需使用glBufferSubData
覆盖数据。