在程序流程的某个时刻,我会生成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数量。
答案 0 :(得分:3)
您在这里遇到了一些精神障碍。您似乎认为“每一个消息:{一个顶点属性==一个VBO}” ,但这并不是它应该工作的方式。您应该做的是使用一个大型VBO,并将其用作一个内存池,从中分配大块,每个大块都保存一些数据。
因此,您不仅将单个网格的所有顶点属性都放入了一个普通的VBO中,而且还将多个网格都放入了一个VBO中。
同样,您似乎在每个渲染迭代中都创建和删除VBO和VAO。为什么?网格在每一帧之间是否会发生巨大变化?如果是这样,那一定是癫痫症引起的注意。烘焙到几何数据中的网格变形不需要重新创建缓冲区,只需使用glBufferSubData
覆盖数据即可。