迭代顶点缓冲区
Posted
技术标签:
【中文标题】迭代顶点缓冲区【英文标题】:Iterate Vertex Buffer 【发布时间】:2013-05-04 06:50:52 【问题描述】:我正在尝试模拟 OpenGL 的 GL_POINT 进行调试和逆向工程 OpenGL。我正在尝试给定它的指针、索引缓冲区指针和步幅。
所以我做了什么:
我连接了一个使用 OpenGL 的应用程序。 我使用 gDebugger 监控调用 (AMD 为调试创建的应用程序)要渲染单个模型,调用是:
glPushMatrix()
glViewport(4, 165, 512, 334)
glMultMatrixf(1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
26880, -741, 26368, 1)
glGenBuffersARB(1, 0x0A2B79D4)
glBindBufferARB(GL_ARRAY_BUFFER, 15)
glBufferDataARB(GL_ARRAY_BUFFER, 17460, 0x0C85DE1C, GL_STATIC_DRAW)
glGenBuffersARB(1, 0x0A2B79D4)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 16)
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, 8946, 0x0C85DE1C, GL_STATIC_DRAW)
glBindBufferARB(GL_ARRAY_BUFFER, 0)
glVertexPointer(3, GL_FLOAT, 12, 0x31CB24C9)
glEnableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY)
glBindBufferARB(GL_ARRAY_BUFFER, 15)
glColorPointer(4, GL_UNSIGNED_BYTE, 12, 0x00000000)
glEnableClientState(GL_COLOR_ARRAY)
glTexCoordPointer(2, GL_FLOAT, 12, 0x00000004)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glDrawElements(GL_TRIANGLES, 4473, GL_UNSIGNED_SHORT, 0x00000000)
glPopMatrix()
我挂钩了每个调用并将所有参数存储到一个类和一些变量中。
typedef struct //A struct to hold information about every buffer the application uses.
GLint ID;
GLsizei Size;
GLboolean Reserved;
GLboolean Bound;
GLenum Type, Usage;
uint32_t CheckSum;
const GLvoid* BufferPointer;
BufferObject;
BufferObject CurrentBuffer; //Keep track of the currently bound buffer.
std::vector<BufferObject> ListOfBuffers; //A list of all buffers used in the application.
//Detours the OpenGL function so that it calls this one first before calling the original one. (OpenGL call interception.)
void HookglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
if ((size == 3) && (pointer != nullptr) && type == GL_FLOAT) //A model is rendering..
ModelRendering = true;
CurrentModel.Stride = stride;
CurrentModel.VertexPointer = pointer; //Store the pointer.
ListOfModels.push_back(CurrentModel); //Store the model.
(*original_glVertexPointer) (size, type, stride, pointer); //Call the original function.
//Hook the drawing function and get each vertex being rendered.
void HookglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
Model* ModelPtr = &ListOfModels.back();
if (ModelPtr != nullptr)
for (int I = 0; I < count / 3; ++I) //So for every triangle, I want to get the vertex of it and store it in my Vertices vector..
//This needs to somehow use the stride to get the right vertex.
//Perhaps CurrentBuffer.BufferPointer instead of ModelPtr->VertexPointer.
int X = *reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(ModelPtr->VertexPointer) * I);
int Y = *reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(ModelPtr->VertexPointer) * I + 1);
int Z = *reinterpret_cast<const GLfloat*>(reinterpret_cast<const char*>(ModelPtr->VertexPointer) * I + 2);
ModelPtr->Vertices.push_back(Vector3D(X, Y, Z));
(*original_glDrawElements) (mode, count, type, indices); //call the original function.
如果有的话,如何获取每个三角形的顶点:
VBO 指针。 大步前进。 索引指针。【问题讨论】:
我看不出这与GL_POINTS
有什么关系。
GL_POINT 在您将它与 glDrawElements 一起使用时会执行此操作。如果我设置 GL_FILL,它会填充整个模型。如果我设置 GL_POINTS,它只会显示每个顶点。我想得到每个顶点,就像函数在使用 GL_POINTS 时所做的那样。我想我正试图弄清楚 gl_drawelements 是如何工作并模拟它的。
我仍然对这与GL_POINTS
渲染有什么关系感到困惑。他们正在使用GL_TRIANGLES
。您是在谈论 多边形模式,还是在谈论传递给绘图函数的原始类型?
【参考方案1】:
如果有的话,如何获取每个三角形的顶点:
VBO 指针。 大步前进。 索引指针。
你不能。
缓冲区对象没有指针。 glBufferData
和glBufferSubData
复制 数据从给定的指针到缓冲区对象存储。与所有不以“指针”一词结尾的 OpenGL 函数一样,after the execution of these functions, the application is free to do whatever it wants with them。 OpenGL 不保留这些指针。因此,你也不应该。
如果您想跟踪存储在缓冲区对象中的内存,您将不得不自己分配内存并自己进行复制。当glBufferData
或glBufferSubData
调用通过时,您将不得不将该指针中的数据复制到您的内部存储中。如果用户映射一个缓冲区进行写入,您将不得不等待缓冲区被取消映射,然后使用glGetBufferSubData
从缓冲区复制数据。
它不会很快。
此外,如果您打算渲染顶点数据,您需要的不仅仅是步幅。你需要类型;假设用户只使用GL_FLOAT
是一个非常糟糕的假设(除非您希望您的代码是特定于应用程序的)。
无论如何,您都在处理一个行为不端的应用程序。它似乎将缓冲区对象用于 some 属性(例如glColorPointer
),而不将它们用于其他属性(glVertexPointer
)。这会让你的工作更难。
您基本上需要做 OpenGL 所做的事情。对于每个属性,您需要记录类型、步幅、规范化和给定的“指针”。但是您还需要检查缓冲区当前是否绑定到GL_ARRAY_BUFFER
(这意味着您需要停止假装一次只能绑定一个缓冲区。您需要跟踪绑定到每个不同目标的内容)。
如果在调用“指针”函数之一时缓冲区绑定到GL_ARRAY_BUFFER
,那么这意味着给定的“指针”不是指针;它是相对于缓冲区对象开头的字节偏移量。因此,您需要存储“指针”和在调用函数时绑定到GL_ARRAY_BUFFER
的缓冲区对象。如果那里没有绑定缓冲区,则该指针实际上是一个真正的内存指针,应用程序必须保持活动状态,只要它尝试使用它进行渲染。
在渲染时,对于每个属性,您要么使用属性的指针,要么使用缓冲区对象 + 偏移量来计算缓冲区对象数据的开始位置。您可以使用它来访问缓冲区对象数据的副本。无论哪种方式,您都解析为指针。然后,您使用类型和规范化来决定如何读取数据,并使用步幅从一个顶点到下一个顶点。
【讨论】:
啊,我明白了。我已经完成了第一部分。我从传递给 glBufferData 和 SubData 的指针中复制了数据,并将其存储在我的 vector以上是关于迭代顶点缓冲区的主要内容,如果未能解决你的问题,请参考以下文章