Ich hoffe, jemand kann mir helfen, das GLViewport zu verstehen und was passiert, wenn wir die Größe ändern
Dies wird meine Verwirrung veranschaulichen ....
Also, hier habe ich ein Quad in der Mitte des Bildschirms. Wenn mein GLViewport mit der Breite und Höhe des Geräts übereinstimmt, erhalte ich das Bild auf dem ersten Bild (links). Genau das, was ich erwarten würde.
- Geräteauflösung 2560 x 1600
- Auflösung des Ansichtsfensters 2560 x 1600
- Quad Größe 200 x 200 (Hinweis, das Bild oben ist nicht maßstabsgetreu !!! :-))
- Quad-Form, erscheint als Quadrat
Nun zum 2. Bild (rechts) ...
- Geräteauflösung 2560 x 1600
- Auflösung des Ansichtsfensters 2560 x 1200 (und vertikal zentriert)
- Quad-Größe (200, 200)
- Quad-Form, erscheint als Rechteck
Meine Frage ist, warum das Quad jetzt als Rechteck und nicht als Quadrat angezeigt wird. Ich habe durch Protokollierung bestätigt, dass mein Quad 200 x 200 Pixel groß ist - bleibt die Größe der physischen Pixel doch gleich? Sie können sich nicht ändern. Also, was ist hier los?
Ich dachte (eindeutig falsch), dass beim Skalieren des Ansichtsfensters nur Pixel abgeschnitten wurden.
Würde mich freuen, wenn jemand erklären könnte, wie das funktioniert.
Bearbeiten
Derzeit stelle ich mein Ansichtsfenster folgendermaßen ein:
width = (int) Math.min(deviceWidth, deviceHeight * 1.702127659574468);
height = (int) Math.min(deviceHeight, deviceWidth / 1.702127659574468);
ratio = width / height;
GLES20.glViewport(offsetX, offsetY, width, height);
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
offsetX und offsetY sind nur so, dass das Ansichtsfenster zentriert ist, wenn Briefkästen vorhanden sind.
quelle
glScissor
anstelle von verwendenglViewport
, werden einfach Pixel abgeschnitten, ohne zu ändern, wo etwas gerendert wird.glViewport
verhält sich eher so, als würde man die Größe des Originalbilds ändern, anstatt es zu beschneiden; Deshalb zerquetscht es Ihre Box.Antworten:
Um zu verstehen, was los ist, müssen Sie die Rendering-Pipeline verstehen:
Ihre Geometrie (das Quad) wird anfänglich im Weltraum definiert. Stellen Sie sich dies als ein globales Koordinatensystem vor. Innerhalb des Vertex-Shaders werden diese in normalisierte Gerätekoordinaten (NDC) umgewandelt, ein virtuelles Koordinatensystem, das so definiert ist, dass alles von -1 bis 1 auf den Bildschirm gezeichnet wird. Beachten Sie, dass der NDC in X und Y zwischen -1 und 1 liegt und völlig unabhängig vom Seitenverhältnis und der Auflösung des Geräts ist. Diese Transformation vom Weltraum zum NDC erfolgt durch die Modell-, Ansichts- und Projektionsmatrix (in einer einfachen Form wurde zunächst nur eine Matrix für alles oder die Geometrie in NDC definiert!).
Die Rasterisierungseinheit muss wissen, wo und wie groß das Raster sein soll. Dies definieren Sie mit dem glViewport-Aufruf: Wo sollen die ersten beiden Parameter beginnen, die Größe sind die zweiten beiden. Die Hardware konvertiert dann durch einfaches Skalieren und Verschieben von NDC in Pixelkoordinaten - und das sehen Sie in Ihrem Beispiel: eine Skalierung auf der Y-Achse.
Um sicherzustellen, dass Ihr Quad im richtigen Seitenverhältnis gerendert wird, müssen Sie auch die Projektionsmatrix so anpassen, dass sie das erwartete Seitenverhältnis des glViewport-Aufrufs enthält.
quelle
glFrustum
die genaue Matrix aufgeführt ist, die von diesen Funktionen erstellt wird. Eine andere häufig verwendete Projektionsmatrix wurde von erstelltglOrtho
. Obwohl all diese Befehle veraltet sind, sind die darin enthaltenen Dokumente eine hervorragende Quelle für einige vorab abgeleitete Mathematik.In Ihrem Aufruf von glViewport geben Sie weniger Pixel in Breite und Höhe an. Ihre Projektionsmatrix wird in Pixel definiert. Deshalb müssen Sie nach einem glViewport-Aufruf eine neue Projektionsmatrix berechnen.
quelle
Zum ersten Bild:
Wir erstellen eine Projektionsmatrix. Beispielsweise werden folgende Parameter verwendet: Left1, Right1, Bottom1, Top1, Near1, Far1. Hier ist Aspect_Ratio_1A = (Rechts1 - Links1) / (Oben1 - Unten1);
Dann führen wir eine Ansichtsport-Transformation durch. Die verwendeten Parameter sind beispielsweise: Breite1, Höhe1. (Der Einfachheit halber erwähne ich keine Verschiebungsparameter). Hier ist Aspect_Ratio_1B = Width1 / Height1;
Für das zweite Bild:
Wir erstellen dieselbe Projektionsmatrix mit denselben Parametern wie zuvor. Also: Aspect_Ratio_2A = Aspect_Ratio_1A;
Diesmal hat die Ansichtsport-Transformation verschiedene Parameter: Breite2 und Höhe2. Hier ist Aspect_Ratio_2B = Breite2 / Höhe2.
Wir stellen fest, dass Aspect_Ratio_1B und Aspect_Ratio_2B unterschiedlich sind. Insbesondere sind sie:
Aspect_Ratio_1B = 2560/1600 = 1,6 Aspect_Ratio_2B = 2560/1200 = 2,13
Wenn wir also zusammenfassen, was wir für den zweiten Fall tun, ist:
Wir projizieren das Bild mit Aspect_Ratio_2A auf eine Ebene und skalieren es auf Aspect_Ratio_2B, bevor wir es dem Benutzer zeigen. Andere Benutzer bitten uns, unsere Projektionsmatrix so zu korrigieren, dass Aspect_Ratio_2A = Aspect_Ratio_2B.
Wir können auch Roberts Kommentare ein paar Mal lesen, um ein besseres Verständnis zu haben.
Ich kann auch nicht zustimmen, dass das rote Quad im zweiten Bild eine Größe von 200 x 200 Pixel hat, wenn es auf dem Bildschirm gezeichnet wird. Da wir wissen, dass ein Pixel ein Quadrat ist, benötigt die längere Seite mehr Pixel, um sicher gezeichnet zu werden, wenn das Quad eine der Seiten länger als die andere hat. Ich persönlich weiß nicht, was Protokollierung ist, aber möglicherweise gibt sie keine Bildschirmpixelgröße zurück.
quelle