Система координат OpenGL - левша или правша?
Я пытаюсь понять систему координат OpenGL. Тем не менее, некоторые учебники говорят, что система координат по умолчанию левша (см. http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx), а другие говорят, что она правша (см. http://www.falloutsoftware.com/tutorials/gl/gl0.htm). Что правильно? Я понимаю, что мы можем преобразовать одно в другое путем зеркального отражения, но я хотел бы знать координаты по умолчанию.
5 ответов
Система координат правша. Первая статья кажется неправильной.
Здесь есть некоторая путаница.
OpenGL правша в пространстве объектов и мировом пространстве.
Но в пространстве окна (он же пространство экрана) мы вдруг оказались левшами.
Как это случилось?
То, как мы получаем от правой руки к левой руке, является отрицательной Z-масштабирующей записью в glOrtho
или же glFrustum
проекционные матрицы. Масштабирование z на -1 (оставляя x и y без изменений) приводит к изменению управляемости системы координат.
Для glFrustum,
дальний и ближний должны быть положительными, а дальний > ближний. Скажи далеко =1000, а рядом =1. Тогда C= -( 1001) / ( 999) = -1,002.
Смотрите здесь для более подробной информации и диаграмм.
С орфографической точки зрения, glOrtho генерирует такую матрицу:
Здесь, слева, справа, снизу и сверху - это координаты для левой вертикальной, правой вертикальной, нижней горизонтальной, верхней горизонтальной плоскостей отсечения (соответственно).
Однако ближняя и дальняя плоскости указаны по-разному. Ближайший параметр определяется как
- Рядом: расстояние до ближайшей плоскости отсечения глубины. Это расстояние отрицательно, если самолет должен быть позади зрителя.
и далеко:
- 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.
По умолчанию нормализованная координата устройства - левша.
По умолчанию glDepthRange [0, 1] (ближний, дальний) направляет ось +z на экран, а +x вправо и +y вверх - это левосторонняя система.
Изменение диапазона глубины на [1, 0] сделает систему правой рукой.
Цитирую предыдущий ответ Николя: (зачеркнутая работа - моя работа, объясненная ниже)
Я удивлен, что никто не упомянул что-то: OpenGL работает и в левой системе координат. По крайней мере, так происходит, когда вы работаете с шейдерами и используете диапазон глубины по умолчанию.
После того, как вы выбросили конвейер с фиксированной функцией, вы имеете дело непосредственно с "clip-space". Спецификация OpenGL определяет пространство клипа как 4D однородную систему координат. Когда вы следуете за преобразованиями через нормализованные координаты устройства и до места в окне, вы найдете это.
Пространство окна находится в пространстве пикселей окна. Начало координат находится в нижнем левом углу, +Y идет вверх, а +X направо. Это очень похоже на правую систему координат. Но как насчет Z?
Диапазон глубины по умолчанию (glDepthRange) устанавливает близкое значение Z в 0, а дальнее значение Z в единицу. Так что +Z уходит от зрителя.
Это левая система координат. Да, ты можешь
изменить тест глубины с GL_LESS на GL_GREATER иизмените glDepthRange с [0, 1] на [1, 0]. Но стандартное состояние OpenGL - работа в левой системе координат. И ни одно из преобразований, необходимых для того, чтобы попасть в пространство окна из пространства клипа, не отменяет Z. Таким образом, пространство клипа, вывод вершинного (или геометрического) шейдера, является пространством для левши (вроде. Это однородное пространство 4D, поэтому трудно придавить руки).В конвейере с фиксированной функцией стандартные проекционные матрицы (созданные glOrtho, glFrustum и т.п.) все преобразуются из правостороннего пространства в левостороннее. Они переворачивают значение Z; просто проверьте матрицы, которые они генерируют. В глазном пространстве +Z движется к зрителю; в пост-проекционном пространстве он уходит.
Я подозреваю, что Microsoft (и GLide) просто не удосужились выполнить отрицание в своих матрицах проекции.
Я ударил одну часть, так как она отличалась от моих выводов.
Изменение либо DepthRange, либо DepthFunc и использование ClearDepth(0) работает, но при использовании обоих они отменяют друг друга обратно в левостороннюю систему.
ТОЛЬКО НДЦ
Вы должны только заметить, что OpenGL only knows NDC!!
и это левая координата. Независимо от того, какую координату вы используете, левую, правую координату оси и т. д. Все должно быть отражено в NDC. Если хотите, вы можете полностью написать мировое пространство в левой координате.
Почему мы используем правую правую координату в мировом пространстве?
Я думаю, что это обычное дело. Просто так. Может, просто хочется отличить его от DirectX.
Книга Куиджи Мацуда "Руководство по программированию WebGl" посвящена почти десяти страницам "WebGl/OpenGl: влево или вправо?"
Согласно книге:
На практике большинство людей используют правостороннюю систему
OpenGl на самом деле внутренняя левосторонняя система
Внутренне, более глубоко это фактически ни то, ни другое. В самом низу OpenGl не заботится о z-значении. Порядок, в котором вы рисуете вещи, определяет то, что нарисовано сверху (сначала нарисуйте треугольник, затем квад, треугольник переопределяет).
Я не полностью согласен с "это ни то, ни другое", но это, вероятно, философский вопрос в любом случае.
Opengl определенно левша. Вы видите много обучающих программ, утверждающих обратное, потому что они отрицают z-значение в матрице проекции. Когда окончательные вершины вычисляются внутри вершинного шейдера, он преобразует вершины, которые вы передаете от клиентской части (правая координата), в левую, и вершины затем передаются в геометрический шейдер и фрагментный шейдер. Если вы используете правую систему координат на стороне клиента, Opengl не волнует. Он знает только нормализованную систему координат, которая левша.
Изменить: Если вы не доверяете мне, просто поэкспериментируйте в своем вершинном шейдере, добавив матрицу перевода, и вы легко сможете увидеть, является ли Opengl левшой или нет.
Используя встроенные в OpenGL функции проецирования и трансформации, наблюдение за движениями на экране следует правилам правой системы координат. Например, если объект перед вашим видом перемещается в положительном направлении оси z, то этот объект будет двигаться к вам.
Буфер глубины совершенно противоположен, и здесь в игру вступают NDC (нормализованные координаты устройства). Если передача GL_LESS в glDepthFunc означает, что пиксели будут отрисовываться, когда они будут ближе к вам, чем то, что уже находится в буфере глубины, то считается, что пиксели находятся в левой системе координат.
Есть еще одна система координат, и это область просмотра! Система координат области просмотра такова, что +x указывает вправо, а +y указывает вниз. Я думаю, что на данный момент своеволие является спорным, так как мы имеем дело только с й, у в этой точке.
Наконец, под капотом gluLookAt должен нейтрализовать вектор взгляда. Поскольку математика предполагает, что вектор направлен в положительном направлении к объекту, на который он смотрит, а камера смотрит вниз -z, вектор взгляда должен быть инвертирован, чтобы он выровнялся с камерой.
Что-нибудь пожевать. Нет особого смысла называть направление z правой системы координат прямым вектором:). Я думаю, что Microsoft осознала это, когда разработала Direct3D.