2009-07-20 66 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