Как я могу предотвратить растяжение / искажение области просмотра?

13

По сути, я хочу знать, как можно устранить искажение или растяжение визуализированного изображения при изменении размера области просмотра / окна.

Следующие изображения иллюстрируют искажение / растяжение, о котором я говорю:

Исходное изображение (квадратное окно)

Без искажений

Искаженное / растянутое изображение (прямоугольное окно)

С искажением

В идеале, второе изображение должно отображать сферу без горизонтального растяжения и показывать пользователю большую часть сцены, чтобы учитывать больший размер окна.

Как это может быть сделано?

Я работаю с OpenGL для рендеринга изображения, и я использую перспективную проекцию через вызовы:

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

Соотношение сторон width/heightсоответствует всем документам / учебникам, с которыми я сталкивался, поэтому я не ожидаю, что оно будет неправильным. Тем не менее, я подозреваю, что это влияет на проблему растяжения.


После мысли

Честно говоря, когда я больше размышляю над этой проблемой, я поверил, что решение предполагает прямо пропорциональную зависимость между углом обзора (полем зрения в направлении y) и соотношением сторон.

Перспективная проекция

Используя вышеупомянутое изображение в качестве эталона, если ширина увеличивается (вызывая горизонтальное растяжение), кажется весьма вероятным, что увеличенный угол должен увеличиться, чтобы вызвать вертикальное растяжение, которое «фиксирует» пропорциональность визуализированного изображения.

Аналогичным образом, уменьшение ширины требует уменьшения угла обзора.

Обновить:

Итак, после изучения этого вопроса, я решил изменить способ настройки усечения просмотра следующим образом:

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

И мои ожидания оправдались, что решило проблему соразмерности. Тем не менее, он не достигает желаемых результатов. Когда ширина окна увеличивается, визуализированное изображение становится меньше (но сфера действительно круглая). Вместо этого сфера не должна изменять размер вообще; должно изменяться только количество отображаемой сцены.

Николас Миллер
источник

Ответы:

14

На самом деле, исходный вопрос - 1 отрешенный от решения.

Оригинальный код

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

Фиксированный код

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

Проблема заключалась в том, что window.widthи window.heightцелых числа, которые вызвали коэффициент пропорциональности , чтобы быть результатом целочисленного деления.

Преобразование одного из измерений в число с плавающей точкой приводит к тому, что в результате вместо этого используется разделение с плавающей точкой.

Поскольку соотношение сторон теперь правильное, растяжения больше нет, как видно из исходного поста.

РЕДАКТИРОВАТЬ: код в исходном посте (и ответ) просто псевдокод для звонков в GPU; Фактическая программа, используемая для вывода изображений выше, написана на Java. Для тех, кто не работает с Java, я не исследовал, чтобы увидеть, реализовано ли деление целых чисел / с плавающей точкой таким же образом. Независимо от этого, решение состоит в том, чтобы убедиться, что соотношение сторон действительно правильно вычислено.

Николас Миллер
источник