【发布时间】:2019-09-16 15:39:08
【问题描述】:
在我的程序流程的某个时刻,我生成了 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 毫秒(删除其中 110 个需要 75 毫秒)。这会在性能上造成明显的中断,因为一帧最多需要 16 毫秒。
这不是处理 VBO 和 VAO 的正确方法吗?我在另一个问题 (glDeleteBuffers slower than glBufferData) 中读到
glGenBuffers 和 glDeleteBuffers 分别设计为仅在初始化和清理时运行。在运行时调用它们是不好的。
但我不确定如何在不调用上述函数的情况下摆脱这些 VBO 和 VAO。
我曾想过将所有要删除的网格添加到队列中,并且每帧只删除几个,慢慢清空队列,但这感觉不是正确的解决方案。我想到的另一个(可能的)解决方案是使用实例化渲染,但据我所知,当我每帧进行不到 1000 次绘制调用时,非实例化渲染也应该可以正常工作。我的程序在任何时候都不会有超过 1000 个 Mesh 对象,我什至不确定这是否能解决我的问题。
更新:除了从下面的答案指出我完全正确的方向外,我还发现我实际上并没有删除 ~0-300 VBO,而是 48 个因子!难怪表演被扼杀了。因此,如果其他人遇到过同样的问题,请彻底检查您的代码正在执行的 glDeleteBuffers 的数量。
【问题讨论】: