華文網

從depth buffer中構建view-space position

觀察透視投影矩陣:

對於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);