Comment puis-je empêcher la fenêtre d’être étirée / déformée?

13

Fondamentalement, je veux savoir comment supprimer la distorsion ou l'étirement de l'image rendue lorsque la taille de la fenêtre / fenêtre change.

Les images suivantes illustrent la distorsion / étirement dont je parle:

Image originale (fenêtre carrée)

Pas de distorsion

Image déformée / étirée (fenêtre rectangulaire)

Avec distorsion

Idéalement, la deuxième image devrait afficher la sphère sans étirement horizontal et exposer davantage la scène à l'utilisateur pour tenir compte de la plus grande taille de fenêtre.

Comment cela peut-il être fait?

Je travaille avec OpenGL pour rendre l'image, et j'utilise la projection en perspective via les appels:

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Le rapport d'aspect width/heightest conforme à tous les documents / tutoriels que j'ai rencontrés, donc je ne m'attends pas à ce qu'il soit incorrect. Cependant, je soupçonne que cela affecte le problème d'étirement.


Après réflexion

Honnêtement, en réfléchissant davantage à la question, je pensais que la solution impliquait une relation directement proportionnelle entre l'angle fovy (champ de vision dans la direction y) et le rapport hauteur / largeur.

Projection en perspective

En utilisant l'image ci-dessus comme référence, si la largeur augmente (provoquant un étirement horizontal), il semble très plausible que l'angle fovy doive augmenter pour provoquer un étirement vertical qui `` fixe '' la proportionnalité de l'image rendue.

De même, une diminution de la largeur nécessite une diminution de l'angle fovy.

Mise à jour:

Donc, après avoir approfondi cela, j'ai décidé de changer la façon dont j'ai configuré le tronc de visualisation comme ceci:

gluPerspective(60 * (float)window.width/window.height, (float)window.width/window.height, 0.01f, 100.0f)

Et mes attentes étaient correctes, ce qui a résolu le problème de proportionnalité. Cependant, il n'atteint pas les résultats souhaités. Lorsque la largeur de la fenêtre augmente, l'image rendue devient plus petite (mais la sphère est en effet circulaire). Au lieu de cela, la sphère ne devrait pas du tout changer de taille; seule la quantité de scène affichée doit changer.

Nicholas Miller
la source

Réponses:

14

En fait, la question initiale est rejetée de la solution.

Code d'origine

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Code fixe

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, (float)window.width/window.height, 0.01f, 100.0f)

Le problème était que window.widthet ce window.heightsont des entiers, ce qui faisait que le rapport d'aspect était le résultat d'une division entière.

Si vous convertissez l'une des dimensions en flottant, le résultat utilise à la place une division en virgule flottante.

Étant donné que le rapport hauteur / largeur est désormais correct, il n'y a plus d'étirement comme indiqué dans le message d'origine.

EDIT: Le code dans le message d'origine (et la réponse) est simplement un pseudo-code pour les appels au GPU; le programme réel utilisé pour produire les images ci-dessus est écrit en Java. Pour ceux qui ne travaillent pas avec Java, je n'ai pas recherché si la division entier / virgule flottante est implémentée de la même manière. Quoi qu'il en soit, la solution consiste à s'assurer que le rapport d'aspect est bien correctement calculé.

Nicholas Miller
la source