为什么在opengl投影矩阵中符号很重要

时间:2010-02-18 05:31:59

标签: opengl graphics projection homogenous-transformation

我正在研究计算机视觉问题,需要使用校准相机渲染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乘以任何非负标量并获得完全相同的渲染结果,但只要乘以负标量,就不会渲染。这是怎么回事?

谢谢!

3 个答案:

答案 0 :(得分:10)

嗯,它的要点是裁剪测试是通过以下方式完成的:

-w_c < x_c < w_c
-w_c < y_c < w_c
-w_c < z_c < w_c

乘以负值会破坏此测试。

答案 1 :(得分:2)

我刚刚发现了这个小窍门,它在答案上取得了进展:

从红皮书,附录G:

  

避免使用负w顶点坐标和负q纹理坐标。 OpenGL可能无法正确剪切此类坐标,并且在对由此类坐标定义的图元进行着色时可能会出现插值错误。

反转投影矩阵将导致负W剪裁坐标,显然opengl不喜欢这样。但任何人都可以解释为什么opengl不处理这种情况?

参考:http://glprogramming.com/red/appendixg.html

答案 2 :(得分:0)

我能想到的原因:

  • 通过反转投影矩阵,坐标将不再位于视锥体的zN​​ear和zFar平面内(必须大于0)。
  • 要创建窗口坐标,标准化设备坐标由视口进行平移/缩放。因此,如果您使用负标量作为剪辑坐标,则标准化设备坐标(现已反转)将视口转换为窗口坐标...窗口(从左侧和下方,如果您愿意)< / LI>

另外,既然你提到使用相机矩阵而你已经反转了投影矩阵,我不得不问......你在哪些矩阵中应用了相机矩阵?在投影矩阵上操作保存near / far / fovy / aspect会导致深度缓冲区中的各种问题,包括使用z的任何问题(深度测试,面部剔除等)。

transformations上的OpenGL常见问题解答部分提供了更多详细信息。