为什么符号在opengl投影矩阵中很重要
-
21-09-2019 - |
题
我正在研究一个计算机视觉问题,需要使用校准相机渲染 3D 模型。我正在编写一个函数,将校准的相机矩阵分解为模型视图矩阵和投影矩阵,但我在 opengl 中遇到了一个有趣的现象,它无法解释(至少对我来说)。
简而言之,否定投影矩阵不会导致任何内容被渲染(至少根据我的经验)。我希望将投影矩阵乘以任何标量都不会产生任何效果,因为它会变换齐次坐标,而不受缩放的影响。
以下是我认为这是出乎意料的原因;也许有人可以指出我的推理有缺陷。
想象一下以下透视投影矩阵,它给出了正确的结果:
[ a b c 0 ]
P = [ 0 d e 0 ]
[ 0 0 f g ]
[ 0 0 h 0 ]
将其乘以相机坐标即可得到齐次剪辑坐标:
[x_c] [ a b c 0 ] [X_e]
[y_c] = [ 0 d e 0 ] * [Y_e]
[z_c] [ 0 0 f g ] [Z_e]
[w_c] [ 0 0 h 0 ] [W_e]
最后,为了获得标准化的设备坐标,我们将 x_c、y_c 和 z_c 除以 w_c:
[x_n] [x_c/w_c]
[y_n] = [y_c/w_c]
[z_n] [z_c/w_c]
现在,如果我们对 P 取反,则生成的剪辑坐标也应该取反,但由于它们是齐次坐标,因此乘以任何标量(例如-1) 不应对生成的标准化设备坐标产生任何影响。然而,在 openGl 中,否定 P 不会导致任何内容被渲染。我可以将 P 乘以任何非负标量并获得完全相同的渲染结果,但是一旦我乘以负标量,就不会渲染任何内容。这里发生了什么??
谢谢!
解决方案
好了,它的要点是,削波的测试是通过完成:
-w_c < x_c < w_c
-w_c < y_c < w_c
-w_c < z_c < w_c
由负值打破了这种测试乘法。
其他提示
我刚刚发现这个珍闻,这使得朝向一个答案进展:
从红皮书,附录G:
避免使用负瓦特顶点坐标和负Q纹理坐标。的OpenGL可能无法正确剪辑这样的坐标和阴影化由这种坐标定义的原语,当可能使内插误差。
反向投影矩阵将导致负W¯¯裁剪坐标,显然的OpenGL不喜欢此。但是,任何人都可以解释为什么OpenGL的不处理这种情况?
我能想到的原因:
- 通过反转投影矩阵,坐标将不再位于视锥体的 zNear 和 zFar 平面内(必须大于 0)。
- 为了创建窗口坐标,标准化设备坐标由视口进行平移/缩放。因此,如果您对剪辑坐标使用负标量,则标准化设备坐标(现在已反转)会将视口转换为窗口坐标...离开你的窗户(如果你愿意的话,在左边和下面)
另外,既然你提到使用相机矩阵并且你已经反转了投影矩阵,我不得不问......您将相机矩阵中的内容应用于哪些矩阵?对投影矩阵进行操作保存近/远/fovy/aspect 会导致深度缓冲区中出现各种问题,包括使用 z 的任何问题(深度测试、面剔除等)。
OpenGL 常见问题解答部分 转变 有一些更多的细节。