OpenGLの自己参照レンダーバッファー
質問
異なる環境間で一貫して動作しないOpenGLコードがあります ハードウェア。次のコードがあります:
- レンダーバッファーを作成し、テクスチャをカラーバッファー(テクスチャA)にバインドします
- このレンダーバッファーをアクティブに設定し、ビューポートなどを調整します
- ピクセルシェーダーをアクティブにします(この例ではガウスぼかし)。
- クワッドをテクスチャAの上にフルスクリーンで描画します。
- レンダーバッファのバインド解除など
私の開発マシンでは、これは正常に動作し、意図したとおりです。 テクスチャを「所定の位置に」ぼかす効果、ただし他のハードウェア これは機能していないようです。
2つの可能性に落とし込みました。
A)レンダーバッファをそれ自体にレンダーすることは機能しないはずです。 私の開発マシンでしか機能しません。何らかの原因で発生します。
または
B)このアプローチは機能するはずですが、他の何かが間違っています。
アイデアはありますか?正直なところ、この問題の詳細を見つけるのに苦労しました。
解決
A)は正解です。読み取り中の同じバッファへのレンダリングは未定義です。動作するかもしれませんが、動作しないかもしれません-これがまさに起こっていることです。
OpenGLの場合、 framebuffer_object extension はセクション「4.4.3バインドされたテクスチャオブジェクトの画像もフレームバッファにアタッチされている場合のレンダリング」何が起こるかを伝えます(基本的には未定義)。 Direct3D9では、そのセットアップを使用すると、デバッグランタイムから大きなエラーが発生します(ただし、ハードウェア/ドライバーによっては動作する場合があります)。 D3D10では、ランタイムは常に宛先として使用されるターゲットのバインドを解除します。
これが未定義なのはなぜですか? GPUが非常に高速である理由の1つは、GPUが多くの仮定を行えることです。たとえば、ピクセルをフェッチするユニットは、ピクセルを書き込むユニットと通信する必要がないと想定できます。そのため、サーフェスを読み取ることができます。Nサイクル後に読み取りが完了し、Nサイクル後にピクセルシェーダーが実行を終了し、GPUの出力マージバッファーに入れて、最後にメモリに書き込まれます。さらに、GPUは「未定義」でラスタライズします。順序(1つのGPUが行でラスタライズし、別のキャッシュフレンドリーな順序で、別のGPUがまったく別の順序でラスタライズする可能性があります)ので、サーフェスのどの部分が最初に書き込まれるかわかりません。
あなたがすべきことは、いくつかのバッファを作成することです。ぼかし/グローの場合、通常は2つで十分です。最初にレンダリングし、次に&を読み取ります。秒に書き込みながらそれをぼかします。必要に応じて、ピンポンでこのプロセスを繰り返します。
他のヒント
特殊なケースでは、バックバッファで十分な場合があります。単にglClearを実行しないでください。以前に描いたものはまだそこにあります。もちろん、注意点は、バックバッファから実際に読み取ることができないということです。ただし、フェードインやフェードアウトなどの効果の場合、これは機能します。