2009-07-20 68 views
4

我目前從場着色器的一個後處理深度的深度紋理使用以下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值作爲距離,但這似乎沒有工作。這裏的正確方法是什麼?

此外,當使用斜截頭截頭將近平面移到選定的截取平面上時,近平面距離現在可能對每個像素有所不同?如果是這樣,那麼這是否意味着任何計算距深度紋理的距離的着色器都需要知道這種情況,而不是假設常量接近平面距離?

謝謝!

+2

我的確有相反的問題,所以你的問題陳述最終成爲我的解決方案。謝謝, – imallett 2013-05-31 20:38:56

回答

2

事實證明,我忘記了否定最終的Z值以在近平面前獲得正距離(OpenGL相機向下看-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); 

如果你想要一個世界空間中的位置,而不是(像超強使用),那麼可以通過將視圖和投影找到矩陣,然後使用該矩陣的逆矩陣,而不是僅使用投影矩陣逆矩陣。

因爲只需要viewPosition的Z和W分量,因此上述用於計算viewPosition的GLSL可以稍微簡化。兩個點的產品就足夠了,而不是一個完整的矩陣乘法,而且也沒有必要全部逆向投影矩陣送入僅需要上下兩排的着色器:

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

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

的這個性能是有點差比使用近距離和遠距離,大概是由於額外的點積,我減少了約5%。近距離和遠距離數學運算也可以通過將(zNear * zFar)(zFar - zNear)作爲常數進行優化,但我沒有看到通過這樣做可以實現的任何可衡量的改進。

有趣的是,當你把上面與使用斜截錐削波,我不能得到任何合理的出它的投影矩陣,但我得到合理的輸出使用具有相同的投影遠近距離方程時矩陣,儘管似乎有一些深度值的扭曲(儘管這可能僅僅是由於斜截頭體削波固有的深度精度的損失)。如果任何人都可以在數學上闡明究竟到底發生了什麼,我會很感激,但也許這應該是一個不同的問題。

1

我在閃電着色器中使用下面的代碼,以計算閃電方向。 Wold位置也是通過將屏幕位置乘以投影矩陣的倒數來計算的。

不幸的是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是正確的!

+0

感謝您確認我在正確的軌道上:-),我已經在下面發佈了我的解決方案和GLSL代碼。 – 2009-07-21 00:57:53