Como impedir que a viewport se estique / distorça?

13

Basicamente, quero saber como remover a distorção ou o alongamento da imagem renderizada quando o tamanho da janela de exibição / janela mudar.

As imagens a seguir exemplificam a distorção / alongamento de que estou falando:

Imagem original (janela quadrada)

Sem distorção

Imagem distorcida / esticada (janela retangular)

Com distorção

Idealmente, a segunda imagem deve exibir a esfera sem o alongamento horizontal e exporia mais da cena ao usuário para explicar o tamanho maior da janela.

Como isso pode ser feito?

Estou trabalhando com o OpenGL para renderizar a imagem e utilizo a projeção em perspectiva através das chamadas:

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

A proporção width/heightestá de acordo com todos os documentos / tutoriais que encontrei, por isso não espero que esteja incorreta. No entanto, minha suspeita é que isso esteja afetando o problema do alongamento.


Depois de pensar

Honestamente, ao pensar mais sobre o assunto, levei a acreditar que a solução envolve uma relação diretamente proporcional entre o ângulo fovy (campo de visão na direção y) e a proporção da imagem.

Projeção em perspectiva

Usando a imagem acima como referência, se a largura aumentar (causando um alongamento horizontal), parece muito plausível que o ângulo do fovy precise aumentar para causar um alongamento vertical que 'conserte' a proporcionalidade da imagem renderizada.

Da mesma forma, uma diminuição na largura requer uma diminuição no ângulo do fovy.

Atualizar:

Então, depois de investigar isso mais adiante, decidi mudar a maneira como configurei o perfil de visualização assim:

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

E minhas expectativas estavam corretas, o que resolveu a questão da proporcionalidade. No entanto, não alcança os resultados desejados. Quando a largura da janela aumenta, a imagem renderizada fica menor (mas a esfera é de fato circular). Em vez disso, a esfera não deve mudar de tamanho; somente a quantidade de cena exibida deve mudar.

Nicholas Miller
fonte

Respostas:

14

De fato, a pergunta original é descartada da solução.

Código original

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

Código Fixo

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

O problema era que window.widthe window.heightsão números inteiros, o que fez com que a proporção aparecesse como resultado de uma divisão inteira.

A conversão de uma das dimensões em um flutuador faz com que o resultado use a divisão de ponto flutuante.

Como a proporção agora está correta, não há mais alongamentos, como visto na postagem original.

EDIT: O código na postagem original (e a resposta) é simplesmente pseudo-código para as chamadas para a GPU; o programa atual usado para gerar as imagens acima é escrito em Java. Para aqueles que não trabalham com Java, não pesquisei para ver se a divisão de número inteiro / ponto flutuante é implementada da mesma maneira. Independentemente disso, a solução é garantir que a proporção seja realmente computada corretamente.

Nicholas Miller
fonte