1

ディファード シェーディング フレームワークでは、さまざまなフレーム バッファ オブジェクトを使用して、さまざまなレンダー パスを実行しています。最初のパスでは、シーン全体の をテクスチャに書き込みます。DEPTH_STENCIL_ATTACHMENTこれを と呼びましょうDepthStencilTexture。さまざまなレンダー パスから格納されている深度情報にアクセスするにはDepthStencilTexture、さまざまなフレーム バッファー オブジェクトを使用します。2 つの方法を知っています
。1) をシェーダーにバインドDepthStencilTextureし、フラグメント シェーダーでアクセスします。これ

uniform vec2 WinSize; //windows dimensions
vec2 uv=gl_FragCoord.st/WinSize;
float depth=texture(DepthStencilTexture ,uv).r;
if(gl_FragCoord.z>depth) discard;

私も設定glDisable(GL_DEPTH_TEST)し、glDepthMask(GL_FALSE)

2) をDepthStencilTextureフレームバッファ オブジェクトにバインドしDEPTH_STENCIL_ATTACHMENT、設定glEnable(GL_DEPTH_TEST)しますglDepthMask(GL_FALSE)(編集: この場合、ループ フィードバックを避けるために、シェーダにバインドしませんDepthStencilTexture。Nicol Bolas の回答を参照してください。使用するフラグメント シェーダーgl_FragCorrd.z)

ステンシル テストとステンシル バッファーへの書き込みが必要なライト ボリュームの描画などの特定の状況では、ソリューション 2) を使用します。ステンシルを完全に無視し、深さを に保存する必要がある他の状況では、DepthStencilTextureオプション 1) はより「自然な」オプション 2) よりも利点がありますか?

たとえば、私は(ばかげていると思いますが)それについて疑問を持っています。フラグメント シェーダーでは、深さから WorldPosition を計算することがあります。1)の場合はこうなる

uniform mat4 invPV; //inverse PV matrix 
vec2 uv=gl_FragCoord.st/WinSize;
vec4 WorldPosition=invPV*vec4(uv, texture(DepthStencilTexture ,uv).r ,1.0f );
WorldPosition=WorldPosition/WorldPosition.w;

ケース 2) の場合は次のようになります (編集: これは間違っています。gl_FragCoord.z は現在のフラグメントの深度であり、テクスチャに格納されている実際の深度ではありません)

uniform mat4 invPV; //inverse PV matrix 
vec2 uv=gl_FragCoord.st/WinSize;
vec4 WorldPosition=invPV*vec4(uv, gl_FragCoord.z, 1.0f );
WorldPosition=WorldPosition/WorldPosition.w;

gl_FragCoord.zケース 2) はケース 1) と同じであると想定しています。texture(DepthStencilTexture ,uv).rつまり、DepthStencilTexture. 本当ですか?gl_FragCoord.z現在バインドされている からDEPTH_STENCIL_ATTACHMENTも読み取られますglDisable(GL_DEPTH_TEST)および? glDepthMask(GL_FALSE)

4

1 に答える 1

3

OpenGL 仕様に厳密に従うと、オプション 2は許可されません。そのテクスチャからも読んでいる場合はそうではありません。

はい、深度書き込みを防ぐために書き込みマスクを使用していることに気づきました。それは問題ではありません; OpenGL の仕様は非常に明確です。OpenGL 4.4 の 9.3.1 に従って、次の場合にフィードバック ループが確立されます。

  • テクスチャ オブジェクト T からのイメージが、アタッチ ポイント A で現在バインドされている描画フレーム バッファ オブジェクトにアタッチされます。

  • テクスチャ オブジェクト T は現在テクスチャ ユニット U にバインドされており、

  • 現在のプログラム可能な頂点および/またはフラグメントの処理状態により、テクスチャ ユニット U にバインドされたテクスチャ オブジェクト T からのサンプリングが可能になります (以下を参照)。

それはあなたのコードの場合です。したがって、技術的には未定義の動作があります。

これが定義されていない理由の 1 つは、ライト マスクを変更するだけで、フレーム バッファやテクスチャ キャッシュのクリアなどを行う必要がなくなるためです。

そうは言っても、 NV_texture_barrierを使用すれば、オプション 2 を回避できます。名前にもかかわらず、AMD ハードウェアで非常に広く利用できます。ここで行う主なことは、すべての深度書き込みを行った後にバリアを発行して、後続のすべての読み取りが確実に機能するようにすることです。バリアは、必要なすべてのキャッシュのクリアなどを行います。

それ以外の場合は、オプション 1 が唯一の選択肢です。深さテストを手動で行うことです。

ケース 2) の gl_FragCoord.z は、ケース 1) の texture(DepthStencilTexture ,uv).r と同じ、つまり、DepthStencilTexture に格納されている深度と同じになると想定しています。本当ですか?

どちらも真実ではありません。gl_FragCoord処理中のフラグメントの座標です。これは、ラスタライズされるプリミティブのデータに基づいて、ラスタライザによって生成されるフラグメントです。フレームバッファの内容とは関係ありません。

于 2013-08-16T07:48:32.120 に答える