¿Cómo puedo evitar que la ventana se estire / distorsione?

13

Básicamente, quiero saber cómo puedo eliminar la distorsión o el estiramiento de la imagen renderizada cuando cambia el tamaño de la ventana / ventana.

Las siguientes imágenes ejemplifican la distorsión / estiramiento del que estoy hablando:

Imagen original (ventana cuadrada)

Sin distorsión

Imagen distorsionada / estirada (ventana rectangular)

Con distorsión

Idealmente, la segunda imagen debería mostrar la esfera sin el estiramiento horizontal, y expondría más de la escena al usuario para dar cuenta del mayor tamaño de la ventana.

¿Cómo se puede hacer esto?

Estoy trabajando con OpenGL para renderizar la imagen, y uso la proyección en perspectiva a través de las llamadas:

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

La relación de aspecto width/heightestá de acuerdo con todos los documentos / tutoriales que he encontrado, por lo que no espero que sea incorrecta. Sin embargo, mi sospecha es que está afectando el problema del estiramiento.


Después de pensar

Honestamente, al pensar más en el tema, me hizo creer que la solución implica una relación directamente proporcional entre el ángulo fovy (campo de visión en la dirección y) y la relación de aspecto.

Proyección Perspectiva

Usando la imagen de arriba como referencia, si el ancho aumenta (causando un estiramiento horizontal), parece muy plausible que el ángulo fovy debe aumentar para causar un estiramiento vertical que 'arregle' la proporcionalidad de la imagen renderizada.

Del mismo modo, una disminución en el ancho requiere una disminución en el ángulo fovy.

Actualizar:

Entonces, después de investigar esto más a fondo, he decidido cambiar la forma en que configuré el frustum de visualización de esta manera:

gluPerspective(60 * (float)window.width/window.height, (float)window.width/window.height, 0.01f, 100.0f)

Y mis expectativas eran correctas, eso resolvió el problema de proporcionalidad. Sin embargo, no logra mis resultados deseados. Cuando el ancho de la ventana aumenta, la imagen renderizada se vuelve más pequeña (pero la esfera es realmente circular). En cambio, la esfera no debería cambiar de tamaño en absoluto; solo la cantidad de escena que se muestra debe cambiar.

Nicholas Miller
fuente

Respuestas:

14

De hecho, la pregunta original está a 1 distancia de la solución.

Código original

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, window.width/window.height, 0.01f, 100.0f)

Código fijo

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60, (float)window.width/window.height, 0.01f, 100.0f)

El problema era eso window.widthy window.heightson enteros, lo que causó que la relación de aspecto sea el resultado de una división entera.

La conversión de una de las dimensiones a un flotante hace que el resultado utilice la división de punto flotante.

Debido a que la relación de aspecto ahora es correcta, no hay más estiramiento como se ve en la publicación original.

EDITAR: El código en la publicación original (y la respuesta) es simplemente un seudocódigo para las llamadas a la GPU; El programa real utilizado para generar las imágenes anteriores está escrito en Java. Para aquellos que no trabajan con Java, no he investigado para ver si la división de entero / punto flotante se implementa de la misma manera. En cualquier caso, la solución consiste en asegurarse de que la relación de aspecto se calcule correctamente.

Nicholas Miller
fuente