Jak mogę zapobiec rozciągnięciu / zniekształceniu widoku?

13

Zasadniczo chcę wiedzieć, jak mogę usunąć zniekształcenie lub rozciągnięcie renderowanego obrazu, gdy zmienia się rozmiar okna / okna.

Poniższe obrazy ilustrują zniekształcenie / rozciąganie, o którym mówię:

Oryginalny obraz (kwadratowe okno)

Bez zniekształceń

Zniekształcony / rozciągnięty obraz (okno prostokątne)

Z dystorsją

Idealnie byłoby, gdyby drugi obraz wyświetlał kulę bez poziomego rozciągania i odsłoniłby więcej sceny dla użytkownika, aby uwzględnić większy rozmiar okna.

Jak można to zrobić?

Pracuję z OpenGL do renderowania obrazu i korzystam z projekcji perspektywicznej za pomocą wywołań:

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

Proporcje obrazu width/heightsą zgodne ze wszystkimi dokumentami / samouczkami, które napotkałem, więc nie oczekuję, że będą one niepoprawne. Podejrzewam jednak, że wpływa to na problem rozciągania.


Po namyśle

Szczerze mówiąc, gdy bardziej zastanawiam się nad tym zagadnieniem, doprowadziłem do przekonania, że ​​rozwiązanie obejmuje bezpośrednio proporcjonalną zależność między ostrym kątem widzenia (pole widzenia w kierunku y) a współczynnikiem kształtu.

Rzut perspektywiczny

Używając powyższego obrazu jako odniesienia, jeśli szerokość rośnie (powodując rozciąganie w poziomie), wydaje się bardzo prawdopodobne, że kąt ostrzenia musi wzrosnąć, aby spowodować rozciągnięcie w pionie, które „naprawia” proporcjonalność renderowanego obrazu.

Podobnie zmniejszenie szerokości wymaga zmniejszenia kąta Fovy.

Aktualizacja:

Po dokładniejszym zbadaniu tego problemu zdecydowałem się zmienić sposób, w jaki skonfigurowałem widok podglądu w następujący sposób:

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

A moje oczekiwania były słuszne, co rozwiązało problem proporcjonalności. Jednak nie osiąga pożądanych rezultatów. Gdy szerokość okna wzrasta, renderowany obraz staje się mniejszy (ale kula rzeczywiście jest okrągła). Zamiast tego kula w ogóle nie powinna zmieniać rozmiaru; powinna się zmieniać tylko ilość wyświetlanej sceny.

Nicholas Miller
źródło

Odpowiedzi:

14

W rzeczywistości pierwotne pytanie jest odrzucone na 1 rozwiązanie.

Kod oryginalny

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

Naprawiono kod

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

Problem polegał na tym, że window.widthi window.heightsą liczbami całkowitymi, co spowodowało o współczynniku być wynikiem dzielenia liczby całkowitej.

Rzutowanie jednego z wymiarów na liczbę zmiennoprzecinkową powoduje, że zamiast tego wynik używa podziału zmiennoprzecinkowego.

Ponieważ proporcje są teraz prawidłowe, nie ma już rozciągania, jak widać w oryginalnym poście.

EDYCJA: Kod w pierwotnym poście (i odpowiedź) to po prostu pseudo-kod dla połączeń z GPU; rzeczywisty program używany do wyświetlania powyższych obrazów jest napisany w Javie. Dla tych, którzy nie pracują w Javie, nie badałem, czy podział na liczby całkowite / zmiennoprzecinkowe jest implementowany w ten sam sposób. Niezależnie od tego rozwiązanie polega na upewnieniu się, że współczynnik kształtu jest rzeczywiście poprawnie obliczony.

Nicholas Miller
źródło