Wie kann ich verhindern, dass das Ansichtsfenster gedehnt oder verzerrt wird?

13

Grundsätzlich möchte ich wissen, wie ich Verzerrungen oder Dehnungen des gerenderten Bildes beseitigen kann, wenn sich die Größe des Ansichtsfensters / Fensters ändert.

Die folgenden Bilder veranschaulichen die Verzerrung / Dehnung, über die ich spreche:

Originalbild (quadratisches Fenster)

Keine Verzerrung

Verzerrtes / gestrecktes Bild (rechteckiges Fenster)

Mit Verzerrung

Im Idealfall sollte das zweite Bild die Kugel ohne horizontale Streckung darstellen und dem Benutzer mehr von der Szene aussetzen, um die größere Fenstergröße zu berücksichtigen.

Wie geht das?

Ich arbeite mit OpenGL, um das Bild zu rendern, und nutze die perspektivische Projektion über die Aufrufe:

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

Das Seitenverhältnis width/heightstimmt mit allen Dokumenten / Tutorials überein, auf die ich gestoßen bin, daher erwarte ich nicht, dass es falsch ist. Mein Verdacht ist jedoch, dass es das Dehnungsproblem betrifft.


Nach dem Gedanken

Ehrlich gesagt, wenn ich über das Problem mehr nachdenke, würde ich glauben, dass die Lösung eine direkt proportionale Beziehung zwischen dem Fovy-Winkel (Sichtfeld in y-Richtung) und dem Seitenverhältnis beinhaltet.

Perspektivische Projektion

Wenn Sie das obige Bild als Referenz verwenden und die Breite zunimmt (wodurch eine horizontale Streckung verursacht wird), erscheint es sehr plausibel, dass der Fovy-Winkel zunehmen muss, um eine vertikale Streckung zu verursachen, die die Proportionalität des gerenderten Bildes "festlegt".

Ebenso erfordert eine Verringerung der Breite eine Verringerung des Fovywinkels.

Aktualisieren:

Nachdem ich dies näher untersucht habe, habe ich beschlossen, die Art und Weise zu ändern, in der ich den Betrachtungsstumpf eingerichtet habe:

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

Und meine Erwartungen waren richtig, das löste das Verhältnismäßigkeitsproblem. Es erreicht jedoch nicht meine gewünschten Ergebnisse. Wenn die Fensterbreite zunimmt, wird das gerenderte Bild kleiner (die Kugel ist jedoch kreisförmig). Stattdessen sollte sich die Größe der Kugel überhaupt nicht ändern. Nur die Anzahl der angezeigten Szenen sollte sich ändern.

Nicholas Miller
quelle

Antworten:

14

Tatsächlich ist die ursprüngliche Frage von der Lösung abzulehnen.

Ursprünglicher Code

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

Fester Code

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

Das Problem war, dass window.widthund window.heightganze Zahlen sind, was dazu führte, dass das Seitenverhältnis das Ergebnis einer ganzzahligen Division war.

Wenn Sie eine der Dimensionen in einen Gleitkommawert umwandeln, wird stattdessen die Gleitkommadivision verwendet.

Da das Seitenverhältnis nun korrekt ist, gibt es keine Dehnung mehr wie im ursprünglichen Beitrag.

BEARBEITEN: Der Code im Originalbeitrag (und die Antwort) ist einfach ein Pseudocode für die Anrufe an die GPU. Das eigentliche Programm zur Ausgabe der obigen Bilder ist in Java geschrieben. Für diejenigen, die nicht mit Java arbeiten, habe ich nicht untersucht, ob die Ganzzahl- / Gleitkommadivision auf die gleiche Weise implementiert ist. Unabhängig davon geht es bei der Lösung darum, sicherzustellen, dass das Seitenverhältnis tatsächlich korrekt berechnet wird.

Nicholas Miller
quelle