投影矩阵导致垂直偏移

问题描述 投票:0回答:1

我正在尝试在 3d 空间中渲染四边形,但是当我应用投影矩阵时,当我希望它仍然位于屏幕中心时,会出现垂直偏移。我觉得我已经消除了所有其他变量(没有其他矩阵,1/1 屏幕比例等),所以投影矩阵本身一定有问题。下图中唯一的区别是我乘以投影矩阵还是单位矩阵。

渲染引擎的坐标系是X向右,Y向前,Z向上。在两个示例中,通过将投影矩阵与翻转轴的矩阵相乘,将其转换为 Vulkan 坐标系。

所以我的问题是,我在投影矩阵计算中哪里出错了?

同样重要的是,矩阵是行主矩阵,NDC 为 (-1, -1, -1) 到 (1, 1, 1)。

编辑: 更多测试确实表明 Z 轴上发生了不需要的偏移。我做了一个简单的投影矩阵,

Matrix4x4f::perspective_near_plane(-1.0, 1.0, 1.0, -1.0, 1.0, 100.0)

并将近平面和远平面的角点坐标乘以投影。这应该简单地给出 NDC 的角点,但返回的是:

[-1, 1, 1, 1]        -> [-1, -0.9999999, 2, 1] -> [-1, -0.9999999, 2, 1]
[1, 1, 1, 1]         -> [1, -0.9999999, 2, 1]  -> [1, -0.9999999, 2, 1]
[1, 1, -1, 1]        -> [1, -0.9999999, 0, 1]  -> [1, -0.9999999, 0, 1]
[-1, 1, -1, 1]       -> [-1, -0.9999999, 0, 1] -> [-1, -0.9999999, 0, 1]
[-100, 100, 100, 1]  -> [-100, 100, 101, 100]  -> [-1, 1, 1.01, 1]
[100, 100, 100, 1]   -> [100, 100, 101, 100]   -> [1, 1, 1.01, 1]
[100, 100, -100, 1]  -> [100, 100, -99, 100]   -> [1, 1, -0.99, 1]
[-100, 100, -100, 1] -> [-100, 100, -99, 100]  -> [-1, 1, -0.99, 1]

没有投影矩阵

Without projection matrix

带有投影矩阵

With projection matrix

投影矩阵计算

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 {
        let m11 = ((T::one() + T::one()) * near) / (right - left);
        let m12 = T::zero();
        let m13 = T::zero();
        let m14 = T::zero();
    
        let m21 = -(right + left) / (right - left);
        let m22 = (far + near) / (far - near);
        let m23 = -(top + bottom) / (top - bottom);
        let m24 = T::one();
    
        let m31 = T::zero();
        let m32 = T::zero();
        let m33 = ((T::one() + T::one()) * near) / (top - bottom);
        let m34 = T::zero();
    
        let m41 = T::zero();
        let m42 = (-(T::one() + T::one()) * far * near) / (far - near);
        let m43 = T::one();
        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)
    }
}

创建投影矩阵

let projection = Matrix4x4f::perspective_horizontal_fov(
    60.0 / 180.0 * std::f32::consts::PI,
    window_size.x as f32 / window_size.y as f32,
    0.1,
    1000.0);

坐标调整矩阵

Matrix4x4f::new(
    1.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.0, -1.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 1.0
)

硬编码顶点位置

static const float3 positions[6] = {
    float3(-0.5, 1, -0.5),
    float3(0.5, 1, 0.5),
    float3(-0.5, 1, 0.5),
    float3(-0.5, 1, -0.5),
    float3(0.5, 1, -0.5),
    float3(0.5, 1, 0.5),
};
rust matrix graphics vulkan
1个回答
0
投票

我找到罪魁祸首了!我将 m24 和 m43 的值都设置为 1。但正如您在this示例中所看到的,矩阵中只有一个元素应该具有非零常数值。

由于 m43 是这两个元素中唯一影响 Z 轴的元素,因此必须将其设置为零。该值被添加到 Z 位置,导致垂直偏移。

Fixed projection

© www.soinside.com 2019 - 2024. All rights reserved.