2

この質問は、自分が何を求めているのかほとんどわからなかったため、最初に尋ねられてから大きく変わりました。また、サイズ変更に関する1つの問題は、フレームバッファの作成と使用に関するより大きな問題を理解する能力を曇らせることでした。フレームバッファが必要な場合は、答えにジャンプしてください...歴史のために、元の質問はそのまま残しました。


初心者の質問。私が取り組んでいるGLプロジェクトがあり、独自の色を使用して選択戦略を開発しようとしています。ほとんどのディスカッション/チュートリアルは、バックバッファーに選択可能なエンティティを描画し、ユーザーがどこかをクリックしたときに選択を計算することを中心に展開されます。選択バッファーを永続化して、マウスの動きのヒットをすばやく計算できるようにし、表示またはオブジェクトのジオメトリが変更されない限り、選択バッファーを再描画しないようにします。

最良の選択は専用のフレームバッファオブジェクトであるように思われます。これが私の問題です。フレームバッファオブジェクトにまったく慣れていないことに加えて、私は興味があります。ウィンドウサイズのイベントでframbufferオブジェクトを削除して再作成するか、最大画面解像度で1回作成してから、そのほんの一部を使用する方がよいでしょうか。多くのサイズ変更イベントのストリームである可能性があるフレームバッファルーチンを1回だけ呼び出すようにイベントを適切に機能させていますが、GPUメモリの断片化やその他の問題が心配で、バッファを何度も再作成しています。

また、フレームバッファオブジェクト(テクスチャと深度)は、その一部だけを使用した場合でも一貫して動作します。

アイデア?私は完全にオフベースですか?

編集:フレームバッファオブジェクトを設定し、ウィンドウのサイズで作業しているので、ウィンドウに合わせてサイズを変更します。私の問題は古典的な「考えすぎ」だったと思います。GPUでのオブジェクトの削除/再作成は、可能な限り避ける必要があることは確かです。正しく処理されている限り、サイズ変更は比較的少なくなります。

私がうまくいったのは、ウィンドウのサイズ変更時にフラグを設定し、バッファをダーティとしてマークしてから、通常のマウスイベントを待ってからバッファのサイズを変更することです。通常のマウスは、ウィンドウをサイズにドラッグし終えた信号を入力または移動し、作業に戻る準備ができています。バッファは一度再作成されました。また、メインフレームバッファーは通常、パイプライン内のウィンドウサイズイベントごとにサイズ変更されるため、フレームバッファーのサイズ変更によってラップトップに穴が開いてしまうことはありません。

危機は回避されました、続けてください!

4

1 に答える 1

3

は質問の中で私が問題を考えすぎていると述べました。その主な理由は、問題が質問よりも大きかったためです。問題は、フレームバッファを制御する方法がわからなかっただけでなく、フレームバッファを作成する方法もわからなかったことです。非常に多くのオプションがあり、どのWebリソースも私がやろうとしていたことを具体的に扱っていないようだったので、私はそれに苦労しました。選択ルーチンを永続バッファを使用する一意の配色に移動する方法にも苦労している場合、またはフレームバッファとオフスクリーンレンダリングに関して完全に途方に暮れている場合は、読み進めてください。

OpenGLキャンバスをクラスとして定義しましたが、「選択バッファオブジェクト」が必要でした。これをクラスのプライベートメンバーに追加しました。

unsigned int sbo;
unsigned int sbo_pixels;
unsigned int sbo_depth;
bool sbo_dirty;
void setSelectionBuffer();

サイズ変更ハンドラーとOpenGL初期化の両方で、選択バッファーにダーティフラグを設定しました。

sbo_dirty = true;

マウスハンドラーの開始時に、ダーティビットをチェックし、必要にsetSelectionBuffer();応じてチェックします。

if(sbo_dirty) setSelectionBuffer();

これは、バッファの複数の削除/再作成に関する私の最初の懸念に対処します。ウィンドウのサイズを変更した後、マウスポインタがクライアント領域に再び入るまで、選択バッファのサイズは変更されません。今、私はバッファを理解する必要がありました...

void BFX_Canvas::setSelectionBuffer()
{
    if(sbo != 0) // delete current selection buffer if it exists
    {
        glDeleteFramebuffersEXT(1, &sbo);
        glDeleteRenderbuffersEXT(1, &sbo_depth);
        glDeleteRenderbuffersEXT(1, &sbo_pixels);
        sbo = 0;
    }

    // create depth renderbuffer
    glGenRenderbuffersEXT(1, &sbo_depth);
    // bind to new renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sbo_depth);
    // Set storage for depth component, with width and height of the canvas
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, canvas_width, canvas_height);
    // Set it up for framebuffer attachment
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, sbo_depth);
    // rebind to default renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

    // create pixel renderbuffer
    glGenRenderbuffersEXT(1, &sbo_pixels);
    // bind to new renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, sbo_pixels);
    // Create RGB storage space(you might want RGBA), with width and height of the canvas
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, canvas_width, canvas_height);
    // Set it up for framebuffer attachment
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, sbo_pixels);
    // rebind to default renderbuffer
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

    // create framebuffer object
    glGenFramebuffersEXT(1, &sbo);
    // Bind our new framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sbo);
    // Attach our pixel renderbuffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, sbo_pixels);
    // Attach our depth renderbuffer
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, sbo_depth);

    // Check that the wheels haven't come off
    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
    {
        // something went wrong
        // Output an error to the console
        cout << "Selection buffer creation failed" << endl;
        // restablish a coherent state and return
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        sbo_dirty = false;
        sbo = 0;
        return;
    }

    // rebind back to default framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    // cleanup and go home
    sbo_dirty = false;
    Refresh(); // force a screen draw
}

次に、レンダリング関数の最後にsboをテストし、準備ができていると思われる場合はsboに描画します。

if((sbo) && (!sbo_dirty)) // test that sbo exists and is ready
{
    // disable anything that's going to affect color such as...
    glDisable(GL_LIGHTING);
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_POINT_SMOOTH);
    glDisable(GL_POLYGON_SMOOTH);

    // bind to our selection buffer
    // it inherits current transforms/rotations
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, sbo);
    // clear it
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // draw selectables
    // for now i'm just drawing my object
    if (object) object->draw();

    // reenable that stuff from before
    glEnable(GL_POLYGON_SMOOTH);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_LIGHTING);

    // blit to default framebuffer just to see what's going on
    // delete this bit once selection is setup and working properly.
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, sbo);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
    glBlitFramebufferEXT(0, 0, canvas_width, canvas_height,
                         0, 0, canvas_width/3, canvas_height/3,
                         GL_COLOR_BUFFER_BIT, GL_LINEAR);

    // We're done here, bind back to default buffer.
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

それは私にこれを与えます...

スクリーンショット

この時点で、選択可能なアイテムを実際にバッファーに描画し、マウス移動イベントを使用してヒットをテストするためのすべてが整っていると思います。そして、私は画面上のサムネイルを持って、どれほど悪いことが爆発しているのかを示しています。

1週間前と同じように、これがあなたにとって大きな助けになったと思います。:)

于 2011-12-14T17:14:54.763 に答える