Если в моделируемых вами сценах присутствуют зеркальные отражения, и вы подзабыли или не слышали про «oblique frustum», то возможно, что эта статья не будет для вас бесполезной.
Несмотря на то, что я, вслед за Эриком Ленгелом, более придерживался при изложении материала представлений OpenGL, все последующие рассуждения легко распространяются на любые другие системы трёхмерного моделирования.

Отражения в 3D–сценах
В случае, когда в 3D-сценах присутствуют отражающие поверхности, обычная практика получения отражения заключается в рендеринге сцены с использованием вспомогательной камеры вида, которая сама является отражением основной камеры вида плоскостью отражающей поверхности.
Рис. 1. Верхняя камера является основной камерой, через которую происходит рендеринг сцены, содержащей отражающую поверхность. Нижняя камера является вспомогательной камерой, предназначенной для рендеринга отражения. Ось X направлена к наблюдателю для обеих пирамид видимости (в принятых для OpenGL представлениях), и очевидно, что координатная система для камеры, осуществляющей рендеринг отражения, является левосторонней.
При рендеринге отражения вспомогательной камерой (камерой отражения), может оказаться, что часть объектов, расположенных между наблюдателем и отражающей поверхностью, оказывается в результирующем рендере, образуя нежелательные артефакты в изображении. Чтобы отсечь нежелательную часть отраженной сцены с финального рендера, программист ограничивает наблюдаемую из камеры отражения часть объема трёхмерной сцены воображаемой поверхностью, используя различные приемы для того, чтобы прервать визуализацию сцены за границей этой поверхности.
Можно воспользоваться инструкцией „discard” для фрагментного шейдера или ей подобными, специфическими для отдельных реализаций рендеринга в общей идеологии 3D–моделирования ( например „kill” в AGALMiniAssembler), однако, если нам желательно решение универсальное, одинаково хорошо работающее на любом процессоре, то стоит обратить внимание на технику, предложеную Эриком Ленгелом.
Идея Эрика Ленгела заключалась в том, чтобы модифицировать проекционную матрицу таким способом, чтобы ближний план пирамиды видимости стал как раз своего рода секущей плоскостью, отделяющей нежелательный в конечном рендере объем основной сцены.
Для дальнейшего уместно напомнить элементарные представления аналитической геометрии.
Плоскость в пространстве
Для удобства изложения, будем придерживаться следующих обозначений:
Плоскость
Для любой пространственной 3D-точки
Рис. 2. Плоскость полностью определяется принадлежащей ей точкой
Уравнение плоскости часто записывается следующим выражением:
где
В случае нормализованного вектора нормали, выражение
может быть использовано, для нахождения расстояния от плоскости до произвольной точки
Удобно записать плоскость четырехмерным вектором. Коротко уравнение плоскости запишется так:
Преобразование плоскости
Для понимания особенности пространственного преобразования плоскости, потребуется некоторое внимание уделить преобразованию нормального вектора. При пространственном преобразовании полигональной модели, вектора касательные к поверхности полигонов и вектора нормальные ведут себя неодинаково. Вектор касательный часто можно представить как разницу между двумя преобразованными вершинами, т.е. между двумя естественным образом преобразованными точками, и, вследствие этого, характер преобразованного вектора совпадает с нашими ожиданиями. Но, в общем случае пространственного преобразования, матрица
Поскольку вектор касательный
если
вспомним, что умножение векторов можно записать и следующим образом (совершенно равнозначным):
Поскольку
Однако, плоскость в однородных координатах, в отличие от нормального вектора, имеет ненулевую
Расстояние до плоскости от начала координат, после применения пространственного преобразования, с учетом особенностей преобразования нормального вектора, для лежащей в этой плоскости точки
Мы воспользовались в данных вычислениях матрицей преобразования
Матрица обратного преобразования к матрице
Транспонируем обратную матрицу:
Можем видеть, что
Для дальнейшего существенно, что плоскость подчиняется ковариантному характеру пространственного преобразования.
Перспективная проекция
Перспективное проецирование применяется, чтобы создать у наблюдателя ощущение глубины на проекционном плане, матрица перспективного преобразования должна отобразить пространство пирамиды видимости в нормализованное пространство куба видимости. Пирамида видимости обычно может быть выражена через термины top, bottom, left, right, far, near или fovy, aspect, near, far, некоторые реализации OpenGL имеют среди своих инструментов средства работы как для правосторонней так и для левой координатных систем. Отличия и порядок умножения матрицы на вектор в каждой из систем, должны быть ясны любому программисту.
Рис. 3. Усеченная пирамида видимости (frustum) в системах компьютерной графики отсекает зону видимости, для целей последующего рендеринга, с боков и вдоль осей проецирования. Пирамида видимости, в пространстве камеры вида, располагается в правосторонней системе координат так, что вершина пирамиды лежит в центре координатной системы, а направление вида из камеры противоположно оси
В общем случае, пирамида видимости не обязана иметь форму правильной усеченной пирамиды, она может быть и асимметричной, поэтому модель с top, bottom, left, right, far, near является более подходящей для иллюстраций особенностей oblique frustum («скошенной пирамиды видимости»). «Сжатое пространство» куба видимости, замкнутое в объёме, ограниченном плоскостями
Чтобы организовать задуманное нами отсечение части объектов в исходной пирамиде видимости, нам потребуется модифицировать применяемую в нашей модели матрицу перспективной проекции. Параметры таковой матрицы программисты OpenGL могут найти на сайте основной документации по OpenGL, программисты на Flash (AS3), вероятнее всего обратятся к классу PerspectiveMatrix3D, программисты Direct3D имеют свои источники, пишущие для андроида найдут всё необходимое в классе android.opengl.Matrix, и т.д. Не исключено, что кто-то, поняв основную идею, предпочтет расширить свой собственный класс перспективного преобразования дополнительной функциональностью.
Точка из пространства пирамиды видимости камеры вида отображается в пространство клипа канонического куба, например, следующим 4х4-матричным преобразованием (воспользуемся матрицей перспективного преобразования генерируемой glFrustum()-функцией OpenGL):
При таком преобразовании,
Особенности искажения пространства стандартной матрицей преобразования видны из Рис.4:
Рис. 4. Отражение
Заменяя ближний план пирамиды видимости плоскостью отсечения, мы должны сохранить основные особенности матрицы перспективного преобразования,
Если
Модифицирование ближнего плана пирамиды видимости
Для начала, извлечем из произвольной проекционной матрицы
На Рис.5 показаны элементы «
Рис. 5. Нормальные векторы для левой, правой, ближней и дальней плоскостей, ограничивающих однородное кубическое пространство клипа. Нормальные векторы для верхней и нижней плоскостей пространства клипа направлены от и к наблюдателю.
Табл. 1. Взаимосвязь между координатами пространства клипа и пространства усеченной пирамиды видимости камеры вида. Матрица проекции
Пусть
Мы не можем модифицировать четвертую строку матрицы перспективной проекции, т.к. она используется для отражения отрицательной
Рис. 6. Замена ближнего плана пирамиды видимости плоскостью
Поскольку, согласно Таблицы 1, третья строка матрицы проекции входит в состав выражения для дальнего плана пирамиды видимости, то очевидно, что её модифицирование необходимо учесть для дальнего плана:
И этот результат являет собой заметную проблему для перспективной проекции: поскольку
Проекция глубины точки, ранее достигавшая максимума на дальнем плане, и необходимая нам для процесса графической растеризации, более не представляет собой проекцию вдоль оси
Рис. 7. (а) Пересечение измененного в соответствии с Выражением (14) дальнего плана
Пусть
Для большинства перспективных проекций, знаки компонент
Имея компоненты преобразованного угла
Чтобы наш дальний план содержал точку
и найдем из условия
Замена
и позволит нам оптимальным образом сориентировать дальний план пирамиды видимости, как показано на Рис. 7 (b) (данная техника замещения работает корректно и для пирамиды видимости, дальний план которой удален на бесконечность,– случай бесконечной проекционной матрицы,– для этого достаточно потребовать, чтобы дальний план был параллелен одной из двух образующих противоположный плоскости
Практическое использование произведенных выше наблюдений
Все ранее проделанные теоретические изыскания распространяются на любые обратимые проекционные матрицы, но, поскольку, в качестве примера уже привлекалась стандартная для OpenGL матрица в Выражении (10), то логично продолжить цепочку примеров с нею же.
Обратная матрица к ней будет выглядеть таким образом:
Получим значение для третьей строки модифицированной проекционной матрицы, как предложено Выражением (18) с учетом
Поскольку
Умножив обратную матрицу из Выражения (19) на
Чтобы убедиться в правильности разработанного метода модифицирования проекционной матрицы, рассмотрим частный случай расположения плоскости отсечения
Скалярное произведение
— результату, совпавшему с ожиданиями: при
Как уже предполагалось выше, следует ожидать, что процесс растеризации не будет столь же привычным, как в случае немодифицированной пирамиды видимости. Полный диапазон значений буфера глубины не будет достигаться вдоль различных направлений внутри пирамиды видимости вследствие изменения в геометрии пирамиды. Возьмем вектор произвольного направления
где
Мы полагаем, что скалярное произведение
полученное выражение указывает максимально достижимое значение нормализованной
Исследуем направление
Хорошей практикой для программиста будет, перед тем, как утвердить для дальнейшей работы выбранную пространственную модель, исследовать поведение нормализованной координаты внутри модифицированной (скошенной | oblique frustum) пирамиды видимости. Своевременно обнаружив проблемные места, он может поправить или положение камеры, или изменить угол наклона секущей плоскости таким образом, чтобы упростить работу буфера глубины, по возможности приблизив её к нормальному режиму. Затраты на такое действие не будут особенно значительными, но результат послужит спокойствию перфекциониста.
Продолжая эксплуатировать стандартную матрицу проекции из Выражения (10), легко перейти к очередному примеру её использования для исследования значений нормализованной
допустим, что плоскость, отсекающая неугодную нам геометрию, и которой мы замещаем ближний план пирамиды видимости, в направляющих косинусах представлена как
Скалярное произведение
и третья строка преобразованной матрицы проекции приобретет вид
Рассмотрим поведение нормализованной координаты
Последнее Выражение вполне подходит для целей численного исследования. Пример такого исследования можно видеть на Рис. 8. Диапазон нормализованных значений, предназначенных для буфера глубины, сильно сужается с ростом угла между нормалью плоскости и отрицательным направлением оси
Рис. 8. Сужение диапазона нормализованной
Заключение
Программисту в процессе разработки приложения часто приходится искать компромисс между быстродействием и реалистичностью рендеринга. Техника, изложенная в настоящей статье, позволяет не только достичь максимального быстродействия на самом широком спектре устройств, но и помогает определить ситуацию, в которой желательно отредактировать сцену, для наиболее благоприятного ее отображения.
Совмещение процессов модификации пирамиды видимости и тестирования работы буфера глубины для модифицированной пирамиды (или учет произведенных выше наблюдений) — залог высокого качества конечного результата непростого труда программиста.
Литература
[1] Eric Lengyel, Oblique View Frustum Depth Projection and Clipping. Journal of Game Development, Vol. 1, No. 2 (March 2005), pp. 5–16.
[2] Eric Lengyel, Mathematics for 3D Game Programming and Computer Graphics. Charles River Media, 2002, p. 103.
Комментарии (6)
nailer Автор
26.09.2017 20:03Возможно, я не вполне понял Ваше замечание, но техника отсечения как раз и применяется к пространству камеры отражения (?). Как раз в ней и строятся «отраженные объекты с отраженным источником света». Конечная растеризация осуществляется по совокупности фрагментов от матриц отражения и основной. Для каждого отражения — своя матрица (если их более одного). На рисунке, предваряющем статью, два отражения, одно из них — во фронтально стоящем зеркале, другое — в поверхности стола, для сохранения реалистичности «резы» неизбежны.
PapaBubaDiop
26.09.2017 23:55Нет, я говорю о варианте без камеры отражения. Объекты отражаются в реальном пространстве относительно плоскости отражения и строятся в общем z-буффере. Но это конечно работает для несложных сцен — типа 4 кубиков)
nailer Автор
27.09.2017 07:33Мне кажется такая техника довольно трудоемкой (если я правильно Вас понял, то предлагается продублировать объекты в сцене в соответствующем отражению координатном представлении), хотя, вероятно, применимой в некоторых ситуациях, но в случае, например, динамических сцен, придется геометрию каждого входящего в сцену объекта (псевдоотраженного) править (если этот объект должен лишь некоторой своей частью быть видимым в сцене), искажая его геометрию подобно «отсечению» (а самая эта «геометрия» может быть довольно сложной). Ничего нереального, конечно, в этом нет, но затраты могут быть много выше, чем «колдовство» с плоскостями и матрицами.
Nick_mentat
28.09.2017 12:51Движок компьютерной игры может быть оптимизирован таким способом, чтобы заранее просчитать порядок прорисовки объектов и составить для них дерево. В таком случае расчёт видимости/невидимости полигонов объектов из отражённой сцены на лету оказывается абсолютно невозможным. С другой стороны этот порядок очень просто наследуется при отражении камеры.
nailer Автор
28.09.2017 21:33Вообще, считаю, что такие основополагающий вещи, как Oblique Frustum должны быть известны, понятны (и, по моему мнению, интересны) любому программисту, несмотря на то, владеет ли он замечательным коммерческим движком, в котором реализовано все мыслимое и предвосхищающее его фантазии, или обладает ограниченным инструментарием для воплощения своих планов. Для более выразительной иллюстрации применения отсекающих плоскостей, прилагаю рисунок:
Специально убрал первый кубик, оставив только его отражения в столе и фронтально стоящем зеркале. Геометрия в обоих случаях обрезается способом, описанным в статье.
PapaBubaDiop
По мне, если не экономить память, куда быстрее строить отраженные объекты в том же пространстве с отраженным источником освещения. И все проблемы с отсечением исчезнут.