Espero que alguien pueda ayudarme a comprender el GLViewport y lo que sucede cuando cambiamos el tamaño
Esto ilustrará mi confusión ...
Entonces, aquí tengo un quad atrapado en el medio de la pantalla. Si mi GLViewport coincide con el ancho y la altura del dispositivo, obtengo lo que está en la primera imagen (izquierda). Exactamente lo que esperaría.
- Resolución del dispositivo, 2560 x 1600
- Resolución de la ventana de visualización 2560 x 1600
- Tamaño cuádruple 200 x 200 (¡¡¡Nota, la imagen de arriba no está a escala !!! :-))
- Forma cuádruple, aparece como cuadrado
Ahora, para la segunda foto (mano derecha) ...
- Resolución del dispositivo, 2560 x 1600
- Resolución de la vista 2560 x 1200 (y centrada verticalmente)
- Tamaño cuádruple (200, 200)
- Forma cuádruple, aparece como rectángulo
Mi pregunta es, ¿por qué el quad se muestra ahora como un rectángulo y no como un cuadrado? He confirmado al iniciar sesión que mi quad es de 200 x 200 pixeles, ¿seguramente el tamaño de los píxeles físicos se mantiene igual? No pueden cambiar. Entonces, ¿qué está pasando aquí?
Pensé (claramente incorrectamente) que cuando escalé la ventana gráfica, literalmente solo cortó píxeles.
Agradecería si alguien pudiera explicar cómo funciona esto.
Editar
Actualmente, estoy configurando mi ventana gráfica de esta manera:
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 y offsetY son solo para que cuando haya buzones, la ventana se centre.
fuente
glScissor
lugar deglViewport
, simplemente recortará los píxeles sin cambiar el lugar donde se representa.glViewport
se comporta más como cambiar el tamaño de la imagen original, en lugar de recortarla; Es por eso que golpea tu caja.Respuestas:
Para comprender lo que está sucediendo, debe comprender la canalización de representación:
Su geometría (el quad) se define inicialmente en el espacio mundial, piense en esto como un sistema de coordenadas global. Dentro del sombreador de vértices, estos se transforman en coordenadas de dispositivo normalizadas (NDC), un sistema de coordenadas virtual definido de modo que todo, desde -1 a 1, se dibujará en la pantalla. Tenga en cuenta que NDC varía de -1 a 1 en X e Y, y es totalmente independiente de la relación de aspecto y la resolución de los dispositivos. Esta transformación del espacio mundial a NDC se realiza mediante el modelo, la vista y la matriz de proyección (en una forma simple, ¡solo una matriz para todo o incluso la geometría se definió en NDC para empezar!).
La unidad de rasterización necesita saber dónde y qué tan grande debe rasterizar y esto es lo que define con la llamada glViewport: dónde comenzar son los dos primeros parámetros, el tamaño son los segundos dos. El hardware luego convertirá de NDC a coordenadas de píxel mediante una escala y un desplazamiento simples, y esto es lo que ve en su ejemplo: una escala en el eje Y.
Por lo tanto, para asegurarse de que su quad se procese en la relación de aspecto correcta, también debe ajustar la matriz de proyección para incluir la relación de aspecto esperada de la llamada glViewport.
fuente
glFrustum
, que enumera la matriz exacta construida por estas funciones. Otra matriz de proyección común que puede desear fue creada porglOrtho
. Si bien todos estos comandos son obsoletos, los documentos en ellos son una excelente fuente de algunas matemáticas derivadas previamente.En su llamada a glViewport, está especificando menos píxeles de ancho y alto. Su matriz de proyección se define en términos de píxeles. Es por eso que tendrá que calcular una nueva matriz de proyección después de una llamada a glViewport.
fuente
Para la primera foto:
Estamos creando una matriz de proyección. Por ejemplo, los parámetros utilizados son: Left1, Right1, Bottom1, Top1, Near1, Far1. Aquí, Aspect_Ratio_1A = (Derecha1 - Izquierda1) / (Superior1 - Inferior1);
Entonces estamos haciendo una transformación del puerto de vista. Por ejemplo, los parámetros utilizados son: Ancho1, Altura1. (No estoy mencionando los parámetros de cambio por simplicidad). Aquí, Aspect_Ratio_1B = Ancho1 / Altura1;
Para la segunda foto:
Estamos creando la misma matriz de proyección con los mismos parámetros que antes. Entonces: Aspect_Ratio_2A = Aspect_Ratio_1A;
Esta vez, la transformación del puerto de vista tiene diferentes parámetros: Ancho2 y Altura2. Aquí, Aspect_Ratio_2B = Width2 / Height2.
Observamos que Aspect_Ratio_1B y Aspect_Ratio_2B son diferentes. Específicamente son:
Aspect_Ratio_1B = 2560/1600 = 1.6 Aspect_Ratio_2B = 2560/1200 = 2.13
Entonces, si resumimos lo que estamos haciendo para el segundo caso es:
Estamos proyectando la imagen en un plano con Aspect_Ratio_2A y antes de mostrársela al usuario, la estamos ampliando a Aspect_Ratio_2B. Otros usuarios nos piden que corrijamos nuestra matriz de proyección de tal manera que Aspect_Ratio_2A = Aspect_Ratio_2B.
También podemos leer los comentarios de Robert un par de veces para tener una mejor comprensión.
Además, no puedo aceptar que el quad rojo en la segunda imagen tenga un tamaño de 200 por 200 píxeles cuando se dibuja en la pantalla. Como sabemos, un píxel es un cuadrado, si el quad tiene uno de los lados más largo que el otro, el lado más largo requiere más píxeles para dibujar con seguridad. Yo, personalmente, no sé qué es el registro, pero es posible que no devuelva el tamaño de píxel de la pantalla.
fuente