Le système de coordonnées OpenGL est-il gaucher ou droitier?

86

J'essaie de comprendre le système de coordonnées OpenGL. Cependant, certains tutoriels disent que le système de coordonnées par défaut est gaucher (voir http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ) et d'autres disent qu'il est droitier (voir http: // www .falloutsoftware.com / tutoriels / gl / gl0.htm ). Qui est correct? Je comprends que nous pouvons transformer l'un en l'autre par mise en miroir mais j'aimerais connaître les coordonnées par défaut.

341008
la source
Programmeurs
88776
2
Cela ne dépend-il pas entièrement de la façon dont vous écrivez vos transformations dans les shaders et dépend donc entièrement de vous?
jcoder
Juste mes deux cents evl.uic.edu/ralph/508S98/coordinates.html , il a quelques images explicites.
rraallvv
Je suppose que vous n'envisageriez pas de mettre à jour votre réponse acceptée?
Jonathan Mee

Réponses:

132

Il y a une certaine confusion ici.

entrez la description de l'image ici

OpenGL est droitier dans l'espace objet et l'espace mondial.

Mais dans l'espace fenêtre (aka espace écran), nous sommes soudainement gauchers .

Comment est-ce arrivé ?

La façon dont nous passons de droitier à gaucher est une entrée de mise à l'échelle z négative dans les matrices de projection glOrthoou glFrustum. La mise à l'échelle de z par -1 (tout en laissant x et y tels quels) a pour effet de modifier la sensibilité du système de coordonnées.

Pour glFrustum,

entrez la description de l'image ici entrez la description de l'image ici

loin et proche sont supposés être positifs, avec loin > proche . Dites loin = 1000 et près = 1. Alors C = - (1001) / (999) = -1,002.

Voir ici pour plus de détails et de diagrammes.

D'un point de vue orthographique , glOrtho génère une matrice comme celle-ci:

entrez la description de l'image ici

Ici, à gauche , à droite , en bas et en haut sont seulement les coordonnées de gauche verticale , droite verticale , horizontale inférieure , supérieurs horizontaux plans de délimitation (resp) .

Les plans proche et éloigné , cependant, sont spécifiés différemment . Le paramètre proche est défini comme

  • Near: La distance par rapport au plan de détourage de profondeur le plus proche. Cette distance est négative si l'avion doit être derrière le spectateur.

et loin:

  • zFar La distance par rapport au plan de détourage de profondeur le plus éloigné. Cette distance est négative si l'avion doit être derrière le spectateur.

Ici, nous avons un volume de vue canonique typique

canonique

Comme le multiplicateur z est (-2 / (très proche)), le signe moins met effectivement à l'échelle z par -1 . Cela signifie que "z" est tourné à gauche pendant la transformation de visualisation, à l'insu de la plupart des gens car ils travaillent simplement dans OpenGL comme un système de coordonnées "droitier".

Donc, si vous appelez

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

Alors le PRÈS DE L'AVION a 10 unités devant vous . Où es-tu? Pourquoi, à l'origine, avec l'axe x à votre droite, l'axe y au-dessus de votre tête et votre nez pointant vers le bas l'axe z négatif (c'est la valeur par défaut "Par défaut, la caméra est située à l'origine , pointe vers le bas l'axe z négatif et a un vecteur ascendant de (0, 1, 0). " ). Le plan proche est donc à z = -10. Le plan lointain est à 10 unités derrière vous, à z = + 10 .

bobobobo
la source
1
"le vecteur avant est annulé dans gluLookAt" - pouvez-vous confirmer que c'est bien le cas? Pas gluPerspective ou glFrustum ou glOrtho?
Kos
1
Nous sommes soudainement gauchers à partir de l'espace du clip, pas seulement de l'espace de la fenêtre.
legends2k
3
+1 pour toute la réponse, -1 (attendez plutôt -2) pour "La façon dont nous passons de droitier à gaucher est que le vecteur avant est annulé dans l'implémentation standard de gluLookAt (), qui est la fonction tout le monde utilise pour créer la matrice de vue. Lorsque vous annulez le vecteur vers l'avant, cela a pour effet de modifier l'aspect manuel du système de coordonnées. " , qui n'est que des ordures ...
Christian Rau
2
... Nier le vecteur avant dans le gluLookAtcalcul n'a rien à voir avec le changement de la sensibilité de l'espace de coordonnées, c'est juste comme ça que cette matrice est calculée (et en fait + z est en effet "en arrière" dans l'espace droitier). gluLookAtne fait rien d'autre que de calculer une transformation de corps rigide ordinaire (rotation + translation) dans un espace droitier. Ce sont les matrices de projection utilisées par le pipeline de fonctions fixes (et généralement par les shaders aussi) qui effectuent le changement de caractère réel dans leur négation du composant z, comme vous l'avez déjà noté dans votre réponse.
Christian Rau
2
@bobobobo Ce que vous dites si vous calculez votre matrice de vue en utilisant uniquement les fonctions de rotation et de traduction (ce que je suppose que vous n'accuserez pas de changer de main), au lieu de cela gluLookAt, il n'y aurait pas de changement de base alors gluLookAtqu'il y en a un? Certainement pas (puisque vous savez probablement que "tout le monde" n'utilise pas gluLookAtpour le calcul de la matrice de vue), car comme vous devriez le savoir gluLookAtne fait rien d'autre qu'un tas d'appels de rotation et de traduction (même déguisés en changement de " terme de haut niveau" base " ) sans aucune réflexion.
Christian Rau
26

