Является ли система координат OpenGL левой или правой?

87

Я пытаюсь понять систему координат OpenGL. Однако в некоторых руководствах говорится, что система координат по умолчанию - левосторонняя (см. Http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ), а в других - правша (см. Http: // www. .falloutsoftware.com / tutorials / gl / gl0.htm ). Что правильно? Я понимаю, что мы можем преобразовать одно в другое путем зеркалирования, но я хотел бы знать координаты по умолчанию.

341008
источник
Связанные programmers.stackexchange.com/a/88776/12693
Кос,
3
Разве это не полностью зависит от того, как вы пишете свои преобразования в шейдерах, и, следовательно, полностью зависит от вас?
jcoder
Всего два моих цента evl.uic.edu/ralph/508S98/coordinates.html , на нем есть несколько понятных изображений.
rraallvv 07
Не думаю, что вы подумали бы об обновлении принятого ответа?
Джонатан Ми

Ответы:

132

Здесь есть некоторая путаница.

введите описание изображения здесь

OpenGL прав в объектном и мировом пространстве.

Но в оконном пространстве (он же экранное пространство) мы внезапно оказываемся левшами .

Как это случилось ?

Способ перехода от правшей к левым - это отрицательная запись масштабирования по z в матрицах проекции glOrthoили glFrustum. Масштабирование z на -1 (оставляя x и y такими, какие они были) приводит к изменению управляемости системы координат.

Для glFrustum,

введите описание изображения здесь введите описание изображения здесь

дальний и близкий должны быть положительными, а дальний > ближний . Скажите far = 1000 и near = 1. Тогда C = - (1001) / (999) = -1,002.

Смотрите здесь для получения более подробной информации и диаграмм.

С орфографической точки зрения glOrtho генерирует такую ​​матрицу:

введите описание изображения здесь

Здесь left , right , bottom и top - это просто координаты для левой вертикальной , правой вертикальной , нижней горизонтальной , верхней горизонтальной плоскостей отсечения (соответственно) .

Однако ближняя и дальняя плоскости указываются по-разному . Рядом параметр определен как

  • Рядом: расстояние до ближайшей плоскости отсечения глубины. Это расстояние отрицательно, если самолет должен быть позади зрителя.

и далеко:

  • zFar Расстояние до дальней плоскости отсечения глубины. Это расстояние отрицательно, если самолет должен быть позади зрителя.

Вот типичный канонический объем просмотра

канонический

Поскольку множитель z равен (-2 / (далеко-близко)), знак минус эффективно масштабирует z на -1 . Это означает, что «z» поворачивается влево во время преобразования просмотра, без ведома большинства людей, поскольку они просто работают в OpenGL как «правосторонняя» система координат.

Итак, если вы позвоните

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

Тогда БЛИЖНИЙ САМОЛЕТ будет на 10 единиц впереди вас . Где ты? Почему в начале координат ось x находится справа от вас, ось Y находится на верхней части головы, а ваш нос направлен вниз по отрицательной оси z (это значение по умолчанию "По умолчанию камера расположена в начале координат , указывает вниз по отрицательной оси Z и имеет вектор вверх (0, 1, 0). " ). Таким образом, ближняя плоскость находится на z = -10. Дальний самолет находится на 10 единиц позади вас, на z = + 10 .

бобобобо
источник
1
"прямой вектор инвертируется в gluLookAt" - можете ли вы подтвердить, что это так? Не gluPerspective или glFrustum или glOrtho?
Кос,
1
Мы внезапно стали левшами из пространства клипов и далее, а не только из оконного пространства.
legends2k
3
+1 для всего ответа, -1 (подождите, скорее -2) для «Мы переходим от правшей к левшей, потому что прямой вектор инвертируется в стандартной реализации gluLookAt (), которая является функцией все используют для создания матрицы вида. Когда вы инвертируете прямой вектор, это приводит к изменению «руки» системы координат ». , это просто чушь ...
Кристиан Рау
2
... Отрицание прямого вектора в gluLookAtвычислении не имеет ничего общего с изменением направленности координатного пространства, это именно то, как вычисляется эта матрица (и на самом деле + z действительно "назад" в правом пространстве). gluLookAtне делает ничего, кроме вычисления обычного преобразования твердого тела (вращение + перенос) в правостороннем пространстве. Как вы уже отметили в своем ответе, именно матрицы проекции, используемые фиксированным конвейером функций (и обычно шейдерами тоже), выполняют фактическое изменение руки при отрицании z-компонента.
Кристиан Рау
2
@bobobobo Вы говорите, что если вы вычисляете матрицу представления, используя только функции вращения и трансляции (которые, я думаю, вы не обвиняете в изменении руки), вместо gluLookAtэтого не будет изменения основы, пока это gluLookAtпроисходит? Определенно нет (поскольку вы, вероятно, знаете, что не «все» используют gluLookAtдля вычисления матрицы представления), поскольку, как вы должны знать, gluLookAtне делает ничего, кроме набора вызовов поворота и перевода (даже если они замаскированы под изменение термина « высокого уровня» base " ) без каких-либо отражений.
Christian Rau
26

По умолчанию нормализованная координата устройства левосторонняя.

GlDepthRange по умолчанию [0, 1] (близко, далеко), что делает точку оси + z на экране, а с + x вправо и + y вверх это система для левшей.

Изменение диапазона глубины на [1, 0] сделает систему правосторонней.

Цитата из предыдущего ответа Николая : (зачеркнутый - моя работа, объяснено ниже)

Я удивлен, что никто что-то не упомянул: OpenGL тоже работает в левой системе координат. По крайней мере, это так, когда вы работаете с шейдерами и используете диапазон глубины по умолчанию.

Выбросив конвейер с фиксированными функциями, вы имеете дело непосредственно с «пространством отсечения». Спецификация OpenGL определяет пространство отсечения как однородную систему координат 4D. Когда вы прослеживаете преобразования через нормализованные координаты устройства и вплоть до оконного пространства, вы обнаруживаете это.

Пространство окна находится в пространстве пикселей окна. Начало координат находится в нижнем левом углу, + Y идет вверх, а + X - вправо. Это очень похоже на правостороннюю систему координат. А как насчет Z?

Диапазон глубины по умолчанию (glDepthRange) устанавливает ближайшее значение Z равным 0, а дальнее значение Z равным единице . Итак, + Z уходит от зрителя.

Это левая система координат. Да, ты можешьизмените тест глубины с GL_LESS на GL_GREATER иизмените glDepthRange с [0, 1] на [1, 0]. Но по умолчанию OpenGL работает в левой системе координат. И ни одно из преобразований, необходимых для перехода в пространство окна из пространства отсечения, не отменяет Z. Таким образом, пространство отсечения, выход вершинного (или геометрического) шейдера является левым пространством (вроде как. Это четырехмерное однородное пространство, поэтому трудно прижать руку).

В конвейере с фиксированной функцией стандартные матрицы проекции (созданные glOrtho, glFrustum и т.п.) все преобразуются из правого пространства в левое . Они меняют значение Z; просто проверьте матрицы, которые они генерируют. В пространстве для глаз + Z перемещается к зрителю; в пост-проекционном пространстве он уходит.

Я подозреваю, что Microsoft (и GLide) просто не потрудились выполнить отрицание в своих матрицах проекций.

Я поразил одну часть, поскольку она расходилась с моими выводами.

Либо изменение DepthRange, либо DepthFunc и использование ClearDepth (0) работает, но при использовании обоих они компенсируют друг друга обратно в левостороннюю систему.

Hultqvist
источник
Диапазон глубины не может быть [1, -1]. Я думаю, вы имели в виду [1, 0]. Также на это указывалось ранее .
Никол Болас
Ваш ответ отличный, очень жаль, что это вопрос о DirectX, вы должны опубликовать его здесь!
hultqvist
3
@SigTerm, почему вы думаете, что исправлять ложное утверждение не стоит? Я потратил несколько часов на устранение неполадок с координатами вершин и генерацией вращения матрицы только для того, чтобы выяснить, что система координат по умолчанию на самом деле не правая.
hultqvist
1
Вопрос был в том, будет ли это левосторонняя или правосторонняя система. В этом ответе есть более подробные сведения, объясняющие два других способа получить его правой рукой, добавление -1 в матричное преобразование - еще один способ сделать это. Но все это не имеет значения, если вы считаете, что система по умолчанию является правосторонней, вы можете что-то изменить, только если знаете, от чего вы меняете. Still
hultqvist
1
Я нашел ответ очень поучительным, и его начали искать, так что он того стоил.
Изучите OpenGL ES
13

ТОЛЬКО НДЦ

Вы должны только заметить, что OpenGL знает только NDC! и это левая система координат.

Независимо от того, какую систему координат вы используете - левую или правую систему осевых координат - все они должны быть отражены в NDC. Если хотите, вы можете полностью обрабатывать мировое пространство как левую систему координат.

Почему мы обычно используем правую систему координат в мировом пространстве?

Думаю, это условно. Это просто так. Может, его просто хотят отличить от DirectX.

ZK_
источник
3
Я думаю, это не повторяется достаточно часто. Все эти диаграммы, показывающие «преобразование моделирования», «преобразование вида», «преобразование перспективы», не показывают, что они не являются внутренней частью OpenGL. Вы даже можете выполнять все преобразования вручную, с шейдерами или без них, с матрицами или без них.
Том
3
Было бы лучше, если бы повторить его, включив в него слова «нормализованные координаты устройства».
Томми
6
OpenGL опередил DirectX на несколько лет, поэтому OpenGL определенно не пытался отличиться от DirectX. Ведущий разработчик DirectX Алекс Сент-Джон заявил, что решение Microsoft перейти на левостороннюю систему координат было «частично обусловлено личными предпочтениями» и «произвольным выбором».
Крис Нолет
Это не совсем так. OpenGL также знает систему координат отсечения, поскольку отсечение происходит в ней. Система координат зажима имеет ту же руку, что и система координат NDC.
Plasmacel
7

В книге "Руководство по программированию WebGl" Коити Мацуда почти десять страниц посвящено теме "WebGl / OpenGl: для левой или правой руки?"

По книге:

  • На практике большинство людей используют праворукую систему.

  • OpenGl внутренне является системой для левшей

  • Внутренне, глубже, на самом деле ни то, ни другое. В самом низу OpenGl не заботится о z-значении. Порядок, в котором вы рисуете объекты, определяет, что будет нарисовано сверху (сначала нарисуйте треугольник, затем четырехугольник, четырехугольник переопределяет треугольник).

Я не полностью согласен с «ни то, ни другое», но это, вероятно, в любом случае философский вопрос.

Heinzlmaen
источник
7
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). Это правда, в отсутствие тестирования глубины. При наличии проверки глубины значение z фрагмента сравнивается со значением в буфере глубины, и фрагмент отбрасывается, если он не проходит проверку глубины, поэтому квад может или не может перезаписать треугольник в зависимости от их глубины и Используемая функция глубины.
Крисварнц
3

Opengl определенно левша. Вы видите множество руководств, в которых говорится об обратном, потому что они отрицают z-значение в матрице проекции. Когда конечные вершины вычисляются внутри вершинного шейдера, он преобразует вершины, которые вы передаете со стороны клиента (правая координата) в левую, а затем вершины передаются геометрическому шейдеру и фрагментному шейдеру. Если вы используете правую систему координат на стороне клиента, Opengl все равно. Он знает только нормализованную систему координат, которая является левосторонней.

Изменить: если вы мне не доверяете, просто поэкспериментируйте со своим вершинным шейдером, добавив матрицу перевода, и вы легко увидите, левша Opengl или нет.

ИностранныйДьявол
источник
0

Используя встроенные функции проекции и трансформации OpenGL, наблюдение за движениями на экране следует правилам правой системы координат. Например, если объект перед вашим видом перемещается в положительном направлении оси z, то этот объект будет двигаться к вам.

Буфер глубины совершенно противоположен, и здесь в игру вступают NDC (нормализованные координаты устройства). Если передача GL_LESS в glDepthFunc означает, что пиксели будут отрисовываться, когда они будут ближе к вам, чем то, что уже находится в буфере глубины, то считается, что пиксели живут в левой системе координат.

Есть еще одна система координат, и это область просмотра! Система координат области просмотра такова, что + x указывает вправо, а + y указывает вниз. Я думаю, что на данный момент своеволие является спорным, так как мы имеем дело только с й, у в этой точке.

Наконец, gluLookAt под капотом должна нейтрализовать вектор взгляда. Поскольку математика предполагает, что вектор направлен в положительном направлении к объекту, на который он смотрит, а камера смотрит вниз -z, вектор взгляда должен быть инвертирован, чтобы он выровнялся с камерой.

Что-нибудь пожевать. Нет смысла называть направление z правой системы координат прямым вектором :). Я думаю, что Microsoft осознала это, когда разработала Direct3D.

Weatx
источник