DirectX正交相机下基于深度纹理获取视图空间位置的问题咨询
正交相机深度纹理转视图空间位置问题修复
现有代码的问题
- 逻辑适配错误:当前代码是透视相机的转换逻辑,正交投影的投影空间w分量恒为1,不需要做齐次除法,且深度映射规则和透视完全不同
- 深度值未映射:采样得到的深度纹理值默认是[0,1]的归一化存储值,需要先映射到对应图形API的投影空间Z范围(D3D类API是[0,1],OpenGL类API是[-1,1])才能参与矩阵运算
- 矩阵乘法顺序错误:常用图形API的投影矩阵为列主序存储,向量为列向量,正确乘法顺序是
mul(矩阵, 向量),原有代码的行向量乘法顺序会得到错误结果
修正后实现代码
首先确认你使用的图形API的深度范围,以D3D风格(投影Z范围[0,1])为例,修正后的代码如下:
// 正交相机专属转换函数 float3 ortho_position_in_view_space(float2 uv) { // 采样深度纹理得到[0,1]范围的深度值 float z = depth_tex.SampleLevel(depth_sampler, uv, 0.0f).x; // UV转NDC坐标 float x = uv.x * 2 - 1; float y = (1 - uv.y) * 2 - 1; // 构造NDC坐标,若为OpenGL风格需要把z映射到[-1,1]:z = z * 2 - 1 float4 vNdcPos = float4(x, y, z, 1.0f); // 列主序矩阵下的正确乘法顺序:矩阵 * 列向量 float4 vPositionVS = mul(inv_proj, vNdcPos); // 正交投影下w恒为1,不需要做齐次除法,直接返回xyz即可 return vPositionVS.xyz; } // 调用代码保持不变 float3 position_from = ortho_position_in_view_space(tex_coord.xy); output.color = float4(position_from, 1.0); return output;
额外校验点
如果修正后还是不符合预期,可以检查以下参数:
- 确认
inv_proj确实是当前正交相机的逆投影矩阵,不要错传透视相机的逆投影矩阵 - 如果深度纹理开启了Reverse-Z,需要先把采样到的z值翻转:
z = 1 - z再做后续运算
内容的提问来源于stack exchange,提问作者Andre Ahmed
相关产品推荐
相关产品推荐