Par défaut, la coordonnée normalisée de l'appareil est gaucher.

Le glDepthRange est par défaut [0, 1] (proche, loin) faisant pointer l'axe + z dans l'écran et avec + x à droite et + y en haut, c'est un système gaucher.

Changer la plage de profondeur sur [1, 0] rendra le système droitier.

Citant une réponse précédente de Nicol : (le barré est mon travail, expliqué ci-dessous)

Je suis surpris que personne n'ait mentionné quelque chose: OpenGL fonctionne également dans un système de coordonnées gaucher. Du moins, c'est le cas lorsque vous travaillez avec des shaders et utilisez la plage de profondeur par défaut.

Une fois que vous avez jeté le pipeline à fonction fixe, vous vous occupez directement de "l'espace de clip". La spécification OpenGL définit l'espace-clip comme un système de coordonnées homogène 4D. Lorsque vous suivez les transformations via les coordonnées normalisées de l'appareil, et jusqu'à l'espace de la fenêtre, vous trouvez ceci.

L'espace de la fenêtre est dans l'espace des pixels d'une fenêtre. L'origine est dans le coin inférieur gauche, avec + Y vers le haut et + X vers la droite. Cela ressemble beaucoup à un système de coordonnées droitier. Mais qu'en est-il de Z?

La plage de profondeur par défaut (glDepthRange) définit la valeur proche de Z sur 0 et la valeur de loin Z sur un . Le + Z s'éloigne donc du spectateur.

