根据深度信息重建世界坐标

摘自
https://forum.unity.com/threads/reconstructing-world-pos-from-depth-imprecision.228936/

unity的实现代码
//main problem encountered is camera.projectionMatrix = ??????? worked but further from camera became more inaccurate
//had to use GL.GetGPUProjectionMatrix( ) seems to stay pretty exact now

//in script somewhere:
Matrix4x4 viewMat = camera.worldToCameraMatrix;
Matrix4x4 projMat = GL.GetGPUProjectionMatrix( camera.projectionMatrix, false );
Matrix4x4 viewProjMat = (projMat * viewMat);          
Shader.SetGlobalMatrix("_ViewProjInv", viewProjMat.inverse);

//in fragment shader:
uniform float4x4 _ViewProjInv;
float4 GetWorldPositionFromDepth( float2 uv_depth )
{    
        float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv_depth);
        float4 H = float4(uv_depth.x*2.0-1.0, (uv_depth.y)*2.0-1.0, depth, 1.0);
        float4 D = mul(_ViewProjInv,H);
        return D/D.w;
}

先获取当前位置的深度值,区间为[0,1]。然后把screen space的坐标转换到标准设备空间(NDC),DirectX在NDC中x,y的区间是[0,1]。OpenGL是[-1,1],所以对OpenGL,最后乘上逆矩阵,之后做一次标准化。

方法很简洁,就是把NDC的坐标再通过逆矩阵转换到世界坐标。但其正确性需要证明一下,因为这里有非线性变换,就是最后标准化,除以w的步骤。

简要证明

假设 VP V , P 分别为camera和projection转换矩阵,最后得到的NDC的坐标为 (x,y,z) ( x , y , z ) 。因为Projection分成了两个部分,线性部分和非线性部分,线性部分就是做矩阵变换,非线性部分就是除以最后的w维(其实 w=z w = z ′ z z ′ 是当前点对应于世界空间中与camera在z轴的距离,看下面的投影矩阵形式就知道了),得到欧氏空间坐标,也就是 (x,y,z) ( x , y , z )

因为看不到Unity的源码,所以这里写出一般的正交投影矩阵, r r 为aspect ratio,α为vertial field of view, f f 为视椎体远平面,n为视椎体近平面。

P=1rtan(α/2)00001tan(α/2)0000ffn100nffn0 P = [ 1 r tan ⁡ ( α / 2 ) 0 0 0 0 1 tan ⁡ ( α / 2 ) 0 0 0 0 f f − n − n f f − n 0 0 1 0 ]

unity使用的矩阵左乘,即 Pvin=vout P ∗ v i n = v o u t ,所以正交投影矩阵形式应该跟上面类似。一个欧氏空间的顶点 (x,y,z) ( x , y , z ) 对应无数个齐次空间点 (xw,yw,zw,w) ( x w , y w , z w , w ) ,w是非零的。

对于上述问题,假设 w=z w = z ′ z z ′ 是当前点对应于世界空间中与camera在z轴的距离,区间为 [near,far] [ n e a r , f a r ] ,把NDC下的点 (x,y,z) ( x , y , z ) 写成齐次坐标 (xw,yw,zw,w)×1w ( x w , y w , z w , w ) × 1 w ,乘以逆变换矩阵将会得到实际在world space中对应的点 (x0,y0,z0,1)×1w ( x 0 , y 0 , z 0 , 1 ) × 1 w ,因为最后要做一次标准化,所以 1w 1 w 最后会消去,最终得到对应的欧氏坐标。

补充

进一步了解投影变换可以参考 https://blog.csdn.net/dengyibing/article/details/80784939

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值