OpenGL: сбит с толку настройками функции unproject

#c #opengl #cursor #transform #raycasting

Вопрос:

Мне нужно внедрить радиовещание. Для этого мне нужно преобразовать курсор мыши в мировое пространство. Для этого я использую функцию unproject. Мне нужно сначала найти точку на ближней плоскости, затем на дальней плоскости. После этого из последнего вычитаем первое, и мы получим луч. Но я не понимаю, как правильно установить winZ. Потому что в некоторых реализациях я вижу два способа: winZ = 0 (ближняя плоскость), winZ = 1 (дальняя плоскость) или winZ = -1 (ближняя плоскость), winZ = 1 (дальняя плоскость). В чем разница в этих диапазонах?

Ответ №1:

Если это действительно пространство Windows z , то есть только [0,1] диапазон. Обратите внимание, что 0 не обязательно означает ближнюю плоскость, а один-дальнюю плоскость. Можно настроить матрицу проекции, в которой ближнее будет равно 1, а дальнее-0 (обратный z, который в сочетании с [0,1] условием z-клипа, как описано ниже, имеет некоторые преимущества в точности).

Также не это glDepthRange может дополнительно изменить, к каким значениям (внутри [0,1] ) будут сопоставлены эти две плоскости.

Чтобы понять непроектную операцию, вам сначала нужно понять различные координатные пространства. Как правило, в API визуализации вам приходится иметь дело с этими 3 пространствами в конце цепочки преобразований:

  1. пространство клипов: это то, в чем находится вывод вершинного шейдера, и где происходит фактическое обрезание, по крайней мере, на концептуальном уровне. Это пространство по-прежнему однородно с произвольным значением w координаты.
  2. нормализованные координаты устройства (NDC). Это то, что вы получаете после разделения перспективы по w координате пространства отсечения (после применения отсечения, что w<=0 полностью устранит случаи).
  3. оконное пространство. 2D xy -часть-это фактические координаты пикселей внутри вашего выходного окна (или цели рендеринга), а преобразование из NDC xy в пространство окна xy определяется настройками окна просмотра. z Координата-это значение, которое войдет в тест глубины, и буфер глубины, он находится в диапазоне [0,1] или некотором поддиапазоне этого (управляется через glDepthRange в GL).

Других пространств перед этим в этот список, как и модель/объект, космос, мировое пространство, глаз/зрения пространства, и полностью зависит от вас и не касаются напрямую ГПУ на всех (наследие фиксированными функциями ГЛ не было наплевать на глаз места для освещения и тумана, но в настоящее время, реализуя это все ваша работа, и вы можете использовать все пространство вы считаете нужным).

Установив пробелы, следующая важная вещь здесь-это объем просмотра. Это объем пространства, которое фактически будет отображено на ваш видовой экран, и это 3D-объем, ограниченный шестью плоскостями: левой, правой, нижней, верхней, ближней и дальней.

Тем не менее, фактический объем просмотра настраивается чисто условно в различных API-интерфейсах визуализации (и фактическом оборудовании GPU).

Поскольку вы отметили этот вопрос «OpenGL», я собираюсь начать с соглашения GL по умолчанию:

  • Стандартное соглашение GL заключается в том, что объем представления является полностью симметричным [-1,1] кубом в NDC. На самом деле это означает, что условие клипа в пространстве клипов таково -w <= x,y,z <= w .
  • Direct3D использует другое соглашение: они используют [-1,1] в NDC для x и y, как и GL, но [0,1] для измерения z. Это также означает, что преобразование диапазона глубины в пространство окна во многих случаях может быть идентичным (вам редко нужно ограничивать его поддиапазоном [0,1]). Это соглашение имеет некоторые численные преимущества, поскольку соглашение GL о перемещении [-1,1] диапазона в [0,1] пространство для окон позволит снизить точность вокруг нулевой точки (NDC).
  • Современный GL, начиная с GL 4.5, опционально позволяет переключаться на [0,1] соглашение для z через glClipControl . Вулкан также поддерживает оба соглашения, но использует [0,1] их по умолчанию.

Не существует функции «непроецирования», но концепция «непроецирования» точки означает вычисление этих преобразований в обратном порядке, переход от пространства окна обратно к некоторому пространству перед пространством клипа, отменяя матрицу проектирования. Для реализации непроектной функции вам необходимо знать, какие соглашения были использованы.

Потому что в некоторых реализациях я вижу два способа: winZ = 0 (ближняя плоскость), winZ = 1 (дальняя плоскость) или winZ = -1 (ближняя плоскость), winZ = 1 (дальняя плоскость). В чем разница в этих диапазонах?

Возможно, они принимают не пространство окна Z, а непосредственно NDC z. Возможно, параметры просто названы неправильно или неправильно. Возможно, некоторые из существующих реализаций просто совершенно неверны.

Комментарии:

1. Я все еще не понимаю, почему 0-ближняя плоскость, а 1-дальняя плоскость. На каких расчетах он основан?

2. Положение NDC и пространства отсечения плоскостей отсечения определяется просто по чистой договоренности . Нет никакого расчета, который приводил бы к этим значениям. Они определены спецификацией he. Вы можете просто выбрать между 2 соглашениями z в современном GL, как я описал. Для оконного пространства [0,1] диапазон также является условным.