Перспективные матрицы в графическом API или дьявол прячется в деталях

Перспективные матрицы в графическом API или дьявол прячется в деталях

527
ПОДЕЛИТЬСЯ

В определённый момент у хоть какого разраба в области компьютерной графики возникает вопросец: как же работают эти многообещающие матрицы? Тотчас ответ отыскать чрезвычайно непросто и , как это традиционно бывает, основная масса разрабов кидает это занятие на полпути.

Это не решение трудности! Давайте разбираться совместно!

Начиная с данной версии каждый разраб должен без помощи других реализовывать модуль матричных операций. Проведём декомпозицию нашей с вами нелёгкой задачки и выделим главные моменты. Будем реалистами с практическим уклоном и возьмём в качестве подопытного OpenGL версии 3.3. Замечательно, это то, что нам необходимо. Незначительно фактов из спецификации OpenGL:

Матрицы хранятся по столбцам (row-major);
Однородные координаты;
Канонический размер отсечения (CVV) в левосторонней системе координат.

При программировании OpenGL есть маленькая хитрость, которая дозволяет отрешиться и от транспонирования матриц при сохранении классических column-major расчётов. По большому счёту представление матриц в памяти не имеет значения, поэтому что матрицу постоянно можно перевести в 1-го вида представления в другое обычным транспонированием. А раз различия нет, то для всех следующих расчётов мы будем применять классические column-major матрицы. Существует два метода хранения матриц: сolumn-major и row-major. В шейдерную програмку матрицу необходимо передавать как есть, а в шейдере создавать умножение не вектора на матрицу, а матрицы на вектор. На лекциях по линейной алгебре как раз употребляется схема сolumn-major.

Иными словами: Однородная координата это матрица-строчка размерности [1×4]. Однородные координаты – это не чрезвычайно хитрецкая система с рядом обычных правил по переводу обычных декартовых координат в однородные координаты и обратно. Для того чтоб перевести декартову координату в однородную координату нужно x, y и z умножить на хоть какое действительное число w (не считая 0). Дальше нужно записать итог в 1-ые три составляющие, а крайний компонент будет равен множителю w.
— в декартовы координаты
w – действительное число не равное 0
— однородные координаты

То есть получить матрицу-строчку: Маленький трюк: Раз w равно единице, то всё что необходимо для перевода, это перенести составляющие x, y и z и приписать единицу в крайний компонент.

С точки зрения однородных координат это полностью допустимо. Несколько слов о нуле в качестве w. В декартовой же системе координат такое разделение нереально. Однородные координаты разрешают различать точки и вектора.
— точка, где (x, y, z) – декартовы координаты
— вектор, где (x, y, z) – радиус-вектор

Все составляющие матрицы-строчки нужно поделить на последнюю компоненту. Обратный перевод вершины из однородных координат в декартовы координаты осуществляется последующим образом. Иными словами:
— однородные координаты
— декартовы координаты

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

Всё, что отчасти выходит за границы CVV, подлежит методам отсечения. Канонический размер отсечения либо Canonic view volume (CVV) – это одна из не достаточно документированных частей OpenGL. Всё, что попадает в область CVV подлежит растеризации, всё, что находится вне CVV игнорируется. Самое основное что нужно знать — система координат CVV левосторонняя! 1 CVV – это выровненный по осям куб с центром в начале координат и длиной ребра равной двойке. Как видно из рис.

Канонический размер отсечения OpenGL (CVV) Рис. 1.

Как же так, ведь в спецификации к OpenGL 1.0 ясно написано, что используемая система координат правосторонняя? Левосторонняя система координат? Давайте разбираться.

Системы координат 2. Рис.

В какой момент происходит перевод пользовательской системы координат в систему координат CVV. 2 системы координат различаются только направлением оси Z. Возникает два логичных вопросца. Наиболее того начиная с версии 3.3 больше не существует такового понятия как обычная система координат OpenGL. Но система координат CVV и пользовательская система координат это две совсем различные вещи. Формирование матриц вращения, формирование проекционных матриц, поиск обратной матрицы, умножение матриц – это малый набор операций, входящих в модуль матричных операций. Проекционные матрицы – это как раз та суть, которая занимается решением этих вопросцев. В OpenGL 1.0 вправду употребляется правосторонняя пользовательская система координат. Раз размер видимости это куб с длиной ребра равной двум, то почему сцена размером в несколько тыщ условных единиц видна на экране? Как видно из рис. Как упоминалось ранее, программер сам реализует модуль матричных операций.

Основная мысль вышеизложенного – разраб сам свободен выбрать тип пользовательской системы координат и должен корректно обрисовать проекционные матрицы. На этом с фактами о OpenGL закончено и подошло время сводить всё воедино.

