Confusione su GLViewport


9

Spero che qualcuno possa aiutarmi a capire GLViewport e cosa succede quando lo ridimensioniamo

Questo illustrerà la mia confusione ....

inserisci qui la descrizione dell'immagine

Quindi, qui ho un quad bloccato nel mezzo dello schermo. Se il mio GLViewport corrisponde alla larghezza e all'altezza del dispositivo, ottengo ciò che è nella prima immagine (a sinistra). Esattamente quello che mi aspetterei.

  • Risoluzione del dispositivo, 2560 x 1600
  • Risoluzione della finestra 2560 x 1600
  • Dimensione quad 200 x 200 (Nota, l'immagine sopra non è in scala !!! :-))
  • Forma quadrata, appare come quadrato

Ora, per la seconda immagine (mano destra) ...

  • Risoluzione del dispositivo, 2560 x 1600
  • Risoluzione della finestra 2560 x 1200 (e centrata verticalmente)
  • Dimensione quadrupla (200, 200)
  • Forma quadrata, appare come rettangolo

La mia domanda è: perché il quad ora viene visualizzato come un rettangolo e non un quadrato? Ho confermato registrando che il mio quad è di 200 x 200 pixel - sicuramente la dimensione dei pixel fisici rimane la stessa? Non possono cambiare. Quindi cosa sta succedendo qui?

Ho pensato (chiaramente in modo errato) che quando ho ridimensionato il viewport, il Mediterraneo ha appena tagliato i pixel.

Gradirei se qualcuno potesse spiegare come funziona.

modificare

Attualmente, sto impostando il mio viewport in questo modo:

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 e offsetY sono solo in modo che quando ci sono cassette delle lettere, la finestra è centrata.


Hai cambiato la tua matrice di proiezione e la finestra quando hai cambiato da 1600 a 1200 pixel verticali? (è necessario)
bcrist

Ciao @bcrist, vedi la mia modifica per mostrare come sto impostando il mio viewport. Tutto ciò che disegno con un numero uguale di pixel (diciamo 50 x 50 o 100 x 100) è disegnato "allungato" - Qualche idea ?!
BungleBonce,

A proposito, se lo usi glScissorinvece di glViewport, semplicemente ritaglierà i pixel senza cambiare dove viene eseguito il rendering di qualcosa. glViewportsi comporta più come ridimensionare l'immagine originale, piuttosto che ritagliarla; ecco perché schiaccia la tua scatola.
Nathan Reed,

Grazie @NathanReed, sono ancora molto confuso. Quello che ho è questo: un viewport che occupa l'intero schermo. Una scatola a forbice che viene ridimensionata per mantenere il rapporto del dispositivo originale (in modo che io possa visualizzare il gioco nella scatola a forbice e disegnare oggetti al di fuori di questo per il riempimento), tutto sembra allungato (verticalmente), quindi più lungo di quanto sia largo. Che cosa sto facendo di sbagliato?
BungleBonce,

Hmm. La forbice non dovrebbe cambiare nulla riguardo alle proporzioni o al ridimensionamento dell'immagine. Se sembra corretto senza la forbice, abilitare semplicemente la forbice - mantenendo la stessa vista, matrice di proiezione, ecc. - Dovrebbe semplicemente ritagliare l'immagine.
Nathan Reed,

Risposte:


11

Per capire cosa sta succedendo, devi capire la pipeline di rendering:

La tua geometria (il quad) è inizialmente definita nello spazio mondiale, pensa a questo come a un sistema di coordinate globale. All'interno del vertex shader, questi vengono trasformati in coordinate del dispositivo normalizzate (NDC), un sistema di coordinate virtuale definito in modo tale che tutto da -1 a 1 verrà disegnato sullo schermo. Si noti che NDC varia da -1 a 1 in X e Y ed è totalmente indipendente dalle proporzioni e dalla risoluzione dei dispositivi. Questa trasformazione dallo spazio del mondo a NDC è fatta dal modello, dalla vista e dalla matrice di proiezione (in una forma semplice, per cominciare, è stata definita una sola matrice per tutto o la geometria in NDC!).

L'unità di rasterizzazione deve sapere dove e quanto deve essere raster e questo è ciò che si definisce con la chiamata glViewport: da dove iniziare sono i primi due parametri, le dimensioni sono i secondi due. L'hardware quindi convertirà da NDC a coordinate pixel con una semplice scala e spostamento - e questo è ciò che vedi nel tuo esempio: una scala nell'asse Y.

Quindi, per essere sicuri che il tuo quad sia reso nelle proporzioni corrette, devi anche regolare la matrice di proiezione per includere le proporzioni previste della chiamata glViewport.


Ciao @Robert, molte grazie per questo, ho qualche difficoltà a cercare di implementarlo, potresti per favore dare un esempio di impostazione della matrice di proiezione nella tua risposta? Grazie!
BungleBonce,

4
Ciao user22241, non ci sono comandi OpenGL per farlo, devi definire la matrice da solo (un array di float 4 per 4) e fornirli al tuo shader di vertice come uniforme. Di quale proiezione hai bisogno (prospettiva, ortogonale) dipende da cosa vuoi fare. Se i concetti matematici delle proiezioni 3D sono nuovi per te, potresti voler consultare i tutorial di OpenGL che insegnano il profilo principale che funziona allo stesso modo di OpenGL ES in questo senso.
Robert,

@BungleBonce mentre non ci sono comandi OpenGL per questo nel profilo principale, puoi sempre guardare la documentazione di comandi obsoleti come glFrustum, che elenca la matrice esatta che è costruita da queste funzioni. È stata creata un'altra matrice di proiezione comune che potresti desiderare glOrtho. Mentre tutti questi comandi sono obsoleti, i documenti su di essi sono un'ottima fonte di alcuni calcoli pre-derivati.
Ruslan,

0

Nella tua chiamata a glViewport stai specificando meno pixel in larghezza e altezza. La tua matrice di proiezione è definita in termini di pixel. Ecco perché dovrai calcolare una nuova matrice di proiezione dopo una chiamata glViewport.


Ciao @bogglez, grazie per la tua risposta. Ho modificato la mia domanda per mostrare (alla fine) quale codice sto usando per il mio viewport. Tutto quello che sto usando è glViewPort - è questo modo errato di farlo? Per favore, potresti mostrare un esempio di cosa intendi nella tua risposta? Grazie.
BungleBonce,

Leggi questo: songho.ca/opengl/gl_projectionmatrix.html Per il 2D vuoi una matrice di proiezione ortogonale, per il 3D probabilmente vuoi una matrice prospettica. Se usi il moderno OpenGL, fornirai una matrice a uno shader. Se si utilizza OpenGL obsoleto con la pipeline grafica fissa, verranno utilizzate funzioni come glLoadMatrix, glFrustum, ecc. Per calcolare la matrice di proiezione. La libreria di utilità GLU ha una funzione gluPerspective ( opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml ) e gluOrtho2D ( opengl.org/sdk/docs/man2/xhtml/gluOrtho2D.xml ) per aiutarti.
Bogglez,

0

Per la prima foto:

  1. Stiamo creando una matrice di proiezione. Ad esempio, i parametri utilizzati sono: Left1, Right1, Bottom1, Top1, Near1, Far1. Qui, Aspect_Ratio_1A = (Right1 - Left1) / (Top1 - Bottom1);

  2. Quindi stiamo effettuando una trasformazione della porta di visualizzazione. Ad esempio, i parametri utilizzati sono: Larghezza1, Altezza1. (Non sto menzionando i parametri di spostamento per semplicità). Qui, Aspect_Ratio_1B = Larghezza1 / Altezza1;

Per la seconda foto:

  1. Stiamo creando la stessa matrice di proiezione con gli stessi parametri di prima. Quindi: Aspect_Ratio_2A = Aspect_Ratio_1A;

  2. Questa volta la trasformazione della porta di visualizzazione presenta parametri diversi: Larghezza2 e Altezza2. Qui, Aspect_Ratio_2B = Larghezza2 / Altezza2.

Notiamo che Aspect_Ratio_1B e Aspect_Ratio_2B sono diversi. Nello specifico sono:

Aspect_Ratio_1B = 2560/1600 = 1.6 Aspect_Ratio_2B = 2560/1200 = 2.13

Quindi, se riassumiamo ciò che stiamo facendo per il secondo caso è:

Stiamo proiettando l'immagine su un piano con Aspect_Ratio_2A e prima di mostrarla all'utente, la stiamo ridimensionando su Aspect_Ratio_2B. Altri utenti ci chiedono di correggere la nostra matrice di proiezione in modo tale che Aspect_Ratio_2A = Aspect_Ratio_2B.

Possiamo anche leggere i commenti di Robert un paio di volte per capire meglio.

Inoltre, non posso essere d'accordo sul fatto che il quad rosso nella seconda immagine abbia una dimensione di 200 per 200 pixel quando disegnato sullo schermo. Poiché sappiamo che un pixel è un quadrato, se il quadrante ha uno dei lati più lungo dell'altro, il lato più lungo impiega più pixel per essere disegnato sicuramente. Personalmente, non so cosa sia la registrazione, ma potrebbe non restituire la dimensione dei pixel dello schermo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.