Конвейер компьютерной графики , также известный как конвейер рендеринга или графический конвейер , представляет собой структуру в компьютерной графике, которая описывает необходимые процедуры для преобразования трехмерной (3D) сцены в двухмерное (2D) представление на экране. [1] После того, как 3D-модель сгенерирована, графический конвейер преобразует модель в визуально воспринимаемый формат на дисплее компьютера. [2] Из-за зависимости от конкретного программного обеспечения , конфигураций оборудования и желаемых атрибутов отображения универсально применимого графического конвейера не существует. Тем не менее, графические прикладные программные интерфейсы (API), такие как Direct3D , OpenGL и Vulkan, были разработаны для стандартизации общих процедур и контроля графического конвейера данного аппаратного ускорителя. Эти API предоставляют уровень абстракции над базовым оборудованием, освобождая программистов от необходимости писать код, явно нацеленный на различные графические аппаратные ускорители, такие как AMD , Intel , Nvidia и другие.
Модель графического конвейера обычно используется при рендеринге в реальном времени. Часто большинство этапов конвейера реализуются на аппаратном уровне, что позволяет проводить специальные оптимизации . Термин «конвейер» используется в аналогичном смысле для конвейера в процессорах : отдельные этапы конвейера выполняются параллельно, пока любой данный этап имеет то, что ему нужно.
3D-конвейер обычно относится к наиболее распространенной форме компьютерного 3-мерного рендеринга, называемого 3D-полигональным рендерингом [ требуется ссылка ] , в отличие от трассировки лучей и рейкастинга . В рейкастинге луч исходит из точки, где находится камера, и если этот луч попадает на поверхность, то вычисляется цвет и освещение точки на поверхности, куда попадает луч. В 3D-полигональном рендеринге происходит обратное — вычисляется область, которая задана камерой, а затем лучи создаются из каждой части каждой поверхности, заданной камерой, и трассируются обратно к камере. [3]
Графический конвейер можно разделить на три основные части: приложение, геометрия и растеризация. [4]
Шаг приложения выполняется программным обеспечением на главном процессоре ( ЦП ). На шаге приложения в сцену вносятся изменения по мере необходимости, например, при взаимодействии пользователя с устройствами ввода или во время анимации. Новая сцена со всеми ее примитивами , обычно треугольниками, линиями и точками, затем передается на следующий шаг в конвейере.
Примерами задач, которые обычно выполняются на этапе приложения, являются обнаружение столкновений , анимация, морфинг и методы ускорения с использованием схем пространственного подразделения, таких как Quadtrees или Octrees . Они также используются для уменьшения объема основной памяти, требуемой в данный момент времени. «Мир» современной компьютерной игры намного больше того, что может поместиться в памяти за один раз.
Шаг геометрии (с конвейером Geometry ), который отвечает за большинство операций с полигонами и их вершинами (с конвейером Vertex ), можно разделить на следующие пять задач. Это зависит от конкретной реализации того, как эти задачи организованы как фактические параллельные шаги конвейера.
Вершина (множественное число: вершины) — это точка в мире. Для соединения поверхностей используется множество точек. В особых случаях облака точек рисуются напрямую, но это все еще исключение.
Треугольник — наиболее распространенный геометрический примитив компьютерной графики. Он определяется тремя вершинами и вектором нормали — вектор нормали служит для указания передней грани треугольника и является вектором, перпендикулярным поверхности. Треугольник может быть снабжен цветом или текстурой ( изображением, «наклеенным» поверх него). Треугольники предпочтительнее прямоугольников, потому что их три точки всегда находятся в одной плоскости .
Система координат мира — это система координат, в которой создается виртуальный мир. Она должна соответствовать нескольким условиям, чтобы следующая математика была легко применима:
То, как определяется единица системы координат, остается на усмотрение разработчика. Поэтому то, соответствует ли единичный вектор системы в действительности одному метру или ангстрему, зависит от приложения.
Объекты, содержащиеся в сцене (дома, деревья, автомобили), часто проектируются в их системе координат объекта (также называемой системой координат модели или локальной системой координат) по причинам более простого моделирования. Чтобы назначить этим объектам координаты в мировой системе координат или глобальной системе координат всей сцены, координаты объекта преобразуются с помощью перевода, поворота или масштабирования. Это делается путем умножения соответствующих матриц преобразования . Кроме того, из одного объекта можно сформировать несколько по-разному преобразованных копий, например, лес из дерева; этот метод называется instancing.
Во-первых, нам нужны три матрицы вращения , а именно по одной для каждой из трех осей самолета (вертикальная ось, поперечная ось, продольная ось).
Мы также используем матрицу перемещения, которая перемещает самолет в нужную точку нашего мира: .
Теперь мы могли бы вычислить положение вершин самолета в мировых координатах, последовательно умножая каждую точку на эти четыре матрицы. Поскольку умножение матрицы на вектор довольно затратно (требует много времени), обычно выбирают другой путь и сначала умножают четыре матрицы друг на друга. Умножение двух матриц еще более затратно, но должно быть выполнено только один раз для всего объекта. Умножения и эквивалентны. После этого полученную матрицу можно было бы применить к вершинам. Однако на практике умножение на вершины по-прежнему не применяется, но матрицы камеры (см. ниже) определяются первыми.
Порядок, в котором применяются матрицы, важен, поскольку умножение матриц не является коммутативным . Это также относится к трем поворотам, что можно продемонстрировать на примере: точка (1, 0, 0) лежит на оси X, если повернуть ее сначала на 90° вокруг оси X, а затем вокруг оси Y, она окажется на оси Z (поворот вокруг оси X не влияет на точку, которая находится на оси). Если, с другой стороны, сначала повернуть вокруг оси Y, а затем вокруг оси X, полученная точка будет расположена на оси Y. Сама последовательность произвольна, пока она всегда одна и та же. Последовательность с x, затем y, затем z (крен, тангаж, курс) часто является наиболее интуитивно понятной, поскольку поворот заставляет направление компаса совпадать с направлением «носа».
Также существуют два соглашения для определения этих матриц, в зависимости от того, хотите ли вы работать с векторами-столбцами или векторами-строками. Различные графические библиотеки имеют здесь разные предпочтения. OpenGL предпочитает векторы-столбцы, векторы-строки DirectX . Решение определяет, с какой стороны векторы точек должны умножаться на матрицы преобразования. Для векторов-столбцов умножение выполняется справа, т. е . , где v out и v in — векторы-столбцы 4x1. Конкатенация матриц также выполняется справа налево, т. е., например , при первом повороте, а затем сдвиге.
В случае векторов-строк это работает ровно наоборот. Умножение теперь происходит слева, как и в случае векторов-строк 1x4, а конкатенация происходит, когда мы также сначала вращаем, а затем перемещаем. Матрицы, показанные выше, действительны для второго случая, в то время как матрицы для векторов-столбцов транспонируются. Применяется правило [5] , которое для умножения с векторами означает, что вы можете изменить порядок умножения, транспонировав матрицу.
В цепочке матриц каждое преобразование определяет новую систему координат, что позволяет использовать гибкие расширения. Например, пропеллер самолета, смоделированный отдельно, может быть прикреплен к носу самолета посредством трансляции, которая только смещается из системы координат модели в систему координат пропеллера. Для визуализации самолета сначала вычисляется его матрица преобразования для преобразования точек, а затем матрица модели пропеллера умножается на матрицу самолета для точек пропеллера. Эта вычисленная матрица известна как «мировая матрица», необходимая для каждого объекта в сцене перед визуализацией. Затем приложение может динамически изменять эти матрицы, например, обновлять положение самолета с каждым кадром на основе скорости.
Матрица, рассчитанная таким образом, также называется матрицей мира . Она должна быть определена для каждого объекта в мире перед рендерингом. Приложение может вносить здесь изменения, например, изменять положение самолета в зависимости от скорости после каждого кадра.
В дополнение к объектам сцена также определяет виртуальную камеру или просмотрщик, который указывает положение и направление обзора, относительно которого визуализируется сцена. Сцена преобразуется таким образом, что камера находится в начале координат и смотрит вдоль оси Z. Полученная система координат называется системой координат камеры, а преобразование называется преобразованием камеры или преобразованием вида .
Zaxis = normal(cameraPosition - cameraTarget)
Xaxis = normal(cross(cameraUpVector, Zaxis))
Yaxis = cross(Zaxis, Xaxis )
Шаг 3D-проекции преобразует объем вида в куб с координатами угловой точки (-1, -1, 0) и (1, 1, 1); Иногда также используются другие целевые объемы. Этот шаг называется проекцией , хотя он преобразует объем в другой объем, поскольку полученные координаты Z не сохраняются в изображении, а используются только в Z-буферизации на более позднем шаге растрирования. В перспективной иллюстрации используется центральная проекция . Чтобы ограничить количество отображаемых объектов, используются две дополнительные плоскости отсечения; Таким образом, визуальный объем представляет собой усеченную пирамиду ( frustum ). Параллельная или ортогональная проекция используется, например, для технических представлений, поскольку она имеет то преимущество, что все параллели в пространстве объектов также параллельны в пространстве изображения, а поверхности и объемы имеют одинаковый размер независимо от расстояния от зрителя. Карты используют, например, ортогональную проекцию (так называемые ортофото ), но косые изображения ландшафта не могут быть использованы таким образом - хотя технически их можно визуализировать, они кажутся настолько искаженными, что мы не можем их использовать. Формула для расчета матрицы перспективного картирования:
Причины, по которым здесь необходимо указать наименьшее и наибольшее расстояние, заключаются, с одной стороны, в том, что это расстояние делится для достижения масштабирования сцены (более удаленные объекты меньше на перспективном изображении, чем близкие объекты), а с другой стороны, для масштабирования значений Z до диапазона 0..1 для заполнения Z-буфера . Этот буфер часто имеет разрешение всего 16 бит, поэтому ближние и дальние значения следует выбирать осторожно. Слишком большая разница между ближним и дальним значением приводит к так называемому Z-борьбе из-за низкого разрешения Z-буфера. Из формулы также видно, что ближнее значение не может быть равно 0, поскольку эта точка является точкой фокусировки проекции. В этой точке нет изображения.
Для полноты картины приведем формулу параллельной проекции (ортогональной проекции):
Из соображений эффективности матрицы камеры и проекции обычно объединяются в матрицу преобразования, так что система координат камеры опускается. Результирующая матрица обычно одинакова для одного изображения, в то время как мировая матрица выглядит по-разному для каждого объекта. Поэтому на практике вид и проекция предварительно вычисляются, так что во время отображения приходится адаптировать только мировую матрицу. Однако возможны более сложные преобразования, такие как смешивание вершин. Также могут быть выполнены свободно программируемые геометрические шейдеры , которые изменяют геометрию.
На этапе фактического рендеринга вычисляется мировая матрица * матрица камеры * матрица проекции, которая затем окончательно применяется к каждой отдельной точке. Таким образом, точки всех объектов переносятся непосредственно в систему координат экрана (по крайней мере, почти, диапазон значений осей по-прежнему составляет -1..1 для видимого диапазона, см. раздел «Окно-Вьюпорт-Преобразование»).
Часто сцена содержит источники света, размещенные в разных позициях, чтобы сделать освещение объектов более реалистичным. В этом случае коэффициент усиления для текстуры вычисляется для каждой вершины на основе источников света и свойств материала, связанных с соответствующим треугольником. На более позднем этапе растеризации значения вершин треугольника интерполируются по его поверхности. Общее освещение (окружающий свет) применяется ко всем поверхностям. Это рассеянная и, таким образом, независимая от направления яркость сцены. Солнце является направленным источником света, который можно считать бесконечно далеким. Освещенность, оказываемая солнцем на поверхность, определяется путем формирования скалярного произведения направленного вектора от солнца и вектора нормали поверхности. Если значение отрицательное, поверхность обращена к солнцу.
Только примитивы, находящиеся внутри визуального объема, должны быть растрированы (отрисованы). Этот визуальный объем определяется как внутренняя часть усеченной пирамиды , фигуры в виде пирамиды с обрезанной вершиной. Примитивы, которые полностью находятся за пределами визуального объема, отбрасываются; это называется отсечением усеченной пирамиды . Дальнейшие методы отсечения, такие как отсечение задней грани, которое уменьшает количество рассматриваемых примитивов, теоретически могут быть выполнены на любом этапе графического конвейера. Примитивы, которые находятся только частично внутри куба, должны быть отсечены по кубу. Преимущество предыдущего этапа проецирования заключается в том, что отсечение всегда происходит по одному и тому же кубу. Только - возможно отсеченные - примитивы, которые находятся внутри визуального объема, передаются на последний этап.
Для вывода изображения в любую целевую область (область просмотра) экрана необходимо применить другое преобразование — преобразование Окно-Область просмотра . Это сдвиг с последующим масштабированием. Полученные координаты являются координатами устройства вывода. Область просмотра содержит 6 значений: высоту и ширину окна в пикселях, верхний левый угол окна в координатах окна (обычно 0, 0), а также минимальное и максимальное значения для Z (обычно 0 и 1).
На современном оборудовании большинство шагов вычисления геометрии выполняются в вершинном шейдере . В принципе, он свободно программируется, но обычно выполняет как минимум преобразование точек и расчет освещенности. Для интерфейса программирования DirectX использование пользовательского вершинного шейдера необходимо с версии 10, в то время как в более старых версиях по-прежнему используется стандартный шейдер.
Шаг растеризации — это последний шаг перед конвейером фрагментного шейдера, с помощью которого растеризуются все примитивы . На шаге растеризации из непрерывных примитивов создаются дискретные фрагменты.
На этом этапе графического конвейера точки сетки также называются фрагментами, для большей различимости. Каждый фрагмент соответствует одному пикселю в буфере кадра, а это соответствует одному пикселю экрана. Они могут быть окрашены (и, возможно, освещены). Кроме того, необходимо определить видимый, более близкий к наблюдателю фрагмент в случае перекрывающихся полигонов. Z-буфер обычно используется для этого так называемого определения скрытой поверхности . Цвет фрагмента зависит от освещенности, текстуры и других свойств материала видимого примитива и часто интерполируется с использованием свойств вершин треугольника. Где это возможно, фрагментный шейдер (также называемый пиксельным шейдером ) запускается на этапе растрирования для каждого фрагмента объекта. Если фрагмент виден, теперь его можно смешать с уже существующими значениями цвета в изображении, если используется прозрачность или мультисэмплинг. На этом этапе один или несколько фрагментов становятся пикселем.
Чтобы пользователь не видел постепенной растеризации примитивов, применяется двойная буферизация. Растеризация выполняется в специальной области памяти. После полной растеризации изображения оно копируется в видимую область памяти изображения.
Все используемые матрицы невырожденные и, следовательно, обратимые. Поскольку умножение двух невырожденных матриц создает еще одну невырожденную матрицу, вся матрица преобразования также обратима. Обратная требуется для пересчета мировых координат из экранных координат — например, для определения по положению указателя мыши объекта, на котором был сделан щелчок. Однако, поскольку экран и мышь имеют только два измерения, третье неизвестно. Поэтому луч проецируется в позицию курсора в мир, а затем определяется пересечение этого луча с полигонами в мире.
Классические графические карты все еще относительно близки к графическому конвейеру. С ростом требований к GPU ограничения постепенно снимались, чтобы создать большую гибкость. Современные графические карты используют свободно программируемый, управляемый шейдерами конвейер, который обеспечивает прямой доступ к отдельным этапам обработки. Чтобы разгрузить основной процессор, дополнительные этапы обработки были перемещены в конвейер и GPU.
Наиболее важными шейдерными блоками являются вершинные шейдеры , геометрические шейдеры и пиксельные шейдеры.
Введен Unified Shader для полного использования всех блоков. Это дает единый большой пул блоков шейдеров. По мере необходимости пул делится на различные группы шейдеров. Поэтому строгое разделение между типами шейдеров больше не является полезным .
Также возможно использовать так называемый compute-shader для выполнения любых вычислений вне отображения графики на GPU. Преимущество в том, что они работают очень параллельно, но есть ограничения. Эти универсальные вычисления также называются вычислениями общего назначения на графических процессорах , или сокращенно GPGPU .
Сетчатые шейдеры — это недавнее дополнение, призванное преодолеть узкие места фиксированной компоновки геометрического конвейера. [6]