java - 为什么我的逆投影矩阵的两个元素始终为 0?

标签 java matrix 3d coordinate-transformation projection-matrix

我正在编写一个光线追踪器,我需要将光线从屏幕转换到世界上。我使用 View -投影-视口(viewport)矩阵的逆来从屏幕像素坐标返回到世界空间坐标。

我偶然注意到,无论我如何移动、缩放、绕轨道运行或旋转相机,逆矩阵的两个元素始终为 0。我对投影矩阵的理解不够深入,不知道为什么。

这是我的 Matrix 类中希望相关的部分:

// OpenGL-style column-vectors layout.
public final class Matrix4 {
    public double e11, e12, e13, e14;
    public double e21, e22, e23, e24;
    public double e31, e32, e33, e34;
    public double e41, e42, e43, e44;
    
    public void transform(Vec3 v) {
        double x = v.x, y = v.y, z = v.z;
        double w = (x * e41) + (y * e42) + (z * e43) + (e44);
        double norm = 1 / w;
        v.x = ((x * e11) + (y * e12) + (z * e13) + (e14)) * norm;
        v.y = ((x * e21) + (y * e22) + (z * e23) + (e24)) * norm;
        v.z = ((x * e31) + (y * e32) + (z * e33) + (e34)) * norm;
    }
    
    public void perspectiveFovLH(double fovy, double aspect, double znear, double zfar) {
        double yscale = 1 / tan(fovy * 0.5);
        double xscale = yscale / aspect;
        double Q = zfar / (zfar - znear);
        
        e11 = xscale;
        e22 = yscale;
        e33 = Q;
        e34 = Q * -znear;
        e43 = 1;
    }
}

这是移动相机一段时间后的 View -投影-视口(viewport)矩阵:

[ -331.62051997,  -616.31014741, -927.45531750,  354532.72229686
   158.60434983, -1091.70516425,  427.49500301,  420008.37868979
     0.75468455,    -0.51045982,   -0.41337968,     766.88486375
     0.75430721,    -0.51020459,   -0.41317299,     771.50142132 ]

这是它的逆:

[ -0.00058203, -0.00019009,  113.94949731, -112.89669211
  -0.00033747, -0.00072765,  -84.29481494,   84.34162134
  -0.00064586,  0.00055151,  -61.14292715,   60.77360931
  -0.00000000, -0.00000000,   -0.19990000,    0.20000000 ]

当我移动相机时,大多数元素都会不断变化。逆函数右下角的两个元素似乎与 znear 和 zfar 参数直接相关。左下角的两个元素看起来总是0。

这个事实在变换方法中很有用。如果 e41 和 e42 为 0,并且当将光线的近点和远点转换到屏幕上时,输入 z 始终为 0 或 1,则可以提前计算 w 除法,而不是按像素计算。这是有效的,并且是一个有用的加速。

但是,我担心这个假设以后会破坏某些东西。所以我想知道,这两个元素都为0意味着什么,这个假设什么时候成立?


编辑:我found out仿射 4x4 矩阵具有最后四个元素 (0 0 0 1)。我的逆矩阵几乎匹配。但是,使透视矩阵的逆矩阵仿射或几乎仿射的魔力是什么?

最佳答案

对于给定的perspectiveFovLH矩阵P和任何齐次/仿射变换矩阵M,逆R≔ (PM)−1总是Rwx=R wy=0。

证明

要看到这一点,对于某些输入v,令tMv,并令s>Pt=PMv,这样v=Rs。 请注意,每个 M 都有 Mwx=Mwy=M wz=0 且Mww=1,这样tw=vw。 然后从P的稀疏性观察sw=tz并且

sz=QtzQz0tw
=QswQz0vw

解最后一个方程得出

vw=(Qswsz)/(Qz0)

这个公式显然只依赖于szsw,证明了假设 Rwx=Rwy=0。

基本原理

我们可以用一种非公式化的方式来理解这一点:3×4 矩阵足以在屏幕上进行透视,因为您只需要 2 个输出坐标和一个用于划分它们的齐次坐标。使用完整的 4×4 矩阵会引入冗余,因为结果的 zw 坐标仅源自输入的 z 坐标(以及初始 w 的已知常数 1)。无论投影之前应用的世界变换如何,变换后的 z原始 w 中仍然有这两个方程,这足以为他们解决。

关于java - 为什么我的逆投影矩阵的两个元素始终为 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76398774/

相关文章:

opengl - HDR渲染管线差异

opengl - 平面阻塞多分辨率体绘制

java - 一个简单计算器代码的问题(Java)

java - 从 PHP/MySQL 到 Java/JSON

java - 故意忽略连字符

java - Neo4j 控制台无法启动

python - 在 Python 中创建二维矩阵的更优雅的方式

c++ - 当矩阵不是奇异时,lapack cgesv 出错

c - double 型矩阵 [n]x[n] 传输至 ASSEMBLY

python - 小狗。如何动态更改顶点的图片(动画)。 OpenGL