Так как же она связана с CVV и пользовательской системой координат? Не секрет, что неважно какая трёхмерная модель состоит из конечного перечня вершин, которые подвергаются матричным преобразованиям совсем независимо друг от друга. Для того чтоб осознать почему объекты уменьшаются с повышением расстояния, давайте разглядим матричные преобразования трёхмерной модели шаг за шагом. Одна из более всераспространенных и трудно постигаемых матриц – это матрица многообещающего преобразования. Почему объекты с повышением расстояния до наблюдающего стают меньше? Для того чтоб найти координату трёхмерной вершины на двухмерном экране монитора нужно:

Перевести декартову координату в однородную координату;
Умножить однородную координату на модельную матрицу;
Итог умножить на видовую матрицу;
Итог умножить на проекционную матрицу;
Итог перевести из однородных координат в декартовы координаты.

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

Во многом это припоминает смысл модельной матрицы. Чем характеризуется наблюдающий? Модельная матрица наблюдающего и есть разыскиваемая ровная матрица. Инвертировав эту матрицу, мы получаем видовую матрицу. В этом пространстве координаты отсчитываются относительно положения и ориентации наблюдающего так, как раз бы он являлся центром мира. По большому счёту так оно и есть. Наблюдающий может передвигаться по сцене и осуществлять повороты. Прямое матричное преобразование выносит координаты из некого места. Наблюдающий описывается координатой, в которой он находится, и векторами направления обзора. Наблюдающий постоянно глядит в направлении собственной локальной оси Z. Как же получить эту обратную матрицу? Сейчас перебегаем к шагу три. Видовое место является локальным относительно мирового места, потому координаты в него нужно вносить (а не выносить, как в прошлом случае). Раз вершина находилась за наблюдателем, то значение её однородной координаты z в видовом пространстве точно будет отрицательным числом. На практике это значит, что все вершины в глобальных однородных координатах получат новейшие однородные координаты относительно наблюдающего. Но, для наблюдающего операция масштабирования бессмысленна, потому меж модельной матрицей наблюдающего и модельной матрицей трёхмерного объекта нельзя ставить символ равенства. Чтоб напротив внести их в него, нужно матричное преобразование инвертировать, потому видовое преобразование описывается обратной матрицей. Соответственно, раз наблюдающий лицезрел определённую вершину, то значение однородной координаты z данной вершины в видовом пространстве точно будет положительным числом. Для начала получим прямую матрицу наблюдающего. Тут начинает работу видовое место.

На четвёртом шаге однородные координаты выносятся из видового места в место CVV. Ещё раз подчеркивается тот факт, что все потенциально видимые вершины будут иметь положительное значение однородной координаты z. Прошлые шаги были рассмотрены так тщательно намеренно, чтоб читатель имел полную картину о всех операндах 4-ого шага. Шаг четыре — это самый увлекательный шаг.

Разглядим матрицу вида:

И точку в однородном пространстве наблюдающего:

Произведём умножение однородной координаты на рассматриваемую матрицу:

Переведём получившиеся однородные координаты в декартовы координаты:

Допустим, есть две точки в видовом пространстве с схожими координатами x и y, но различными координатами z. Из-за многообещающего преломления наблюдающий должен узреть обе точки. Иными словами одна из точек находится за иной. Чем больше значение z (чем далее точка от наблюдающего), тем посильнее сжатие. Вправду, из формулы видно, что из-за деления на координату z, происходит сжатие к точке начала координат. Вот и разъяснение эффекту перспективы.

В спецификации OpenGL сказано, что операции по отсечению и растеризации выполняются в декартовых координатах, а процесс перевода однородных координат в декартовы координаты делается автоматом.

Выведем многообещающую матрицу для левосторонней пользовательской системы координат. Матрица (1) является шаблоном для матрицы перспективой проекции. Как было сказано ранее, задачка матрицы проекции заключается в 2-ух моментах: установка пользовательской системы координат (левосторонняя либо правосторонняя), перенос размера видимости наблюдающего в CVV.

