質問

私は現在、次のGLSLコードを使用してフィールドシェーダの後処理深さの深さのテクスチャから読んます:

vec4 depthSample = texture2D(sDepthTexture, tcScreen);
float depth = depthSample.x * 255.0 / 256.0 +
              depthSample.y * 255.0 / 65536.0 +
              depthSample.z * 255.0 / 16777216.0;

そして遠近平面距離に基づいて、ビュー空間距離に奥行き値を変換

float zDistance = (zNear * zFar) / (zFar - depth * (zFar - zNear));

これは、すべてのしかし、私は別のzNearzFar値を必要とせずに、現在の射影行列に基づいて上記の計算を行う方法を知って興味を持って、かなりうまく動作するようです。

私の初期の試みは、その後、距離として得(vec4(tcscreen.x, tcScreen.y, depth, 1.0) * 2.0 - 1.0)値をとる、wによって介して結果を分割する、射影行列の逆行列によってzを乗算関与し、これは動作するようには思えませんでした。ここでは、正しいアプローチは何ですか?

また、選択されたクリッピング平面に近く平面をシフトするためにクリッピング斜め円錐台を使用する場合は今、すべてのピクセルのための潜在的に異なる周辺面間隔は?だから、これは深度テクスチャからの距離を計算する任意のシェーダが一定に近い平面の距離を想定し、この例意識する必要がないという意味ではない場合はどうなりますか?

ありがとうございます。

役に立ちましたか?

解決

これは、私が(OpenGLのカメラは-Zを見下ろす)に近い平面の前に正の距離を取得するために、最終的なZ値を否定するために忘れていたことが判明します。将来の参照のために周辺の平面の前方の距離を取得するためのGLSLコードは

float depth = /* sampled from depth texture as in the original question */ ;

vec4 screenPos = vec4(tcScreen.x, tcScreen.y, depth, 1.0) * 2.0 - 1.0;
vec4 viewPosition = projectionMatrixInverse * screenPos;

float z = -(viewPosition.z / viewPosition.w);

(のSuperProを使用していたように)あなたが代わりにワールド空間位置を望んでいたならば、それはビューおよび投影行列を組み合わせ、その行列の逆行列を使用しただけではなく、射影行列の逆を使用することによって見つけることができます。

唯一ZとviewPositionのW成分が必要とされるので、

viewPositionを計算するための上記のGLSLは幾分簡略化することができます。二つの内積は、完全な行列の乗算の代わりに十分であり、かつ底面のみ2行が必要なようシェーダに完全な逆射影行列を供給する必要はありません。

vec2 viewPositionZW = vec2(
    dot(projectionMatrixInverseRow2, screenPos),
    dot(projectionMatrixInverseRow3, screenPos)
);

float z = -(viewPositionZW.x / viewPositionZW.y);

この性能は、おそらく余分なドット積の、近くと遠くの距離を使用するよりも少し悪いです、私は〜5%の削減を得ました。近くと遠くの数学も(zNear * zFar)を供給することにより、最適化され、定数として(zFar - zNear)が、私はこれを行うことにより、任意の測定可能な改善を見ていないことができます。

興味深いことに、あなたは私がそれのうち賢明な何かを得ることができないクリッピング斜めの錐台を使用している投影行列で上記を組み合わせたが、私は同じ投影行列と近くと遠くの方程式を使用した場合、合理的な出力を得る行うとき、(これは単に斜め錐台のクリッピングに固有の深さ精度の損失の原因である可能性がありますが)深度値の若干の歪みと思われるものとはいえ。誰もが正確に数学的にここで何が起こっているかについていくつかの光を当てることができれば、私は多分、それは別の問題であるべきにもかかわらず、それをいただければと思います。

他のヒント

Iは雷方向を計算するために、雷シェーダに次のコードを使用します。 ウォールド位置は、投影行列の逆行列で画面位置を乗じて算出される。

残念ながらHLSLます:

float depth = tex2D(DepthMapSampler, PSIn.TexCoord).r;

float4 screenPos;
screenPos.x = PSIn.TexCoord.x*2.0f-1.0f;
screenPos.y = -(PSIn.TexCoord.y*2.0f-1.0f);
screenPos.z = depth;
screenPos.w = 1.0f; 

float4 worldPos = mul(screenPos, xViewProjectionInv);
worldPos /= worldPos.w;

正常に動作しますので、私はWorldpositionが正しいと仮定!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top