OpenGLのレンダーバッファからテクスチャを取得しますか?


13

FBOにレンダーバッファー(DepthStencil)があり、そこからテクスチャを取得する必要があります。FBOにDepthComponentテクスチャとDepthStencilレンダーバッファーの両方を含めることはできないようです。そのため、後で使用するためにレンダーバッファーをDepthComponentテクスチャに変換する方法が必要です。

何週間もレンダーバッファーから深度コンポーネントを取得するために多くのテクニックを試してきましたが、いつも迷惑メールが出ます。最後に欲しいのは、レンダーバッファを使用していなかった場合にFBOから取得するのと同じテクスチャです。この一見単純な操作をカバーする包括的な指示またはコードを誰でも投稿できますか?

編集:

コードの抽出バージョンへのリンク http://dl.dropbox.com/u/9279501/fbo.cs

被写界深度エフェクトのスクリーニー+ FBO-深度なし(!) http://i.stack.imgur.com/Hj9Oe.jpg

被写界深度エフェクトなしのスクリーニー+ FBO-正常に機能する深度 http://i.stack.imgur.com/boOm1.jpg

回答:


2

代わりに、レンダーバッファベースのものからテクスチャベースのものなど、あるFBOから別のFBOにブリットすることができます。私はこのようにします:

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderBufferSurface->m_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_textureSurface->m_fbo);
glBlitFramebufferEXT(0, 0, m_renderBufferSurface->m_width, m_renderBufferSurface->m_height, 0, 0, m_textureSurface->m_width, m_textureSurface->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

(バッファを深める場合は、GL_COLOR_BUFFER_BITの代わりにGL_DEPTH_BUFFER_BITを使用できます)

テクスチャベースのレンダーバッファにブリットした後、通常どおりテクスチャを使用できます。ユニフォームまたは好きなものとしてシェーダーに渡します。


1

いいえ、それは不可能です。せいぜいデータをCPUにglReadPixelsし、そのテクスチャを作成できますが、それは面倒で遅くなります。レンダーバッファーはそのためのものではなく、その機能はテクスチャによってのみ提供されます。


それを考えると、代替手段は何ですか?描画バッファの深度をどのように維持し、深度コンポーネントをテクスチャとして取得することができますか?
-Rushyo

@Rushyo:別の方法として、ステンシルバッファーを削除し(可能な場合!)、深度レンダーバッファーを深度テクスチャにすることもできます。なぜステンシルを使用しているのですか?
Calvin1602

基本的に、深度テクスチャを取得するたびに、深度テストは失敗します。深度アタッチメントをFBOに添付すると、FBOは他の場所に深度情報を書き込みません。したがって、カラーアタッチメントを取得しようとしても、深度テストは行われません(通常は深度アタッチメントがない場合です) )。前述の「面倒で遅い」方法など、考えられるすべての組み合わせを試しました。私が何をするにしても、あるテクスチャーでシーンの「典型的な」レンダリングと別のテクスチャーの深さの両方を取得することはできません。
-Rushyo

@ Calvin1602レンダーバッファーを使用していたときに、ステンシルアタッチメントなしで深度アタッチメントを使用すると、望ましくない結果が生じることがわかりました。
-Rushyo

@Rushyo私はあなたがテクスチャを正しく設定していないに違いない、コードを投稿することで私たちが助けてくれるだろう:)
マティアスバルデネグロ

1

OpenGL 3.2では、求めていることが可能です。拡散色をカラーテクスチャに、法線を別のカラーテクスチャに、深度を深度テクスチャに吐き出します。レンダーバッファは不要です。実際、レンダーバッファーはサンプルから取得できないため、単に問題になります。GPU glReadPixels(...)メモリ内のすべてを維持するのではなく、RBOからデータをCPU上のテクスチャに使用するか、何らかの方法でコピーする必要があります。そう...

本当にしたい場合は、ファーストパスシェーダーでコードを記述して、深度などをFBOの別のカラーテクスチャアタッチメントに手動で出力できます。これは、ポストパスシェーダーで使用するためのものです。以下のためのOpenGLの 内部の深さのテストで使用する、あなたは、さらにあなたのFBOのGL_DEPTH_ATTACHMENTとしてRBOやテクスチャのセットのいずれかが必要になります。ただし、両方に役立つ単一のテクスチャを設定できます。これはより効率的で使いやすいです。

私の深度テクスチャ設定コードは次のようになります(Java、ByteBufferを無視します...整数ハンドル/ポインタを参照するために「id」を使用していることに注意してください。

        gBufferDepthTexture = new Texture();
        gBufferDepthTexture.id = glGenTextures();
        gBufferDepthTexture.unit = 2;
        gBufferDepthTexture.width = Display.getWidth();
        gBufferDepthTexture.height = Display.getHeight();
        gBufferDepthTexture.bytes = ByteBuffer.allocateDirect(Display.getWidth()*Display.getHeight() * 4);
        glActiveTexture(gBufferDepthTexture.unit + GL_TEXTURE0); //eg. 0 + 33984 = GL_TEXTURE0, while 31 + 33984 = GL_TEXTURE31.
        glBindTexture(GL_TEXTURE_2D, gBufferDepthTexture.id);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gBufferDepthTexture.width, gBufferDepthTexture.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, gBufferDepthTexture.bytes);
        //...GL_UNSIGNED_INT or GL_UNSIGNED_BYTE may work better for you, instead... YMMV.

        //glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

以降:

        glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo.id);
        //your existing glFramebufferTexture2D(...) calls here
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gBufferDepthTexture.id, 0);

これでgBufferDepthTexture、2番目、3番目のパスフラグメントシェーダーにユニフォームとして(または何が必要か)渡すことができます。ステンシルバッファでもまったく同じことができると安全に想定できると思います。


0

GL_DEPTH_STENCIL形式を使用して、(RenderBufferの代わりに)テクスチャを作成できるはずです。シェーダープログラムでそのようなテクスチャから深度を使用するための正確なプロセスはわかりません(FBOを使用しているため、使用していると仮定します)が、OpenGL仕様では、どのカラーチャネルがどの値を取得するかを指定する必要があります(私の推測では、R、G、およびBはすべて深度に設定され、Aはステンシルに設定されます)。

私は最近OpenGL 3.2をターゲットにしているので、テクスチャフォーマットが機能することを確認する必要があるかもしれません。どのバージョンが異なる機能を導入しているのか思い出せません。


問題は、GL_DEPTH_STENCILコンポーネントをテクスチャでキャプチャすることではなく、FBOですべての深度情報が失われるという事実です。FBOは、シーンを描画バッファーにレンダリングするために使用できなくなります。したがって、この問題を回避するためにRenderbufferを使用していました。私は今のところ選択肢がないと思いますが、深さをつかむために2つのパスを作成し、情報を個別に描画します=(
回避策を

@Rushyo私はこの古代の質問への答えを投稿しました:)あなたはおそらくこの年前に解決したかもしれませんが、見てみたいと思うかもしれません。
エンジニア

@NickWiggill欲しい!何かをファッジして、私の人生を続けました。このプロトタイプで使用したアセットを再作成するまで、実際に答えをテストすることはできません。ある時点でそれを回避するかもしれません
...-Rushyo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.