OpenGL Vertex缓冲区对象,我可以访问顶点数据以用于其他用途(例如碰撞检测)吗? [英] OpenGL Vertex buffer object, can I access the vertex data for other uses such as collision detection?

查看:79
本文介绍了OpenGL Vertex缓冲区对象,我可以访问顶点数据以用于其他用途(例如碰撞检测)吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Superbible 5版随附的GLTools类.我正在查找GLTriangleBatch类,它具有以下代码:

I'm currently using the GLTools classes that come along with the Superbible 5th edition. I'm looking in the GLTriangleBatch class and it has the following code:

// 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;

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

From what I understand the code passes the arrays that the pointers pVerts, pNorms, pTexCoords, pIndexes and stores them in a Vertex array object, which essentially is an array of vertex buffer objects. These are stored in memory on the GPU. The original pointers are then deleted.

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

I'm interested in accessing the vertex positions, which were held in the array pVert pointed to.

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

Now my question revolves around collision detection. I want to be able to access an array of all of the vertices of my GLTriangleBatch. Can I obtain them through the vertexBufferObject at a later time using some sort of getter method? Would it be best to just keep the pVerts pointer around and use a getter method for that instead? I'm thinking in terms of performance, as I hope to implement a GJK collision detection algorithm in the future...

推荐答案

缓冲区对象用作顶点数据的源时,出于渲染的目的而存在.从性能的角度来看,通常不建议向后(读回数据).

Buffer objects, when used as sources for vertex data, exist for the benefit of rendering. Going backwards (reading the data back) is generally not advisable from a performance point of view.

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

The hint you give glBufferData has three access patterns: DRAW, READ, and COPY; these tell OpenGL how you intend to be getting/retrieving data from the buffer object directly. The hints do not govern how OpenGL should be reading/writing from/to it. These are just hints; the API doesn't enforce any particular behavior, but violating them may lead to poor performance.

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

DRAW means that you will put data into the buffer, but you will not read from it. READ means that you will read data from the buffer, but you will not write to it (typically for transform feedback or pixel buffers). And COPY means that you will neither read from nor write to the buffer directly.

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

Notice that there is no hint for "read and write." There is just "write", "read", and "neither." Consider that a hint as to how good of an idea it is to write data to a buffer directly and then start reading from that buffer.

同样,这些提示是针对用户直接获取或检索数据的. glBufferDataglBufferSubData和各种映射功能都可以进行写操作,而glGetBufferSubData和映射功能都可以进行读操作.

Again, the hints are for the user directly getting or retrieving data. glBufferData, glBufferSubData, and the various mapping functions all do writes, while glGetBufferSubData and mapping functions all do reads.

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

In any case no, you should not do this. Keep a copy of the position data around in client memory if you need to use it on the client.

此外,某些驱动程序完全忽略了使用提示.相反,它们根据您实际使用缓冲区的方式(而不是您打算使用的方式)来决定将缓冲区对象放置在何处.对于您来说,这将变得更糟,因为如果您开始从该缓冲区读取数据,驱动程序可能会将缓冲区的数据移到内存中的速度并不快.它可能会移出GPU,甚至移至客户端内存空间.

Also, some drivers ignore the usage hints entirely. They instead decide where to place the buffer object based on how you actually use it, rather than how you say you intend to use it. This will be worse for you, because if you start reading from that buffer, the driver may move the buffer's data to memory that is not as fast. It may be moved out of the GPU and even into the client memory space.

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

However, if you insist on doing this, there are two ways to read data from a buffer object. glGetBufferSubData is the inverse of glBufferSubData. And you can always map the buffer for reading instead of writing.

这篇关于OpenGL Vertex缓冲区对象,我可以访问顶点数据以用于其他用途(例如碰撞检测)吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