观察透视投影矩阵:
对于x和y,矩阵变换只是一个缩放系数,那么逆变换就是缩放系数的倒数,所以
设Xndc Yndc为NDC空间中的XY坐标,Xview Yview Zview为view space中的坐标,则
所以
所以已知XY的NDC坐标和view space z,就能求出view space position,写成代码就是:
float M = tan(fov*0.5f)*aspect; float N = tan(fov*0.5f); float3 GetViewSpacePos(float2 NDCPos, float ViewSpaceZ) { float3 VPos = float3(NDCPos.xy, 1.f) * float3(M, N, 1.f); return VPos * ViewSpaceZ; }
如果depth buffer中已经存储了线性的view space depth,那么只需采样出depth,然后计算出position即可;如果depth buffer中储存的是非线性的perspective z(NDC z),那么需要先把perspective z逆变换为view space z,再使用上述方法计算position。
把perspective z变换为view space z:
对于view space z,乘以投影矩阵然后除以w得到ndc z:
由上式可得:
其中
写成代码就是:
float P0 = 1/zn; float Q = zf/(zf - zn); float P1 = 1/(zn*Q); float PerpectiveZToLinearZ(float Zndc) { return 1.f / (P0 - P1 * Zndc); }
所以对于perspective z,构建view-space postion的代码如下:
float3 GetViewSpacePos_NDCZ(float2 NDCPos, float Zndc) { float ViewSpaceZ = PerspectiveZToLinearZ(Zndc); return GetViewSpacePos(NDCPos, ViewSpaceZ);}
时间: 2024-10-24 14:39:58