OpenGL Vertex缓冲区对象,我可以访问顶点数据以进行其他用途,例如碰撞检测吗?

kbi*_*irk 6 opengl collision-detection vertex-buffer vertex vertex-array

我目前正在使用与Superbible第5版一起提供的GLTools课程.我正在查看GLTriangleBatch类,它具有以下代码:

// Create the master vertex array object
glGenVertexArrays(1, &vertexArrayBufferObject);
glBindVertexArray(vertexArrayBufferObject);


// Create the buffer objects
glGenBuffers(4, bufferObjects);

#define VERTEX_DATA     0
#define NORMAL_DATA     1
#define TEXTURE_DATA    2
#define INDEX_DATA      3

// Copy data to video memory
// Vertex data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_VERTEX);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pVerts, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Normal data
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_NORMAL);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pNorms, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0);

// Texture coordinates
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[TEXTURE_DATA]);
glEnableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*2, pTexCoords, GL_STATIC_DRAW);
glVertexAttribPointer(GLT_ATTRIBUTE_TEXTURE0, 2, GL_FLOAT, GL_FALSE, 0, 0);

// Indexes
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*nNumIndexes, pIndexes, GL_STATIC_DRAW);

// Done
glBindVertexArray(0);

// Free older, larger arrays
delete [] pIndexes;
delete [] pVerts;
delete [] pNorms;
delete [] pTexCoords;

// Reasign pointers so they are marked as unused
pIndexes = NULL;
pVerts = NULL;
pNorms = NULL;
pTexCoords = NULL;
Run Code Online (Sandbox Code Playgroud)

根据我的理解,代码传递指针pVerts,pNorms,pTexCoords,pIndexes的数组并将它们存储在Vertex数组对象中,该对象本质上是顶点缓冲区对象的数组.它们存储在GPU的内存中.然后删除原始指针.

我有兴趣访问顶点位置,这些位置保存在pVert指向的数组中.

现在我的问题围绕碰撞检测.我希望能够访问我的GLTriangleBatch的所有顶点的数组.我可以通过vertexBufferObject以后使用某种getter方法获得它们吗?是否最好只保留pVerts指针并使用getter方法代替?我正在考虑性能,因为我希望将来能够实现GJK碰撞检测算法......

Nic*_*las 7

当缓冲对象用作顶点数据的源时,存在用于渲染的益处.从性能的角度来看,通常不建议倒退(读回数据).

你给glBufferData的提示有三种访问模式:DRAW,READ和COPY; 这些告诉OpenGL你打算如何直接从缓冲区对象获取/检索数据.提示不管理OpenGL应该如何读/写它.这些只是提示; API不会强制执行任何特定行为,但违反这些行为可能会导致性能下降.

DRAW表示您将数据放入缓冲区,但您不会从中读取数据.READ表示您将从缓冲区读取数据,但不会写入(通常用于变换反馈或像素缓冲区).而COPY意味着您既不会直接读取也不会直接写入缓冲区.

请注意,没有"读写"的提示.只有"写","读"和"都不".考虑一下这样一个提示:将数据直接写入缓冲区然后从该缓冲区开始读取是多么好.

同样,提示是用户直接获取或检索数据.glBufferData,glBufferSubData和各种映射函数都写入,而glGetBufferSubData映射函数都进行读取.

无论如何不,你不应该这样做.如果需要在客户端上使用,请在客户端内存中保留位置数据的副本.

此外,一些驱动程序完全忽略使用提示.而是根据您实际使用它的方式决定放置缓冲区对象的位置,而不是您打算如何使用缓冲区对象.这对你来说会更糟,因为如果你从那个缓冲区开始读取,驱动程序可能会将缓冲区的数据移动到不那么快的内存.它可能会移出GPU甚至移动到客户端内存空间.

但是,如果您坚持这样做,有两种方法可以从缓冲区对象中读取数据.glGetBufferSubData是反的glBufferSubData.并且您始终可以将缓冲区映射为读取而不是写入.