OpenGL: cambio de tamaño de pantalla y glOrtho / glViewport


16

He investigado esta pregunta de varias fuentes y todavía no he encontrado una respuesta firme que diga "sí, eso es pensar correctamente" o "no, así es como se hace".

Estoy tratando de garantizar la independencia de la resolución con la representación de OpenGL. La forma en que creo que debería hacerlo es crear una proyección usando glOrtholo que quiera que sean las coordenadas del mundo. Por ejemplo, glOrtho(-50.0, 50.0, -50.0, 50.0, 1.0, -1.0). A continuación, configure la ventana gráfica a la resolución de la pantalla , es decir, - glViewport(0, 0, 800, 600). Finalmente, cada vez que se redimensione la ventana, realice una llamada glViewportcon la resolución de pantalla actualizada. Esto escalará tus figuras.

¿Es esta la forma correcta de garantizar que los modelos tengan la misma proporción de espacio de pantalla en diferentes resoluciones? ¿Debería usar una proyección igual a la resolución también? Encontré algunas respuestas que glOrthodeberían usar la resolución de su ventana, mientras que otras dijeron que debería / puede ser diferente.

Pensamientos?

Respuestas:


20

Lo que ha descrito es completamente adecuado y apropiado para proporcionar independencia de resolución. Cualquier cosa que dibujes siempre ocupará la misma proporción de tu ventana.

Sin embargo, si no hace nada más que esto, tendrá problemas de relación de aspecto . Por ejemplo, dados los números que escribió, si dibuja un círculo, se aplastará, más ancho que alto, porque su escala horizontal es 800 / (50 + 50) = 8 y su escala vertical es 600 / (50+ 50) = 6.

No puede haber ninguna solución automática a este problema ; Tendrás que elegir el resultado gráfico que deseas y considerar su efecto en el juego. Algunos ejemplos comunes:

  • En un juego 3D de proyección en perspectiva sin HUD, la solución simple habitual (disponible en OpenGL como parte de gluPerspective) es arreglar el campo de visión de la proyección en relación con la dimensión vertical . Esto significa que en un juego de este tipo, si cambia el tamaño de la ventana horizontalmente, verá más o menos la escena y la parte media de la imagen no cambiará en absoluto.

    La misma idea se puede aplicar a una vista 2D / 2.5D también.

    (Tenga en cuenta que esto le permite al jugador ampliar su campo de visión horizontalmente al hacer una ventana ancha pero no alta. Esto podría no ser deseado en un juego competitivo de varios jugadores).

  • Si tiene gráficos que llenan la ventana gráfica con una relación de aspecto fija (por ejemplo, un mapa 2D sin desplazamiento o un borde decorativo), o si no puede cambiar el diseño, debe hacer algo como tener barras negras en dos lados para llenar el espacio no utilizado.

    O puede hacer gráficos que tengan material de relleno temáticamente consistente alrededor de los bordes que pueden ser recortar para que se ajusten a la pantalla sin dañar el juego.

  • Si tiene un HUD encima de otros gráficos, puede decidir que cada elemento del HUD esté fijado a una parte de la ventana (arriba a la izquierda, centro inferior, etc.) y calcular sus coordenadas; el 'estiramiento' de variar las relaciones de aspecto se absorbe por el 'espacio en blanco' entre los elementos del HUD.

En cuanto a las matemáticas específicas de la cuestión, dado que usted está haciendo independencia de la resolución, todo lo que necesita para comenzar con la relación de aspecto es, un solo número: width / height. Por ejemplo, si la ventana es cuadrada será 1; si es 800 por 600 será 800/600 = 4/3 = 1.333̅.

Por ejemplo, suponga que desea que la proyección ortográfica que ha escrito gane espacio adicional en los lados izquierdo y derecho si se amplía la ventana. Puedes hacer eso así:

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

Esto garantiza que, para ventanas al menos tan anchas como altas, cualquier cosa que dibuje con coordenadas x e y dentro de -50 a 50 será visible.

Por otro lado, si la ventana es más estrecha que alta, se cortará el rango de -50 a 50. Digamos que desea asegurarse de que siempre esté visible (para que su contenido tenga su tamaño máximo si la ventana es cuadrada, pero de lo contrario es más pequeña); en ese caso, simplemente haces lo mismo con la altura en lugar del ancho.

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);

Tenga en cuenta que en el segundo caso dividimos en lugar de multiplicar. Esto es simplemente porque calculamos la relación de aspecto en width / heightlugar deheight / width ; tome el recíproco si le resulta más fácil de entender de esa manera.

Nuevamente, esta no es la única forma de administrar la relación de aspecto; Esta es una muy simple para asegurarse de que su contenido no sea aplastado ni cortado. Averigua qué quieres que suceda cuando tu ventana es ancha, alta o lo que sea; luego resuelve las matemáticas de la misma.


Gracias por la respuesta MUY perspicaz. Respondí mi pregunta más allá de lo suficiente.
Chris Henderson
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.