16

texture1 を texture2 にコピーしたい。最も愚かな方法は、tex1 データを GPU から CPU にコピーしてから、CPU データを GPU にコピーすることです。愚かなコードは次のとおりです。

float *data = new float[width*height*4];
glBindTexture(GL_TEXTURE_2D, tex1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, data);
glBindTexture(GL_TEXTURE_2D, tex2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data);

私が知っているように、CPU を介さずに GPU tex から GPU tex へのデータ コピーをサポートする方法が存在する必要があります。tex1クワッドをtex2にレンダリングするFBOの使用を検討しています。でも、なんとなくまだナイーブだと思います。では、これを実装する最も効率的な方法は何ですか?

4

1 に答える 1

21

OpenGL 4.3 をサポートしている場合は、glCopyImageSubDataまさにこの目的のための簡単な方法があります。

glCopyImageSubData(tex1, GL_TEXTURE_2D, 0, 0, 0, 0,
                   tex2, GL_TEXTURE_2D, 0, 0, 0, 0,
                   width, height, 1);

もちろん、これには目的のテクスチャが適切なサイズと形式の画像で既に割り当てられている必要があります (単純な を使用するか、とにかく GL 4 を使用している場合はglTexImage2D(..., nullptr)さらに良いかもしれません)。glTexStorage2D


それがない場合でも、FBO を使用して 1 つのテクスチャを別のテクスチャにレンダリングすることが最善の方法である可能性があります。結局、ソース テクスチャをレンダリングする必要さえありません。両方のテクスチャを FBO にアタッチし、glBlitFramebuffer(OpenGL 3 以降のコア、または 2.x の GL_EXT_framebuffer_blit 拡張機能を使用して、FBO が最初に配置されているほぼすべての場所で)を使用して、1 つのカラー アタッチメントを別のカラー アタッチメントにブリットすることができます。

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                       GL_TEXTURE_2D, tex1, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 
                       GL_TEXTURE_2D, tex2, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, 
                  GL_COLOR_BUFFER_BIT, GL_NEAREST);

もちろん、それを複数回行う場合は、この FBO を有効にしておくことをお勧めします。同様に、これには、目的のテクスチャ イメージが適切なサイズと形式を事前に持っている必要があります。または、ソース テクスチャのみを FBO にアタッチし、古き良きものを宛先テクスチャに適用するというMichaelの提案を使用することもできます。glCopyTex(Sub)Image2Dどちらが優れているかを評価する必要があります (存在する場合)。


そして、それさえ持っていない場合でも、1 つのテクスチャを読み取り、そのデータを別のテクスチャに書き込むというアプローチを使用できます。ただし、CPU メモリを一時バッファーとして使用する代わりに、ピクセル バッファー オブジェクト (PBO) (OpenGL 2.1 以降のコア) を使用します。まだ追加のコピーがありますが、少なくともそれは GPU-GPU コピーになります (またはそうなる可能性があります)。

于 2013-04-19T08:55:07.183 に答える