You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

投影矩阵引发垂直偏移问题排查请求

投影矩阵的核心错误分析与修正

你的透视投影矩阵存在元素行列位置完全错位和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)
    }
}

修正说明

  1. 将X/Y/Z分量的缩放、偏移值放到了对应NDC分量的行中,符合行主序矩阵的计算逻辑。
  2. 修正了Z分量的符号,确保将[near, far]范围内的Z值正确映射到NDC的[-1,1]区间,匹配Vulkan的坐标系要求。
  3. 调整了齐次行的元素,保证透视除法后各分量符合NDC范围。

用修正后的矩阵测试时,近平面顶点[-1,1,1,1]会被正确投影为NDC的[-1,1,1,1],远平面顶点[-100,100,100,1]会被投影为[-1,1,-1,1],解决垂直偏移和Z轴异常问题。

内容的提问来源于stack exchange,提问作者Rick de Water

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:54:50