Search code examples
openglgraphicsprojectionhomogenous-transformation

Why does sign matter in opengl projection matrix


I'm working on a computer vision problem which requires rendering a 3d model using a calibrated camera. I'm writing a function that breaks the calibrated camera matrix into a modelview matrix and a projection matrix, but I've run into an interesting phenomenon in opengl that defies explanation (at least by me).

The short description is that negating the projection matrix results in nothing being rendered (at least in my experience). I would expect that multiplying the projection matrix by any scalar would have no effect, because it transforms homogeneous coordinates, which are unaffected by scaling.

Below is my reasoning why I find this to be unexpected; maybe someone can point out where my reasoning is flawed.

Imagine the following perspective projection matrix, which gives correct results:

    [ a b c 0 ]
P = [ 0 d e 0 ]
    [ 0 0 f g ]
    [ 0 0 h 0 ]

Multiplying this by camera coordinates gives homogeneous clip coordinates:

[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]

Finally, to get normalized device coordinates, we divide x_c, y_c, and z_c by w_c:

[x_n]   [x_c/w_c]
[y_n] = [y_c/w_c]
[z_n]   [z_c/w_c]

Now, if we negate P, the resulting clip coordinates should be negated, but since they are homogeneous coordinates, multiplying by any scalar (e.g. -1) shouldn't have any affect on the resulting normalized device coordinates. However, in openGl, negating P results in nothing being rendered. I can multiply P by any non-negative scalar and get the exact same rendered results, but as soon as I multiply by a negative scalar, nothing renders. What is going on here??

Thanks!


Solution

  • Well, the gist of it is that clipping testing is done through:

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

    Multiplying by a negative value breaks this test.