OpenGL - gluPerspective / glFrustum - проблемы zNear & zFar - PullRequest
4 голосов
/ 07 сентября 2011

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

Изначально я не обращал внимания на параметр zNeargluPerspective (), пока я не работал над планетарными объектами.Поскольку моя шкала указана в световых единицах, я вскоре понял, что из-за того, что zNear равен 1.0f, я не смогу видеть такие объекты.После экспериментов я пришел к следующим цифрам:

#define POV 45
#define zNear 0.0000001f
#define zFar 100000000.0f
gluPerspective (POV, WinWidth/WinHeight, zNear ,zFar);

Это работает исключительно хорошо, потому что я смог совершить кругосветное путешествие по моей солнечной системе (позиция 0,0,0) и подойти близко к планетам, которые выглядят великолепно освещенными.и текстура сопоставлена.Однако другие системы (не в положении 0,0,0) проходить намного сложнее, потому что объекты удалялись от камеры необычными способами.

Однако я заметил, что странные визуальные глюки начали происходить при путешествии по вселенной.Объекты позади меня будут «оборачиваться» и показываться вперед, если я поверну на 180 градусов в направлении Y, они также появятся на своем первоначальном месте.Таким образом, при искривлении в пространстве большинство звезд правильно параллаксируются, но некоторые появляются и движутся в противоположном направлении (что, по меньшей мере, мешает).

Изменение значения zNear на 0.1f немедленно исправляет ВСЕ эти глюки.(но также не разрешит объекты солнечной системы).Так что я застрял.Я также пытался работать с glFrustum, и он дает точно такие же результаты.

Я использую следующее для просмотра мира:

glTranslatef(pos_x, pos_y, pos_z);

С соответствующим кодом камеры для ориентации по мере необходимости.Даже отключение функции камеры ничего не меняет.Я даже попробовал gluLookAt (), и снова он дает те же результаты.

Есть ли у gluPerspective () ограничения при использовании экстремальных значений zNear / zFar?Я пытался уменьшить диапазон, но безрезультатно.Я даже изменил свои мировые единицы с световых лет на километры, масштабируя все и используя большее значение zNear - ничего.ПОМОГИТЕ!

Ответы [ 3 ]

5 голосов
/ 07 сентября 2011

Проблема в том, что вы хотите решить слишком много одновременно.Вы хотите видеть вещи в масштабе Солнечной системы, в то же время имея полугалактический масштаб.Это просто невозможно.Не с рендерером в реальном времени.

Существует только так много точности с плавающей точкой.А с zNear, находящимся на невероятно близком расстоянии, вы фактически уничтожили свой буфер глубины для всего, что находится на расстоянии более 0,0001 от вашей камеры.

Что вам нужно сделать, это нарисовать вещина основе расстояния.Ближайшие объекты (в масштабе солнечной системы) рисуются одной перспективной матрицей с использованием одного диапазона глубины (скажем, от 0 до 0,8).Затем более удаленные объекты рисуются с другой перспективной матрицей и другим диапазоном глубины (от 0,8 до 1).Это действительно единственный способ заставить эту работу работать.

Кроме того, вам может понадобиться вычислить матрицы для объектов на ЦП в математике с двойной точностью, а затем преобразовать их обратно в одинарную точность для OpenGL.использовать.

3 голосов
/ 11 сентября 2011

OpenGL не должен рисовать что-либо дальше от камеры, чем zFar, или ближе к камере, чем zNear.

Но для промежуточных вещей OpenGL вычисляет значение глубины, которое хранится в буфере глубины, который ониспользуется, чтобы сказать, блокирует ли один объект другой.К сожалению, буфер глубины имеет ограниченную точность (обычно 16 или 24 бита), и в соответствии с this , примерно log2 (zFar / zNear) биты точности теряются.Таким образом, отношение zFar / zNear, равное 10 ^ 15 (потеря ~ 50 бит), может вызвать проблемы.Один из вариантов - немного увеличить zNear (если вы можете).В противном случае вам нужно изучить разделенные буферы глубины или логарифмические буферы глубины

1 голос
/ 08 сентября 2011

Николь Болас уже рассказала вам одну часть истории.Во-вторых, вы должны начать думать о структурированном способе хранения координат: сохраняйте положение каждого объекта относительно объекта, который доминирует над ним гравитационно, и используйте соответствующие единицы для них.,Расстояния между звездами измеряются в световых годах.Звезды вращаются вокруг планет.Расстояния внутри звездной системы измеряются от световых минут до световых часов.Планеты вращаются вокруг лун.Расстояния в планетарной системе измеряются в световых секундах.

Чтобы отобразить такие масштабы, вам необходимо выполнить рендеринг за несколько проходов.Объекты с их масштабами образуют дерево.Сначала вы сортируете ветви, чтобы закрыть, а затем сначала пройдете глубину дерева.Для каждого уровня ветвления вы используете соответствующие параметры проекции, так что ближние → дальние плоскости отсечения плотно прилегают к визуализируемым объектам.После рендеринга каждого уровня очистите буфер глубины.

...