深度图重建世界空间是从深度信息计算出对应像素的世界位置坐标,对于实现如阴影映射、环境遮挡和后处理效果(例如景深和运动模糊)等高级图形效果至关重要。

VP矩阵变换法

在该方法中,需要先构建出NDC坐标,再通过VP矩阵(视图矩阵和透视矩阵)将NDC坐标变换到世界空间。

深度图重建世界空间:VP矩阵变换法
在3D渲染中,若任意两个点在最终渲染图像里对应着同一个像素点,即两点的屏幕空间坐标完全一致,那么无论采用的是透视投影还是正交投影方式,该两点在NDC空间下的X、Y坐标值必然相同。在进行深度图重建世界空间时,采样深度图所使用的坐标恰好是归一化屏幕空间坐标(屏幕UV),那么我们便可据此计算出采样到的深度值对应点的X、Y坐标。

  1. 首先将屏幕UV转到NDC空间(映射到[-1, 1]),该值也正是目标点在NDC空间下的X、Y坐标:$$ \text{NDC}_{XY} = 2 \text{UV} - 1 $$
  2. 构建NDC空间下的Z值,并补全NDC的W分量:$$ \begin{align*} \text{NDC}_{Z} &= \begin{cases} \text{Depth}, & \text{DirectX} \\ 2 \cdot \text{Depth} + 1, & \text{OpenGL} \end{cases} \\ \text{NDC}_{W} &= 1.0 \end{align*} $$
  3. NDC空间世界空间(视图矩阵 & 透视矩阵 & 齐次除法):$$ \text{Position}_{XYZ} = \frac{(M_{\text{View}}^{-1}\cdot M_{\text{Project}}^{-1}\cdot\text{NDC})_{XYZ}}{(M_{\text{View}}^{-1}\cdot M_{\text{Project}}^{-1}\cdot\text{NDC})_{W}} $$ Unity示例如下
HLSL
float2 UV = IN.positionHCS.xy / _ScaledScreenParams.xy; // 计算屏幕UV
real depth = SampleSceneDepth(UV); // 采样深度图
#if !UNITY_REVERSED_Z // 调整 Z 以匹配 OpenGL 的 NDC ([-1, 1])
	depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, depth);
#endif
// 重建世界空间位置
float3 worldPos = ComputeWorldSpacePosition(UV, depth, UNITY_MATRIX_I_VP);
点击展开查看更多

大部分逻辑已经被封装成函数ComputeWorldSpacePosition

相似三角形法

深度图重建世界空间:相似三角形法

版权声明

作者: Chaim

链接: https://chaim.eu.org/posts/%E6%B7%B1%E5%BA%A6%E5%9B%BE%E9%87%8D%E5%BB%BA%E4%B8%96%E7%95%8C%E7%A9%BA%E9%97%B4/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键