opengl - камера не может видеть объект при использовании glOrtho - PullRequest
0 голосов
/ 04 июля 2018

Я новичок в OpenGL и пытаюсь понять, как в нем работает матрица проекций.

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

(0,1,0), (1,0,0), (-1,0,0)

Я установил матрицу вида модели и матрицу проекции, как показано ниже:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    0, 0, 2,
    0, 0, 0,
    0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // does not work
// glOrtho(-2, 2, -2, 2, 0.1, 2.0); // works

Насколько я понимаю, gluLookAt() используется для установки матрицы просмотра. Поскольку OpenGL не имеет понятия «камера», и, таким образом, он преобразует весь мир, чтобы достичь эффекта камеры. В приведенном выше коде я предполагаю, что «камера» находится на (0,0,2), глядя на (0,0,0). Так OpenGL внутренне перемещает треугольник назад вдоль оси z к z=-2.

Чтобы определить усеченный вид, glOrtho() получить 6 параметров. Чтобы сделать треугольник видимым в усеченном контуре, я установил значения near и far на -0.1 и -2.0 соответственно, и это должно означать, что усеченное кольцо включает [-0.1, -2.0] на оси z.


Я искал похожие вопросы и обнаружил, что кто-то утверждает, что последние два параметра glOrtho() на самом деле -near и -far. Но если это правильно, следующий код должен работать (, но не ):

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    0, 0, -2, // changed 2 to -2, thus the triangle should be transformed to z=2?
    0, 0, 0,
    0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // -near=-0.1, -far=-2.0, thus the frustum should include [0.1, 2.0], thus include the triangle

Если я прав, на экране должен быть нарисован треугольник, поэтому с моим кодом должно быть что-то не так. Кто-нибудь может помочь?

1 Ответ

0 голосов
/ 04 июля 2018

Прежде всего, обратите внимание, что стек конвейеров с фиксированной функцией и отрисовка последовательностями glBegin / glEnd устарели уже более 10 лет. Прочитайте о конвейере с фиксированными функциями и посмотрите Vertex Specification для современного способа рендеринга.


Если вы используете такую ​​матрицу вида:

gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);

Тогда значения для ближней и дальней плоскостей должны быть положительными при настройке матрицы проекции,

glOrtho(-2, 2, -2, 2, 0.1, 2.0);

потому что, gluLookAt преобразует вершины в пространство просмотра (в пространстве просмотра ось z указывает из области просмотра), но матрица проекции инвертирует ось z.

Но будьте осторожны, поскольку треугольник находится на z=0

(0,1,0), (1,0,0), (-1,0,0)

и расстояние от камеры до треугольника равно 2, поскольку из-за матрицы вида треугольник расположен точно на дальней плоскости (что также составляет 2,0). Я рекомендую увеличить расстояние до дальней плоскости с 2,0 до (например) 3,0:

glOrtho(-2, 2, -2, 2, 0.1, 3.0);

Если вы измените матрицу вида,

gluLookAt(0, 0, -2, 0, 0, 0, 0, 1, 0);

затем по-прежнему (ось пространства просмотра) ось z указывает из области просмотра, но вы смотрите на «обратную» сторону треугольника. Треугольник все еще находится в центре вида (0, 0, 0), но положение камеры изменилось. Треугольник все еще перед камерой.

Если бы вы сделали

gluLookAt(0, 0, 2, 0, 0, 4, 0, 1, 0);

тогда вы отведете взгляд от треугольника. Вам придется проецировать заднюю сторону вида в окно просмотра, чтобы «увидеть» треугольник (glOrtho(-2, 2, -2, 2, -0.1, -3.0);).


Далее отметим, что glOrtho умножает текущую матрицу на матрицу ортографической проекции. Это означает, что вы должны установить матрицу идентификаторов перед использованием glOrtho, как вы делаете это с матрицей вида модели:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, 0.1, 2.0);

Объяснение

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

В ортографической проекции эта область (объем) определяется 6 расстояниями (слева, справа, снизу, сверху, близко и далеко) к позиции зрителя.

Просмотр матрицы

Система координат вида описывает направление и позицию, с которой просматривается сцена. Матрица вида трансформируется из пространства Вольда в пространство вида (глаза).

Если система координат пространства просмотра представляет собой Правую систему, то ось X указывает влево, ось Y вверх и ось Z вне вида (Примечание в правой системе ось Z является перекрестным произведением оси X и оси Y).

enter image description here

Матрица проекции

Матрица проекции описывает отображение от трехмерных точек вида на сцене к двухмерным точкам в области просмотра. Он преобразуется из пространства глаза в пространство клипа, а координаты в пространстве клипа преобразуются в нормализованные координаты устройства (NDC) путем деления на компоненту w координат клипа. НДЦ находятся в диапазоне (-1, -1, -1) - (1,1,1).
Каждая геометрия, находящаяся вне пространства отсечения, обрезается.

В ортогональной проекции координаты в пространстве просмотра линейно отображаются на координаты пространства клипа, а координаты пространства клипа равны нормализованным координатам устройства, поскольку компонент w равен 1 (для декартовой входной координаты).
Значения слева, справа, снизу, сверху, близко и далеко определяют поле. Вся геометрия, которая находится внутри объема окна, «видна» в окне просмотра.

enter image description here

Матрица ортографической проекции выглядит следующим образом:

r = right, l = left, b = bottom, t = top, n = near, f = far 

2/(r-l)         0               0               0
0               2/(t-b)         0               0
0               0               -2/(f-n)        0
-(r+l)/(r-l)    -(t+b)/(t-b)    -(f+n)/(f-n)    1

Ось z инвертируется проекционной матрицей.

...