【发布时间】:2014-10-06 20:19:32
【问题描述】:
我有一个 udp 客户端,用于从服务器读取点,该服务器在 4 毫秒内生成点,每个数据包有近 3000 个点。我阅读了这些点并将它们映射到具有 100 万个坐标元素的矩阵。 (我从带有固定键的流式点创建一个哈希表。我的意思是你可以想到一个 1000 个键,每个键最多有 1000 个点,但它是不同的。完成此表后,我从服务器获得的任何新值,映射到我的键一种排序方式,我的意思是,我首先更新了较小键中的点,然后......:D
我真的很惭愧我不能这样做,我的 1990x1080 像素的 LCD 比我快! :-((
我想将它插入 VBO,然后在 30 毫秒内升级每个关键部分。
所以我想创建 1000 个用于绘图的 vbos 和 1000 个用于缓冲的 vbos,并且在每 33 ms 迭代之后,我将 50 个绘图 vbos 更改为缓冲的 vbos。每个 vbo 最多有 0f 1000 个点和颜色,一个 VBO 中的点数从 10 变为 1000;
我的问题从这里开始,我不明白 VBO 的工作原理以及实现此问题的最佳解决方案? :D
1- 我的第一个问题:我为什么要创建 VAO 以及它如何与新一代缓冲区相关联? 它看起来与下一个 glGenBuffer() 相关联,对吗?但是在我阅读的任何示例中,我都没有看到该指针的任何使用(仅用于绘制)?这是我创建从某处下载的 vbo 的代码
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
// First see if the vertex array buffer has been created...
if(uiVertexArray == 0) { // Nope, we need to create it
glGenBuffers(1, &uiVertexArray);
glBindBuffer(GL_ARRAY_BUFFER, uiVertexArray);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nNumVerts, NULL, GL_DYNAMIC_DRAW);
}
// Now see if it's already mapped, if not, map it
if(pVerts == NULL) {
glBindBuffer(GL_ARRAY_BUFFER, uiVertexArray);
pVerts = (M3DVector3f *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
}
// Ignore if we go past the end, keeps things from blowing up
if(nVertsBuilding >= nNumVerts)
return;
// Copy it in...
pVerts[nVertsBuilding][0] = x;
pVerts[nVertsBuilding][1] = y;
pVerts[nVertsBuilding][2] = z;
nVertsBuilding++;
对于颜色和纹理映射它的样子。哪个有更好的性能(GL_DYNAMIC_DRAW,GL_STREAM_DRAW)
2- 这是一个绘图功能?为什么使用最后一行?用于创建下一个 VBO 和 VAO?
// Set up the vertex array object
glBindVertexArray(vertexArrayObject);
glDrawArrays(primitiveType, 0, nNumVerts);
glBindVertexArray(0);
3- 下次我想用新点更改缓冲的 VBO 内容时,我必须为不同数量的点再次执行此操作,如果我这样做,我必须删除 VBO 的最后一个缓冲区吗?
// Vertex buffer objects
if(uiVertexArray != 0)
glDeleteBuffers(1, &uiVertexArray);
4- 我可以调整我的 VBO 的大小并且不使用重新创建缓冲区 VBO 吗?
5- 如何从缓冲区 VBO 中复制数据以绘制 VBO?
这是我在主绘制函数中绘制 VBO 的交换缓冲区,我在交换函数中从第一个开始重新创建 VBO 数据
for(int i=0; i<1000; i++)
if(must_show_buffer(i))
{
bufferVBO[i].draw();
drawedVBO[i].swap(bufferVBO[i]);
}
else drawedVBO[i].draw();
更新:
我将此函数用于交换数据: 如果(批处理-> cVerts != NULL) { CopyVertexData3f(batch->cVerts); CopyColorData4f(batch->cColors); } 结束();
void GLBatch::CopyColorData4f(M3DVector4f *vColors)
{
// First time, create the buffer object, allocate the space
if(uiColorArray == 0) {
glGenBuffers(1, &uiColorArray);
glBindBuffer(GL_ARRAY_BUFFER, uiColorArray);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * nNumVerts, vColors, GL_DYNAMIC_DRAW);
}
else { // Just bind to existing object
glBindBuffer(GL_ARRAY_BUFFER, uiColorArray);
// Copy the data in
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * 4 * nNumVerts, vColors);
pColors = NULL;
}
}
这种方法是正确的,但是 glBufferSubData 增加内存使用的速度如此之快,我得到一个内存溢出异常
还有这种方法
if(batch->uiVertexArray != NULL)
{
// First time, create the buffer object, allocate the space
if(uiVertexArray == 0) {
glGenBuffers(1, &uiVertexArray);
glBindBuffer(GL_ARRAY_BUFFER, uiVertexArray);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * nNumVerts, NULL, GL_DYNAMIC_DRAW);
}
// Fast copy data
glBindBuffer(GL_COPY_READ_BUFFER, batch->uiVertexArray);
glBindBuffer(GL_COPY_WRITE_BUFFER, uiVertexArray);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nNumVerts);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
//copy color data
if(uiColorArray == 0) {
glGenBuffers(1, &uiColorArray);
glBindBuffer(GL_ARRAY_BUFFER, uiColorArray);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * nNumVerts, NULL, GL_DYNAMIC_DRAW);
}
glBindBuffer(GL_COPY_READ_BUFFER, batch->uiColorArray);
glBindBuffer(GL_COPY_WRITE_BUFFER, uiColorArray);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, nNumVerts);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
}
没有内存分配问题但不清除之前的点
我在每个实现中错过了什么?
【问题讨论】:
-
一篇帖子中有很多问题恕我直言。
-
为什么不使用 wiki 和手册页? (opengl.org/sdk/docs/manopengl.org/wiki) 您的问题很基础,很容易在这些网站上找到答案。
-
可能适合您,但我不明白复制和调整大小部分?我想知道它的实施好还是最差