3): Матрицу проекции можно обрисовать с помощью 4 характеристик (рис.

Угол обзора в радианах (fovy);
Соотношение сторон (aspect);
Расстояние до ближней плоскости отсечения (n);
Расстояние до дальней плоскости отсечения (f).

3. Многообещающий размер видимости Рис.

Так же следует учитывать, что пользовательская система координат совпадает с системой координат CVV, то есть везде пользуется левосторонняя система координат. Для большей наглядности на рис. 4 изображён вид сбоку. Разглядим проекцию точки в пространстве наблюдающего на переднюю грань отсечения многообещающего размера видимости.

Проецирование случайной точки 4. Рис.

На основании параметров схожих треугольников справедливы последующие равенства:

Выразим yꞌ и xꞌ:

Но для правильного экранирования трёхмерных объёктов нужно знать глубину каждого фрагмента. Как раз это значение употребляется при тестах глубины OpenGL. Выход из сложившейся ситуации – внедрение так именуемой псевдоглубины. 3 видно, что значение zꞌ не подступает в качестве глубины фрагмента, поэтому что все проекции точек могут однообразное значение zꞌ. На рис. Иными словами нужно хранить значение составляющие z. В принципе, выражений (2) довольно для получения координат точек проекции.

Характеристики псевдоглубины:
Псевдоглубина рассчитывается на основании значения z;
Чем поближе к наблюдающему находится точка, тем меньшеe значение имеет псевдоглубина;
У всех точек, лежащих на передней плоскости размера видимости, значение псевдоглубины равно -1;
У всех точек, лежащих на дальней плоскости отсечения размера видимости, значение псевдоглубины равно 1;
Все фрагменты, лежащие снутри размера видимости, имеют значение псевдоглубины в спектре [-1 1].

Давайте выведем формулу, по которой будет рассчитываться псевдоглубина. В качестве базы возьмём последующее выражение:

Для того чтоб это сделать, воспользуемся качествами псевдоглубины 3 и 4. Коэффициенты a и b нужно вычислить. Получаем систему из 2-ух уравнений с 2-мя неизвестными:

Произведём сложение обоих частей системы и умножим итог на произведение fn, при этом f и n не могут приравниваться нулю. Получаем:

Раскроем скобки и перегруппируем слагаемые так, чтоб слева осталась лишь часть с а, а справа лишь с b:

Подставим (6) в (5). Преобразуем выражение к обычный дроби:

Приведём подобные, перегруппируем слагаемые и выразим b: Умножим обе стороны на -2fn, при этом f и n не могут приравниваться нулю.

Подставим (7) в (6) и выразим a:

Соответственно составляющие a и b равны:

Сейчас подставим приобретенные коэффициенты в матрицу заготовку (1) и проследим, что будет происходить с координатой z для случайной точки в однородном пространстве наблюдающего. Подстановка выполняется последующим образом:

Пусть расстояние до передней плоскости отсечения n равно 2, а расстояние до дальней плоскости отсечения f равно 10. Разглядим 5 точек в однородном пространстве наблюдающего:
Взаимное размещение точки и размера видимости
Точка
Значение
Описание
1
1
Не проходит растеризацию. Точка находится перед передней плоскостью отсечения размера видимости.
2
2
Точка находится на передней грани отсечения размера видимости. Проходит растеризацию.
3
5
Точка находится меж передней гранью отсечения и дальней гранью отсечения размера видимости. Проходит растеризацию.
4
10
Проходит растеризацию. Точка находится на дальней грани отсечения размера видимости.
5
20
Не проходит растеризацию. Точка находится за дальней гранью отсечения размера видимости.

Для этого нам нужно вычислить значения новейших однородных компонент и . Умножим все точки на матрицу (8), а потом переведём приобретенные однородные координаты в декартовые координаты.

Точка 1:

Точка 2:

Точка 3:

Точка 4:

Точка 5:

Обратите внимание, что однородная координата полностью правильно позиционируется в CVV, а самое основное, что сейчас возможна работа теста глубины OpenGL, поэтому что псевдоглубина на сто процентов удовлетворяет требованиям тестов.

С координатой z разобрались, перейдём к координатам x и y. Соответственно, высоту и ширину многообещающего размера видимости нужно сжать до 2-ух условных единиц. Как говорилось ранее весь многообещающий размер видимости должен умещаться в CVV. Длина ребра CVV равна двум.

Давайте выразим высоту и ширину, используя эти величины. В нашем распоряжении имеется угол fovy и величина aspect.

Размер видимости Рис. 5.

5 видно, что: Из рис.

Сейчас можно получить окончательный вид многообещающей проекционной матрицы для пользовательской левосторонней системы координат, работающей с CVV OpenGL:

На этом вывод матриц закончен.

Что касается системы координат CVV, то в DirectX, как и в OpenGL, употребляется левосторонняя система координат. Спектр x и y равен [-1 1], а спектр z равен [0 1]. В DirectX CVV — это прямоугольный параллелепипед с длинами по осям x и y равными двойке, а по оси z длина равна единице. DirectX различается от OpenGL лишь габаритами CVV и его позиционированием. Пару слов о DirectX — основном сопернике OpenGL.

Для матриц DirectX характеристики 3 и 4 модифицируются под спектр [0 1]. Для вывода многообещающих матриц для пользовательской правосторонней системы координат нужно перерисовать рис. 2, рис.3 и рис.4 с учётом новейшего направления оси Z. Дальше расчёты на сто процентов подобны, с точностью до знака.

На этом тему многообещающих матриц можно считать закрытой.

Нужная литература
1. Graphics pipeline
2. Homogeneous coordinates
3. Lanterman A. Multicore and GPU programming for videogames
CS 543 — Computer Graphics: Projection 4. Lindeman R.W.
Segal M., Akeley K. The OpenGL Graphics System: A Specification (Version 3.3 (Core Profile) — March 11, 2010) 5.
OpenGL Projection Matrix Song H.A. 6.
7. The OpenGL Shading Language Version 3.30
Tutorial 12 — Perspective Projection 8.
Игнатенко А. 9. Однородные координаты
10. Многообещающие преобразования habrahabr.ru