0

OpenGL のデバッグとリバースエンジニアリングのために OpenGL の GL_POINT をエミュレートしようとしています。ポインター、インデックスバッファーポインター、およびストライドを指定して、頂点バッファーを反復しようとしています。

だから私がしたこと:

  • 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 ポインター。
  • ストライド。
  • インデックス ポインター。
4

1 に答える 1

3

次の場合、各三角形の頂点を取得するにはどうすればよいですか。

  • VBO ポインター。
  • ストライド。
  • インデックス ポインター。

できません。

バッファ オブジェクトにはポインタがありません。指定されたポインタからバッファオブジェクトストレージにデータglBufferDataglBufferSubData コピーします。"Pointer" という単語で終わらないすべての OpenGL 関数と同様に、これらの関数の実行後、アプリケーションは自由にそれらを使って好きなことを行うことができます。OpenGLはこれらのポインタを保持しません。したがって、あなたもすべきではありません。

バッファオブジェクトに格納されたメモリを追跡したい場合は、自分でメモリを割り当て、自分でコピーする必要があります。glBufferDataorが呼び出されたらglBufferSubData、そのポインターから内部ストレージにデータをコピーする必要があります。ユーザーが書き込み用にバッファーをマップした場合、バッファーがマップ解除されるまで待機してから、 を使用してバッファーからデータをコピーする必要がありますglGetBufferSubData

速くはなりません。

さらに、頂点データをレンダリングする場合は、一歩先を行く必要があります。タイプが必要です。ユーザーが使用しているだけであると仮定することGL_FLOATは、かなり貧弱な仮定です (コードをアプリケーション固有にしたい場合を除きます)。

いずれにせよ、あなたは非常に行儀の悪いアプリケーションを扱っています。一部の属性 (など) にバッファー オブジェクトをglColorPointer使用し、他の属性 ( ) には使用していないようですglVertexPointer。それはあなたの仕事を難しくするでしょう。

基本的に、OpenGL が行うことを行う必要があります。属性ごとに、タイプ、ストライド、正規化、および指定された「ポインター」を記録する必要があります。ただし、バッファーが現在バインドされているかどうかも確認する必要がありGL_ARRAY_BUFFERます (つまり、一度に 1 つのバッファーしかバインドできないというふりをやめる必要があります。それぞれの異なるターゲットにバインドされているものを追跡する必要があります)。

「ポインター」関数のいずれかを呼び出すときにバッファーがバインドされているGL_ARRAY_BUFFER場合、それは指定された「ポインター」がポインターではないことを意味します。これは、バッファ オブジェクトの先頭からのバイト オフセットです。そのため、「ポインタ」とGL_ARRAY_BUFFER、関数が呼び出されたときにバインドされたバッファ オブジェクトを格納する必要があります。そこにバッファがバインドされていない場合、ポインタは実際には実際のメモリ ポインタであり、アプリケーションがそれをレンダリングしようとする限り、このポインタを保持しておく必要があります。

レンダリング時に、属性ごとに、属性のポインターを使用するか、バッファー オブジェクト + オフセットを使用して、バッファー オブジェクト データの開始位置を計算します。これを使用して、バッファー オブジェクト データのコピーにアクセスします。いずれにせよ、ポインタに解決されます。次に、型と正規化を使用してデータの読み取り方法を決定し、ストライドを使用して 1 つの頂点から次の頂点に移動します。

于 2013-05-04T07:36:10.517 に答える