我正在使用OpenGL进行实验,以找出最频繁/最有效地将新数据添加到glBufferData的最佳/最有效方法。
为此,我编写了一个小型2D绘制程序,并在移动鼠标时简单地添加点。
整个功能如下所示:
void addPoint(double x, double y)
{
glBindBuffer(GL_ARRAY_BUFFER, pointVertBuffObj);
if (arrayOfPointCapacity < numOfPoints + 1) {
U32 size = (arrayOfPointCapacity + 8) * sizeof(Point2);
Point2 *tmp = (Point2*)realloc(arrayOfPoints, size);
arrayOfPoints = tmp;
arrayOfPointCapacity += 8;
}
arrayOfPoints[numOfPoints].x = x,
arrayOfPoints[numOfPoints].y = y;
U32 offset = numOfPoints * sizeof(Point2);
glBufferData(GL_ARRAY_BUFFER, numOfPoints * sizeof(Point2), arrayOfPoints, GL_DYNAMIC_DRAW);
numOfPoints++;
}
每次添加点时都必须用新数据重置glBufferData似乎绝对疯狂。我考虑过使用
glBufferData
分配大量的点,并使用glBufferSubData
设置这些点。当缓冲区的大小变得太小时,我再次调用glBufferData
来增加缓冲区的大小,并将现有的点复制回去。理想情况下,我希望避免将点数据存储在计算机内存中,并将所有内容保留在GPU内存中。但是,当我要调整缓冲区的大小时,我必须将数据从缓冲区复制回CPU,然后再调整缓冲区的大小,最后将数据从CPU复制回缓冲区。所有这一切,似乎也没有效率。
任何的想法?最佳做法是什么?
最佳答案
不错的主意。实际上,这是推荐的方法。但是不要使块太小。
那不是OpenGL的工作方式。缓冲区对象的内容可以根据需要在CPU和GPU内存之间自由交换。
正确。您要避免在OpenGL和主机程序之间进行复制。这就是OpenGL-3.1和更高版本中的函数glCopyBufferSubData在缓冲区之间复制数据的原因。当需要调整缓冲区大小时,您还可以创建一个新的缓冲区对象,并将其从旧对象复制到新的对象^ 1。
[1]:也许您还可以通过利用名称孤立来在同一缓冲区对象名称中调整副本的大小;但我首先必须阅读规范(如果实际上已定义),然后交叉指责所有实现都正确。