C'est un système de coordonnées gaucher. Oui, vous pouvezchanger le test de profondeur de GL_LESS à GL_GREATER etchangez le glDepthRange de [0, 1] à [1, 0]. Mais l' état par défaut d'OpenGL est de travailler dans un système de coordonnées gaucher . Et aucune des transformations nécessaires pour accéder à l'espace fenêtre à partir de l'espace de clip annule le Z. Donc, l'espace de clip, la sortie du shader de vertex (ou de géométrie) est un espace de gauche (un peu. C'est un espace homogène 4D, donc il est difficile de cerner la sensibilité).

Dans le pipeline à fonction fixe, les matrices de projection standard (produites par glOrtho, glFrustum et autres) se transforment toutes d'un espace droitier à un espace gauche . Ils inversent la signification de Z; vérifiez simplement les matrices qu'ils génèrent. Dans l'espace oculaire, + Z se déplace vers le spectateur; dans l'espace post-projection, il s'éloigne.

Je soupçonne que Microsoft (et GLide) n'ont tout simplement pas pris la peine d'effectuer la négation dans leurs matrices de projection.

J'ai frappé une partie car elle divergeait de mes conclusions.

Le changement de DepthRange ou de DepthFunc et l'utilisation de ClearDepth (0) fonctionnent mais lors de l'utilisation des deux, ils se sont annulés pour revenir à un système gaucher.

hultqvist
la source
La plage de profondeur ne peut pas être [1, -1]. Je pense que vous vouliez dire [1, 0]. En outre, cela a déjà été souligné .
Nicol Bolas
Votre réponse est excellente, dommage que ce soit à une question DirectX, vous devriez la republier ici!
hultqvist
3
@SigTerm pourquoi pensez-vous que corriger une fausse déclaration n'en vaut pas la peine? J'ai passé plusieurs heures à dépanner les coordonnées des sommets et la génération de rotation de la matrice juste pour découvrir que le système de coordonnées par défaut n'était en fait pas droitier.
hultqvist
1
La question était de savoir s'il s'agissait d'un système gaucher ou droitier. Cette réponse a plus de détails que cela, expliquant deux autres façons de l'obtenir droitier, ajouter un -1 dans une transformation matricielle est encore une autre façon de le faire. Mais rien de tout cela n'a d'importance si vous pensez que le système est droitier par défaut, vous ne pouvez changer quelque chose que si vous savez de quoi vous changez. Still
hultqvist
1
J'ai trouvé la réponse très éclairante, et elle est apparue dans les recherches, donc ça valait le coup pour moi.
Apprendre OpenGL ES
13

UNIQUEMENT NDC

Vous devriez seulement remarquer qu'OpenGL ne connaît que NDC! et c'est un système de coordonnées gaucher.

Quel que soit le système de coordonnées que vous utilisez - système de coordonnées d'axe gauche ou droit - tous doivent être mis en miroir sur NDC. Si vous le souhaitez, vous pouvez totalement gérer l'espace-monde comme un système de coordonnées gaucher.

Pourquoi utilisons-nous généralement un système de coordonnées droitier dans l'espace-monde?

Je pense que c'est conventionnel. C'est juste le cas. Peut-être veut-il simplement faire la distinction avec DirectX.

ZK_
la source
3
Je pense que cela ne se répète pas assez. Tous ces diagrammes montrant «transformation de modélisation», «transformation de vue», «transformation de perspective» ne montrent pas qu'ils ne font pas partie intégrante d'OpenGL. Vous pouvez même faire toutes vos transformations manuellement, avec ou sans shaders, avec ou sans matrices.
Tom
3
Il serait peut-être plus agréable de le répéter pour inclure les mots «coordonnées de périphérique normalisées».
Tommy
6
OpenGL est antérieur à DirectX de quelques années, donc OpenGL n'essayait certainement pas de se distinguer de DirectX. Le développeur principal de DirectX, Alex St. John, a déclaré que la décision de Microsoft d'opter pour un système de coordonnées pour gauchers était "en partie par préférence personnelle" et "un choix arbitraire".
Chris Nolet
Ce n'est pas tout à fait correct. OpenGL connaît également le système de coordonnées de découpage, puisque le découpage se produit là-dedans. Le système de coordonnées de clip a la même main que le système de coordonnées NDC tho.
plasmacel
7

Le livre "WebGl Programming Guide" de Kouichi Matsuda consacre près de dix pages à "WebGl / OpenGl: Left or Right Handed?"

D'après le livre:

  • En pratique, la plupart des gens utilisent un système droitier

  • OpenGl est en fait un système pour gauchers en interne

  • En interne, plus profondément, ce n'est ni l'un ni l'autre. Tout en bas, OpenGl ne se soucie pas de la valeur z. L'ordre dans lequel vous dessinez les choses détermine ce qui est dessiné en haut (dessinez d'abord un triangle, puis un quad, le quad remplace le triangle).

Je ne suis pas entièrement d'accord avec le «ce n'est ni l'un ni l'autre», mais c'est probablement une question philosophique de toute façon.

Heinzlmaen
la source
6
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). C'est vrai, en l'absence de test de profondeur. En présence d'un test de profondeur, la valeur z d'un fragment est comparée à la valeur du tampon de profondeur, et le fragment est rejeté s'il échoue au test de profondeur, de sorte que le quad peut ou non écraser le triangle en fonction de sa profondeur et de la fonction de profondeur utilisée.
chrisvarnz
3

Opengl est définitivement gaucher. Vous voyez de nombreux didacticiels indiquant le contraire car ils annulent la valeur z dans la matrice de projection. Lorsque les sommets finaux sont calculés à l'intérieur du vertex shader, il convertit les sommets que vous passez du côté client (coordonnée à droite) en gaucher, et les sommets seront ensuite passés au shader geometry et au fragment shader. Si vous utilisez le système de coordonnées de droite côté client, Opengl s'en fiche. Il ne connaît que le système de coordonnées normalisé, qui est gaucher.

Edit: Si vous ne me faites pas confiance, expérimentez simplement votre vertex shader en ajoutant une matrice de traduction, et vous pourrez facilement voir si Opengl est gaucher ou non.

Diable étranger
la source
0

En utilisant les fonctions de projection et de transformation intégrées d'OpenGL, l'observation des mouvements à l'écran suit les règles du système de coordonnées droitier . Par exemple, si un objet devant votre vue est traduit dans la direction z positive, l'objet se déplacera vers vous.

Le tampon de profondeur est tout le contraire, et c'est là que les NDC (Normalized Device Coordinates) entrent en jeu. Si le fait de passer GL_LESS dans glDepthFunc signifie que les pixels seront dessinés lorsqu'ils seront plus proches de vous que ce qui se trouve déjà dans le tampon de profondeur, alors les pixels sont considérés comme vivant dans un système de coordonnées gaucher .

Il y a un autre système de coordonnées, et c'est la fenêtre! Le système de coordonnées de la fenêtre est tel que + x pointe vers la droite et + y pointe vers le bas. Je pense qu'à ce stade, la sensibilité est sans objet puisque nous n'avons affaire qu'à x, y à ce stade.

Enfin, gluLookAt sous le capot doit annuler le vecteur de regard. Étant donné que le calcul suppose qu'un vecteur pointe dans une direction positive vers l'objet qu'il regarde et qu'une caméra regarde vers le bas -z, le vecteur d'observation doit être annulé afin qu'il s'aligne avec la caméra.

Quelque chose à mâcher. Cela n'a pas beaucoup de sens d'appeler la direction z d'un système de coordonnées droitier un vecteur avant :). Je pense que Microsoft a réalisé cela quand ils ont conçu Direct3D.

weatx
la source