¿Por qué la matriz de proyección OpenGL tiene -1 en la fila inferior?

Digamos que usted es un desarrollador de OpenGL que quiere representar una proyección en perspectiva como una matriz, porque los ha utilizado para representar todas sus otras transformaciones.

Haces los cálculos y descubres que la coordenada x proyectada de cualquier vector que se puede transformar está dada por la ecuación:

[matemáticas] Ps_x = \ dfrac {2nx} {- z (rl)} \ dfrac {r + l} {rl} [/ matemáticas]

Donde z la coordenada z del vector, [matemática] n [/ matemática] es el plano de recorte cercano, y [matemática] r [/ matemática] y [matemática] l [/ matemática] son ​​los límites derecho e izquierdo. Los detalles se pueden encontrar en The OpenGL Perspective Projection Matrix.

Ahora es solo para poner eso en una matriz, ¡genial! Probemos uno de 3 por 3 porque es todo en 3D.

[matemáticas] \ begin {bmatrix} a & b & c \\ \ cdots & \ cdots & \ cdots \\ \ cdots & \ cdots & \ cdots \ end {bmatrix} \ begin {bmatrix} x \\ y \\ z \ end {bmatrix} = \ begin {bmatrix} Ps_x \\ Ps_y \\ Ps_z \ end {bmatrix} [/ math]

Solo estamos enfocados en el xcoordinate que viene dado por:

[matemáticas] Ps_x = ax + por + cz [/ matemáticas]

Ahora es solo para encontrar ab y c …

Espere. ¿Cómo vamos a dividir x por z? Z claramente solo se suma.

Ingrese las coordenadas homogéneas, donde agregamos una dimensión adicional “w” que cuando se convierte de nuevo en coordenadas cartesianas, divide todas las demás coordenadas.

cartesiano homogéneo

[matemáticas] \ lbrack x, y, z, w \ rbrack \ iff \ left \ lbrack \ frac {x} {w}, \ frac {y} {w}, \ frac {z} {w} \ right \ rbrack [/matemáticas]

Entonces, si hacemos todos nuestros vectores 4d y nuestra matriz 4d también, obtenemos:

[matemáticas] \ begin {bmatrix} a & b & c & d \\ \ cdots & \ cdots & \ cdots & \ cdots \\ \ cdots & \ cdots & \ cdots & \ cdots \\ 0 & 0 & -1 & 0 \ end {bmatrix} \ begin {bmatrix} x \\ y \\ z \\ w \ end {bmatrix} = \ begin {bmatrix} Ps_x \\ Ps_y \\ Ps_z \\ Ps_w \ end {bmatrix} [/ math]

Ahora, dado que [math] Ps_w [/ math] dividirá todas las demás coordenadas proyectadas, si lo establecemos en -z colocando ese -1 en la tercera columna de la última fila, podemos dividir nuestro [math] Ps_x [/ math] por nuestra coordenada z! Hooray problema resuelto.

Esto puede funcionar porque calcular [math] Ps_y [/ math] también requiere dividir por -z.

La razón por la cual es -z es porque nosotros, como desarrolladores de OpenGL, decidimos enfrentar la cámara hacia abajo en la dirección negativa de z por alguna razón, por lo que debemos negar la z para que se vuelva positiva.

Se pueden encontrar más detalles en el primer enlace.