投影矩阵引发垂直偏移问题排查请求
投影矩阵的核心错误分析与修正
你的透视投影矩阵存在元素行列位置完全错位和Z轴映射逻辑错误两个核心问题,直接导致了垂直偏移和Z轴异常。
具体错误点
1. 矩阵元素的行列位置完全混乱
行主序的透视投影矩阵中,每行对应NDC一个分量的计算逻辑,但你把X/Y/Z分量的缩放、偏移值全部放错了行列:
- X分量(第一行):仅正确设置了X轴缩放
m11,但把X轴偏移量-(right+left)/(right-left)错误放到了第二行第一列(m21),且符号错误(正确应为(right+left)/(right-left))。 - Y分量(第二行):把Y轴缩放
2*near/(top-bottom)错误放到了第三行第三列(m33),Y轴偏移量-(top+bottom)/(top-bottom)错误放到了第二行第三列(m23)。 - Z分量(第三行):把Z轴缩放
(far+near)/(far-near)错误放到了第二行第二列(m22),Z轴偏移量-2*far*near/(far-near)错误放到了第四行第二列(m42),且Z缩放符号错误(需要将[near, far]的Z值映射到NDC的[-1,1],正确符号应为负)。 - 齐次分量(第四行):错误设置
m43=1,正确应为-1,用于透视除法时的Z分量处理。
2. Z轴映射逻辑完全错误
从补充测试结果看,近平面(Z=1)顶点投影后Z值为2,远平面(Z=100)顶点投影后Z值为1.01,完全没有映射到NDC的[-1,1]范围,反而成了递增的正数,这是因为Z分量的计算位置和符号全部错误导致的。
修正后的投影矩阵代码
impl<T> Matrix4x4<T> { pub fn perspective_near_plane(left: T, top: T, right: T, bottom: T, near: T, far: T) -> Self where T: Real { // 行主序:每行对应NDC的X、Y、Z、齐次分量计算 let m11 = (T::one() + T::one()) * near / (right - left); let m12 = T::zero(); let m13 = (right + left) / (right - left); // X轴偏移,正确位置 let m14 = T::zero(); let m21 = T::zero(); let m22 = (T::one() + T::one()) * near / (top - bottom); // Y轴缩放,正确位置 let m23 = (top + bottom) / (top - bottom); // Y轴偏移,正确位置 let m24 = T::zero(); let m31 = T::zero(); let m32 = T::zero(); let m33 = -(far + near) / (far - near); // Z轴缩放,修正符号与位置 let m34 = -(T::one() + T::one()) * far * near / (far - near); // Z轴偏移,正确位置 let m41 = T::zero(); let m42 = T::zero(); let m43 = -T::one(); // 齐次分量Z项,正确值 let m44 = T::zero(); Self::new( m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 ) } pub fn perspective_horizontal_fov(horizontal_fov: T, aspect_ratio: T, near: T, far: T) -> Self where T: Real { let right = (horizontal_fov / (T::one() + T::one())).tan() * near; let left = -right; let top = right / aspect_ratio; let bottom = -top; Self::perspective_near_plane(left, top, right, bottom, near, far) } }
修正说明
- 将X/Y/Z分量的缩放、偏移值放到了对应NDC分量的行中,符合行主序矩阵的计算逻辑。
- 修正了Z分量的符号,确保将[near, far]范围内的Z值正确映射到NDC的[-1,1]区间,匹配Vulkan的坐标系要求。
- 调整了齐次行的元素,保证透视除法后各分量符合NDC范围。
用修正后的矩阵测试时,近平面顶点[-1,1,1,1]会被正确投影为NDC的[-1,1,1,1],远平面顶点[-100,100,100,1]会被投影为[-1,1,-1,1],解决垂直偏移和Z轴异常问题。
内容的提问来源于stack exchange,提问作者Rick de Water
相关产品推荐
相关产品推荐

