迭代顶点缓冲区

时间:2013-05-04 06:50:52

标签: c++ opengl hook

我正在尝试模拟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指针。
  • The Stride。
  • 指数指针。

1 个答案:

答案 0 :(得分:3)

  

如果我有以下内容,如何获取每个三角形的顶点:

     
      
  • VBO指针。
  •   
  • The Stride。
  •   
  • 指数指针。
  •   

你不能。

缓冲区对象没有指针glBufferDataglBufferSubData 数据从给定指针复制到缓冲区对象存储中。与所有不以“指针”一词结尾的OpenGL函数一样,after the execution of these functions, the application is free to do whatever it wants with them。 OpenGL 不会保留这些指针。因此,你也不应该。

如果要跟踪存储在缓冲区对象中的内存,则必须自己分配内存并自行复制。当glBufferDataglBufferSubData调用通过时,您将不得不将该指针中的数据复制到内部存储中。如果用户映射缓冲区以进行写入,则必须等待缓冲区取消映射,然后使用glGetBufferSubData从缓冲区复制数据。

这不会很快。

此外,如果您打算渲染顶点数据,则需要更多步幅。你需要的类型;假设用户仅使用GL_FLOAT是一个相当差的假设(除非您希望您的代码是特定于应用程序的。)

无论如何,您正在处理一个非常不良的应用程序。它似乎是为某些属性(例如glColorPointer)使用缓冲区对象而不是将其用于其他属性(glVertexPointer)。这将使你的工作更加艰难。

你基本上需要做OpenGL的工作。对于每个属性,您需要记录类型,步幅,规范化和给定的“指针”。但是需要检查缓冲区当前是否绑定到GL_ARRAY_BUFFER(这意味着您需要停止假装只能绑定一个缓冲区时间。你需要跟踪每个不同目标的束缚。)

如果在调用其中一个“指针”函数时缓冲区绑定到GL_ARRAY_BUFFER,则表示给定的“指针”不是指针;它是相对于缓冲区对象开头的字节偏移量。因此,您需要在调用函数时将“指针”存储到绑定到GL_ARRAY_BUFFER的缓冲区对象。如果没有绑定缓冲区,那么指针实际上是一个真正的内存指针,只要它尝试使用它就可以保持活动状态。

在渲染时,对于每个属性,您可以使用属性的指针,或使用缓冲区对象+偏移量来计算缓冲区对象数据的起始位置。您可以使用它来访问缓冲区对象数据的副本。无论哪种方式,您都可以解析为指针。然后使用类型和规范化来决定如何读取数据,并使用步幅从一个顶点到下一个顶点。