1

これは非常に漠然とした問題ですので、このプロジェクトに関する何かを自由に明確にしてください。

私は非常に大規模なアプリケーションに取り組んでいますが、最近、テクスチャリングに関して非常に厄介なバグが発生しました。読み込んでいるテクスチャの一部が読み込まれています - コードをステップ実行して実行しましたが、これらのテクスチャのすべての OpenGL レンダリングは奇妙なピンク/ホワイト ストライプ テクスチャです。

この状況のデバッグを開始するために何を提案しますか?

  • このプロジェクトはマルチスレッド化されていますが、ミューテックスは、すべての OpenGL 呼び出しが他のものによって中断されないようにします。
  • いくつかのテクスチャがロードされていますが、いくつかはロードされていません。それらはすべてまったく同じ方法でロードされます。
  • すべてのテクスチャが存在することを確認しました
  • 「ピンク/ホワイト」のテクスチャは確実にメモリに読み込まれます。他のテクスチャを OpenGL に読み込むとすぐに表示されます。

私は困惑しており、他に何が間違っているのかわかりません。テクスチャを強制的に使用可能にする glTexImage の後に呼び出すことができる OpenGL コマンドはありますか?

編集:コマンドの失敗ではなく、主にタイミングの問題です。他のテクスチャがロードされるまで、ピンク/白のテクスチャがしばらく表示されます。まるでテクスチャがキューに入れられているかのようで、キューは一時停止します。

次の編集: glIntercept ログが正しく機能するようになりました。これが出力されたものです (プログラム全体がクラッシュする前)。

http://freetexthost.com/1kdkksabdg

次の編集: テクスチャが OpenGL メモリに読み込まれていることは事実ですが、何らかの理由でプログラム自体でレンダリングされていません。

4

7 に答える 7

3

テクスチャの色が正しくない場合は、RGB の順序が間違っている可能性があります。glTexImage2D で、画像形式に適した列挙型を使用していることを確認してください。コンポーネントの数が正しいこと、および format 引数で RGB ピクセルの順序が正しいことを確認してください。

おそらくテクスチャが間違って表示されることとは関係ありませんが、OpenGL はマルチスレッドの描画をサポートしていないため、コンテキストを所有するスレッドとは異なるスレッドで描画作業を行っていないことを確認してください。

編集: 参照レンダラーを持っているので、イメージ ピクセルが期待どおりに読み込まれていることを確認できますか? ピクセルをロードしてすぐにファイルに保存する小さなルーチンを作成することを強くお勧めします。これにより、適切なテクスチャ結果が確実に得られるようになります。

于 2009-12-16T17:42:17.483 に答える
1

あなたが言う時:

プロジェクトはマルチスレッドですが、ミューテックスにより、すべてのOpenGL呼び出しが他の何かによって中断されないようになります。

これは私には十分に強力な保護のようには思えません。OpenGLは大量の内部状態を持つステートマシンであることを忘れないでください。OpenGLの状態が、呼び出しを行っているときに期待する状態であること、および呼び出しの特定のシーケンスが他のスレッドからの呼び出しによって中断されないことを確認する必要があります。

私はOpenGLスレッドセーフの専門家ではありませんが、これはあなたの問題がどこにあるのか私には思えます。

于 2009-12-16T20:24:22.793 に答える
1

テクスチャ座標を確認してください。正しく設定されていない場合、プリミティブ全体にマップされたテクセルが 1 つまたは 2 つだけ表示されます。OpenGL はステート マシンであることを思い出してください。間違ったタイミングでテクスチャ座標の状態を変更していないか確認してください。コードの後半でテクスチャ座標を設定している可能性があり、これらの要素の再描画に戻ると、テクスチャをコードにマッピングするために状態が許容されます。

テクスチャをロードする OpenGL 呼び出しが時間内に実行されない単なるタイミングの問題であり、スレッド コードが正しい場合は、テクスチャをロードした後に glFlush() への呼び出しを追加してみてください。glFlush() は、保留中のすべての OpenGL コマンドを実行します。

于 2009-12-16T20:43:45.767 に答える
0

美しい白いテクスチャが表示されるため、スレッドにテクスチャをロードして他の別のスレッドで使用することはできません。これを可能にするには、OpenGL関数を使用する前に、異なるスレッド間でOpenGLコンテキストをロードする必要があります。

于 2010-01-08T11:07:40.347 に答える
0

GLIntercept を使用してコードをチェックする場合は、必ず有効にしてください。 ThreadChecking = True; gliConfig.ini ファイルで。

ログを表示すると、かなりの数の OpenGL 呼び出しがメイン コンテキストの外でメインになっているようです。

于 2010-02-01T13:57:45.743 に答える
0

白いテクスチャを取得せずに別のスレッドにテクスチャをロードすることは可能です。問題は、OpenGL ウィンドウを初期化すると、OpenGL コンテキストがこのスレッドに「バインド」されることです。テクスチャをロードしている間はメイン スレッドでコンテキストを非アクティブ化する必要があり、それらのロードを開始する前に、このスレッドでコンテキストをアクティブ化する必要があります。

このクラスを使用できます:

Context.h:

#ifndef CONTEXT_H
#define CONTEXT_H

#include <GL/glut.h>

class Context
{
public:
    static Context* getInstance();

    void bind();
    void unbind();
private:
    Context();
    Context(const Context&);
    ~Context();

    static Context *instance;

    HGLRC hglrc;
    HDC hdc;

    class Guard
    {
    public:
        ~Guard()
        {
            if (Context::instance != 0) {
                delete Context::instance;
            }
        }
    };
    friend class Guard;
};

#endif

Context.cpp:

#include "Context.h"

Context* Context::getInstance()
{
    static Guard guard;
    if(Context::instance == 0) {
        Context::instance = new Context();
    }
    return Context::instance;
}

void Context::bind()
{
    wglMakeCurrent(this->hdc, this->hglrc);
}

void Context::unbind()
{
    wglMakeCurrent(NULL, NULL);
}

Context::Context()
{
    this->hglrc = wglGetCurrentContext();
    this->hdc = wglGetCurrentDC();
}

Context::~Context()
{
}

Context *Context::instance = 0;

そして、それはあなたがしなければならないことです:

int state = 0;

void main()
{
    // Create the window.
    glutCreateWindow(TITLE);

    // Set your loop function.
    glutDisplayFunc(&loop);

    // Initialize the singleton for the 1st time.
    Context::getInstance()->bind();

    glutMainLoop();
}

void loop()
{
    if (state == 0) {
        Context::getInstance()->unbind();
        startThread(&run);
    } else if (state == 1) {
        // Rebind the context to the main thread (just once).
        Context::getInstance()->bind();
        state = 2;
    } else if (state == 2) {
        // Draw your textures, lines, etc.
    } else {
        // Draw something (but no textures).
    }
}

void run()
{
    Context::getInstance()->bind();

    // Load textures...

    Context::getInstance()->unbind();
    state = 1;
}
于 2010-11-26T15:56:33.303 に答える
0

テクスチャとして使用する画像のサイズと圧縮を確認してください。OpenGL のテクスチャ サイズは 2 のべき乗でなければならないと思います ...

于 2009-12-16T17:42:15.487 に答える