Pourquoi avons-nous besoin d'une quatrième coordonnée pour diviser par z?

12

J'ai lu la réponse ici:

Que fait la carte graphique avec le quatrième élément d'un vecteur comme position finale?

"Le quatrième composant est une astuce pour garder une trace de la projection en perspective. Lorsque vous effectuez une projection en perspective, vous voulez diviser par z: x '= x / z, y' = y / z, mais ce n'est pas une opération qui peut être implémenté par une matrice 3x3 fonctionnant sur un vecteur de x, y, z. L'astuce qui est devenue standard pour ce faire est d'ajouter une quatrième coordonnée, w, et de déclarer que x, y, z sera toujours divisé par w après l'application de toutes les transformations et avant la pixellisation. "

mais je ne comprenais pas pourquoi ne pouvions-nous pas diviser par z en utilisant une matrice 3x3?

ne pouvons-nous pas simplement multiplier par

1/z 0 0
0 1/z 0
0 0 1/z

obtenir [x/z y/z 1]

?

Communauté
la source
Essayez d'exprimer une transformation (ou composition de transformations) qui inclut la traduction quelque part dans la chaîne. Sans valeur aw, vous ne pouvez pas l'exprimer dans une seule matrice.
DMGregory
Je comprends la partie traduction, mais je n'ai tout simplement pas compris comment l'ajout d'une quatrième coordonnée aiderait ou serait une astuce à diviser par z
Pour ce que ça vaut, vous pouvez totalement faire ce que vous avez dit. La division de x et y par z est une méthode valide pour convertir des coordonnées 3D en un espace d'écran 2D avec projection où les objets distants deviennent plus petits. Le w est une coordonnée homogène pour le porter jusqu'à la quatrième dimension pour pouvoir faire la traduction.
Alan Wolfe

Réponses:

14

Parce que si vous ne divisez que [x, y, z]par zvous obtenez [x/z, y/z, 1]et vous avez perdu la valeur réelle de z, ce qui est réellement utile si vous voulez effectuer un écrêtage dans le plan proche / lointain ou remplir un Z-buffer.

La meilleure façon de conserver des informations z, au moins sur le GPU, est donc d'utiliser 4 composants au lieu de 3. En pratique, ce qui se trouve réellement dans les deux derniers composants vectoriels avant la division en perspective dépend du type de projection et d'effets que vous vouloir.

Par exemple, dans le cas d'une projection en perspective, il s'agit du vecteur à 4 composantes résultant:

| a 0 0 0 |   | x |   |   ax   |
| 0 b 0 0 |   | y |   |   by   |
| 0 0 c d | × | z | = | cz + d |
| 0 0 1 0 |   | 1 |   |    z   |

Après la division de la perspective, le vecteur devient:

|  ax/z   |
|  by/z   |
| c + d/z |
|    1    |

Et la c + d/zpartie nous laisse suffisamment d'informations pour remplir le tampon Z.

sam hocevar
la source
Vous pouvez diviser uniquement X et Y par Z, ce qui donne [x / z, y / z, z]. Le GPU ne possède il pourrait faire la division vecteur, ont été conçus pour faire un calcul.
user253751
3

Techniquement, vous pourriez le faire. Mais pourquoi s'embêter? Au moment où vous avez cette finale z, vous pouvez soit:

  • construire une matrice 3x3 comme vous l'avez décrit, en gaspillant des 9 * sizeof(float)octets d'espace, en dépensant des cycles pour calculer 1/z(une division) et en faisant ensuite neuf multiplications et six ajouts pour obtenir votre sommet final, ou
  • vous pouvez faire trois divisions, comme le fait le pipeline moderne

L'un d'eux me semble beaucoup plus optimal, et ce n'est pas le premier. Même s'il existe du matériel optimisé pour la multiplication matricielle, comme c'est certainement le cas, il reste conceptuellement plus complexe qu'une simple division.

De plus, une matrice 3x3 ne peut pas coder une traduction, et donc une matrice 4x4 (et donc la quatrième wcoordonnée) est utilisée plus tôt dans le pipeline de toute façon . Cela signifie que vous disposez déjà de ce quatrième composant, vous pouvez donc aussi l'utiliser pour transporter une valeur utile et faire votre division avec.


la source