OpenGL: Größenänderung von Anzeige und glOrtho / glViewport


16

Ich habe diese Frage aus mehreren Quellen recherchiert und muss noch eine eindeutige Antwort finden, die besagt, dass "Ja, das ist korrektes Denken" oder "Nein, hier ist, wie es gemacht wird".

Ich versuche, mit OpenGL-Rendering die Unabhängigkeit von der Auflösung zu gewährleisten. Ich denke, ich sollte so vorgehen, dass ich eine Projektion glOrthomit den von mir gewünschten Weltkoordinaten erstelle. Zum Beispiel glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0). Stellen Sie als nächstes das Ansichtsfenster auf die Bildschirmauflösung ein , dh - glViewport(0, 0, 800, 600). Rufen Sie schließlich glViewportbei jeder Größenänderung des Fensters mit der aktualisierten Bildschirmauflösung an. Dies skaliert Ihre Zahlen.

Ist dies der richtige Weg, um sicherzustellen, dass Modelle bei unterschiedlichen Auflösungen den gleichen Anteil an Bildschirmfläche einnehmen? Sollte ich auch eine Projektion verwenden, die der Auflösung entspricht? Ich fand einige Antworten, glOrthodie besagten, dass die Auflösung Ihres Fensters verwendet werden sollte, während andere sagten, dass es anders sein sollte / kann.

Gedanken?

Antworten:


20

Was Sie beschrieben haben, ist völlig ausreichend und angemessen , um die Unabhängigkeit der Lösung zu gewährleisten. Alles, was Sie zeichnen, nimmt in der Tat immer den gleichen Teil Ihres Fensters ein.

Wenn Sie jedoch nichts weiter tun, treten Probleme mit dem Seitenverhältnis auf. Wenn Sie beispielsweise einen Kreis mit den von Ihnen geschriebenen Zahlen zeichnen, wird er gequetscht - breiter als hoch, da Ihre horizontale Skalierung 800 / (50 + 50) = 8 und Ihre vertikale Skalierung 600 / (50+) beträgt 50) = 6.

Es kann keine automatische Lösung für dieses Problem geben . Sie müssen das gewünschte grafische Ergebnis auswählen und dessen Auswirkung auf das Gameplay berücksichtigen. Einige gebräuchliche Beispiele:

  • In einem Perspektivprojektions-3D-Spiel ohne HUD besteht die übliche einfache Lösung (verfügbar in OpenGL als Teil von gluPerspective) darin, das Sichtfeld der Projektion relativ zur vertikalen Dimension festzulegen . Dies bedeutet, dass Sie in einem solchen Spiel mehr oder weniger von der Szene sehen und sich der mittlere Teil des Bildes überhaupt nicht ändert, wenn Sie die Größe des Fensters horizontal ändern.

    Dieselbe Idee kann auch auf eine 2D / 2.5D-Ansicht angewendet werden.

    (Beachten Sie, dass der Spieler dadurch sein Sichtfeld horizontal vergrößern kann, indem er ein breites, aber nicht hohes Fenster erstellt. Dies kann in einem wettbewerbsorientierten Mehrspielerspiel unerwünscht sein.)

  • Wenn Sie mit Ansichtsfenstern gefüllte Grafiken mit einem festen Seitenverhältnis haben (z. B. eine nicht scrollende 2D-Karte oder eine dekorative Umrandung) oder wenn Sie das Layout auf andere Weise nicht ändern können, müssen Sie beispielsweise zwei schwarze Balken verwenden Seiten, um den ungenutzten Raum zu füllen.

    Sie können auch Grafiken mit thematisch einheitlichem Füllmaterial an den Rändern erstellen, die so zugeschnitten werden können, dass sie auf das Display passen, ohne das Gameplay zu beeinträchtigen.

  • Wenn Sie eine Schwebepalette über anderen Grafiken haben, können Sie festlegen, dass jedes Schwebepalettenelement an einem Teil des Fensters befestigt ist (oben links, unten in der Mitte usw.), und die Koordinaten berechnen. Die Streckung durch Variation der Seitenverhältnisse wird durch den "Leerraum" zwischen den HUD-Elementen absorbiert.

In Bezug auf die spezifischen Mathematik der Sache, da Sie Auflösungsunabhängigkeit tun, alles , was Sie brauchen , um mit zu beginnen ist das Seitenverhältnis, eine einzige Zahl: width / height. Wenn das Fenster beispielsweise quadratisch ist, ist es 1; Wenn es 800 mal 600 ist, ist es 800/600 = 4/3 = 1,333̅.

Angenommen, Sie möchten, dass die von Ihnen geschriebene orthografische Projektion auf der linken und rechten Seite zusätzlichen Platz einnimmt, wenn das Fenster erweitert wird. Das können Sie so machen:

float aspect = width / height;
glViewport(0, 0, width, height);
glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);

Dies garantiert, dass für Fenster, die mindestens so breit wie hoch sind, alles sichtbar ist, was Sie mit x- und y-Koordinaten zwischen -50 und 50 zeichnen.

Ist das Fenster hingegen schmaler als hoch, wird der Bereich von -50 bis -50 abgeschnitten. Angenommen, Sie möchten sicherstellen, dass es immer sichtbar ist (damit Ihr Inhalt seine maximale Größe hat, wenn das Fenster quadratisch ist, andernfalls aber kleiner). In diesem Fall machen Sie einfach das Gleiche mit der Höhe anstelle der Breite.

float aspect = width / height;
glViewport(0, 0, width, height);
if (aspect >= 1.0)
  glOrtho(-50.0 * aspect, 50.0 * aspect, -50.0, 50.0, 1.0, -1.0);
else
  glOrtho(-50.0, 50.0, -50.0 / aspect, 50.0 / aspect, 1.0, -1.0);

Beachten Sie, dass wir im zweiten Fall eher dividieren als multiplizieren. Dies liegt einfach daran, dass wir das Seitenverhältnis als width / heightund nicht als berechnet haben height / width. Nehmen Sie das Gegenteil, wenn Sie es leichter finden, auf diese Weise zu verstehen.

Auch dies ist nicht die einzige Möglichkeit, das Seitenverhältnis zu verwalten. Dies ist nur eine sehr einfache Methode, um sicherzustellen, dass Ihre Inhalte weder gequetscht noch abgeschnitten werden. Finden Sie heraus, was passieren soll, wenn Ihr Fenster breit, hoch oder was auch immer ist. dann erarbeiten Sie die Mathematik davon.


Vielen Dank für die sehr aufschlussreiche Antwort. Meine Frage darüber hinaus ausreichend beantwortet.
Chris Henderson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.