Современные технологии трехмерной графики

Автор: Антон Бреусов

Источник: http://itc.ua/articles/sovremennye_tehnologii_trehmernoj_grafiki_14781

За последний десяток лет графические карты, позже названные 3D-акселераторами, прошли немалый путь развития -- от первых SVGA-ускорителей, о 3D вообще ничего не знавших, и до самых современных игровых "монстров", берущих на себя все функции, связанные с подготовкой и формированием трехмерного изображения, которое производители именуют "кинематографическим". Естественно, с каждым новым поколением видеокарт создатели добавляли им не только дополнительные мегагерцы и мегабайты видеопамяти, но и множество самых разных функций и эффектов. Давайте же посмотрим, чему, а главное, зачем научились акселераторы последних лет, и что это дает нам, любителям трехмерных игр.



"Нефотореалистичный рендеринг": использование шейдеров для имитации "плоской" картины, нарисованной вручную

Но сначала нелишним будет выяснить, какие действия производит программа (или игра) для того, чтобы получить в итоге трехмерную картинку на экране монитора. Набор таких действий принято называть 3D-конвейером -- каждый этап в конвейере работает с результатами предыдущего (здесь и далее курсивом выделены термины, которые более подробно освещены в нашем "Глоссарии 3D-графики" в конце статьи).

На первом, подготовительном, этапе программа определяет, какие объекты (3D-модели, части трехмерного мира, спрайты и прочее), с какими текстурами и эффектами, в каких местах и в какой фазе анимации нужно отобразить на экране. Также выбираются положение и ориентация виртуальной камеры, через которую зритель смотрит на мир. Весь этот исходный материал, подлежащий дальнейшей обработке, называется 3D-сценой.

Далее наступает очередь собственно 3D-конвейера. Первым шагом в нем является тесселяция -- процесс деления сложных поверхностей на треугольники. Следующие обязательные этапы -- взаимосвязанные процессы трансформации координат точек или вершин, из которых состоят объекты, их освещения, а также отсечения невидимых участков сцены.

Рассмотрим трансформацию координат. У нас имеется трехмерный мир, в котором расположены разные трехмерные же объекты, а в итоге нужно получить двумерное плоское изображение этого мира на мониторе. Поэтому все объекты проходят несколько стадий преобразования в разные системы координат, называемых еще пространствами (spaces). Вначале локальные, или модельные, координаты каждого объекта преобразовываются в глобальные, или мировые, координаты. То есть, используя информацию о расположении, ориентации, масштабе и текущем кадре анимации каждого объекта, программа получает уже набор треугольников в единой системе координат. Затем следует преобразование в систему координат камеры (camera space), с помощью которой мы смотрим на моделируемый мир. После чего отсчет будет начинаться из фокуса этой камеры -- по сути как бы "из глаз" наблюдателя. Теперь легче всего исключить из дальнейшей обработки целиком невидимые (отбраковка, или culling) и "обрезать" частично видимые (отсечение, или clipping) для наблюдателя фрагменты сцены.

Параллельно производится освещение (lighting). По информации о расположении, цвете, типе и силе всех размещенных в сцене источников света рассчитывается степень освещенности и цвет каждой вершины треугольника. Эти данные будут использованы позже при растеризации. В самом конце, после коррекции перспективы, координаты трансформируются еще раз, теперь уже в экранное пространство (screen space).

На этом заканчивается трехмерная векторная обработка изображения и наступает очередь двумерной, т. е. текстурирования и растеризации. Сцена теперь представляет собой псевдотрехмерные треугольники, лежащие в плоскости экрана, но еще с информацией о глубине относительно плоскости экрана каждой из вершин. Растеризатор вычисляет цвет всех пикселов, составляющих треугольник, и заносит его в кадровый буфер. Для этого на треугольники накладываются текстуры, часто в несколько слоев (основная текстура, текстура освещения, детальная текстура и т. д.) и с различными режимами модуляции. Также производится окончательный расчет освещения с использованием какой-либо модели затенения, теперь уже для каждого пиксела изображения. На этом же этапе выполняется окончательное удаление невидимых участков сцены. Ведь треугольники могут располагаться на разном расстоянии от наблюдателя, перекрывать друг друга полностью или частично, а то и пересекаться. Сейчас повсеместно применяется алгоритм с использованием Z-буфера. Результирующие пикселы заносятся в Z-буфер, и как только все изображение будет готово, его можно отображать на экране и начинать строить следующее.



Эффект, имитирующий глубину резкости (фокусное расстояние) реальной кинокамеры: объекты, находящиеся в фокусе, имеют четкий вид, а остальные выглядят размытыми

Теперь, когда нам понятно устройство 3D-конвейера в общем виде, давайте взглянем на архитектурные различия разных поколений 3D-ускорителей. Каждая стадия 3D-конвейера очень ресурсоемка, требует миллионов и миллиардов операций для получения одного кадра изображения, причем двумерные этапы текстурирования и растеризации гораздо "прожорливее" геометрической обработки на ранних, векторных, стадиях конвейера. Так что перенос как можно большего количества стадий в "видеожелезо" благотворно влияет на скорость обработки 3D-графики и значительно разгружает CPU. Первое поколение ускорителей брало на свои плечи только последний этап -- текстурирование и растеризацию, все предыдущие шаги программа должна была просчитать сама с помощью CPU. Рендеринг происходил куда быстрее, чем при полном отсутствии 3D-акселерации, ведь видеокарта уже выполняла наиболее тяжелую часть работы. Но все же с увеличением сложности сцен в 3D-играх программная трансформация и освещение становились узким горлышком, препятствующим увеличению скорости. Поэтому в 3D-акселераторы начиная с первых моделей NVidia GeForce и ATI Radeon был добавлен блок, именуемый T&L-блоком. Как видно из названия, он отвечает за трансформацию и освещение, т. е. теперь и за начальные стадии 3D-конвейера. Его даже правильнее называть TCL-блоком (Transformation-Clipping-Lighting), поскольку отсечение -- тоже его задача. Таким образом, игра, использующая аппаратный T&L, практически полностью освобождает центральный процессор от работы над графикой, а значит, появляется возможность "нагрузить" его другими расчетами, будь то физика или искусственный интеллект.

Казалось бы, все хорошо и чего еще желать? Но не стоит забывать, что любой перенос функций "в железо" означает отказ от гибкости, присущей программным решениям. И с появлением аппаратного T&L у программистов и дизайнеров, желающих реализовать какой-то необычный эффект, осталось лишь три варианта действий: они могли либо полностью отказаться от T&L и вернуться к медленным, но гибким программным алгоритмам, либо пытаться вмешиваться в этот процесс, выполняя постобработку изображения (что не всегда возможно и уж точно очень медленно)... либо ждать реализации нужной функции в следующем поколении видеокарт. Производителей аппаратуры такой расклад тоже не устраивал -- ведь каждое дополнительное T&L-расширение приводит к усложнению графического чипа и "раздуванию" драйверов видеокарт.

Как мы видим, не хватало способа гибко, на "микроуровне", управлять видеокартой. И такая возможность была подсказана профессиональными пакетами для создания 3D-графики. Называется она шейдер (shader). По сути, шейдер -- это небольшая программа, состоящая из набора элементарных операций, часто применяющихся в 3D-графике. Программа, загружаемая в акселератор и непосредственно управляющая работой самого графического процессора. Если раньше программист был ограничен набором заранее определенных способов обработки и эффектов, то теперь он может составлять из простых инструкций любые программы, позволяющие реализовывать самые разные эффекты.



Имитация отражающих поверхностей с помощью специальной текстуры - карты среды, представляющей собой изображение окружающего объект мира

По своим функциям шейдеры делятся на две группы: вершинные (vertex shaders) и пиксельные (pixel shaders). Первые заменяют собой всю функциональность T&L-блока видеокарты и, как видно из названия, работают с вершинами треугольников. В последних моделях акселераторов этот блок фактически убран -- его эмулирует видеодрайвер с помощью вершинных шейдеров. Пиксельные же шейдеры предоставляют гибкие возможности для программирования блока мультитекстурирования и работают уже с отдельными пикселами экрана.

Шейдеры также характеризуются номером версии -- каждая последующая добавляет к предыдущим все новые и новые возможности. Наиболее свежей спецификацией пиксельных и вершинных шейдеров на сегодняшний день является версия 2.0, поддерживаемая DirectX 9, -- на нее и будут ориентироваться как производители акселераторов, так и разработчики новых игр. На их поддержку аппаратурой стоит обращать внимание и пользователям, желающим приобрести современную игровую видеокарту. Тем не менее экспансия игр, построенных на шейдерных технологиях, только начинается, так что и более старые вершинные шейдеры (1.1), и пиксельные (1.3 и 1.4) будут использоваться еще как минимум год, хотя бы для создания сравнительно простых эффектов -- пока DirectX 9-совместимые акселераторы не получат большего распространения.

Первые шейдеры состояли всего из нескольких команд, и их нетрудно было написать на низкоуровневом языке ассемблера. Но с ростом сложности шейдерных эффектов, насчитывающих иногда десятки и сотни команд, возникла необходимость в более удобном, высокоуровневом языке написания шейдеров. Их появилось сразу два: NVidia Cg (C for graphics) и Microsoft HLSL (High Level Shading Language) -- последний является частью стандарта DirectX 9. Достоинства и недостатки этих языков и прочие нюансы будут интересны только программистам, так что подробнее на них мы останавливаться не станем.

Теперь давайте посмотрим, что необходимо для того, чтобы получить все те возможности, которые дает столь полезная технология, как шейдеры последнего поколения. А нужно следующее:

самая свежая версия DirectX, на данный момент это DirectX 9.0b;

видеокарта с поддержкой DirectX 9;

самые свежие драйверы видеокарты (в более старых некоторые функции могут отсутствовать);

игра, использующая все эти возможности.

Тут же хотелось бы развеять вероятные заблуждения. Некоторые трактуют популярный ныне термин "DirectX 9-совместимая видеокарта" следующим образом: "такая видеокарта будет работать и раскрывать все свои возможности только под API DirectX 9", или же "DirectX 9 стоит устанавливать на компьютер только с такой видеокартой". Это не совсем верно. Подобное определение скорее означает: "данная видеокарта обладает возможностями, требуемыми от нее спецификацией DirectX 9".



Имитация меха с помощью шейдеров



Отражение источника света в воде, реализованное с помощью T&L



Три наиболее распространенных способа фильтрации текстур в сравнении (слева направо - билинейная, трилинейная и анизотропная)



Пример реализации воды с помощью вершинных и пиксельных шейдеров



Применение шейдеров для создания эффекта преломления света при прохождении через стекло


Глоссарий 3D-графики

3D API - Набор библиотек, интерфейсов и соглашений для работы с 3D-графикой. Сейчас широко используются два 3D API: открытый и кросс-платформенный OpenGL (Open Graphics Library) и Microsoft Direct3D (он же DirectX Graphics), являющийся частью универсального мультимедийного API DirectX.

3D-акселератор, или 3D-ускоритель (3D-accelerator) - Видеокарта, способная брать на себя обработку трехмерной графики, освобождая таким образом центральный процессор от этой рутинной работы.

3D-конвейер, или конвейер рендеринга (3D-pipeline, или rendering pipeline) - Многоступенчатый процесс преобразования внутренних данных программы в изображение на экране. Обычно включает как минимум трансформацию и освещение, текстурирование и растеризацию.

3D-сцена - Часть виртуального трехмерного мира, подлежащая рендерингу в данный момент времени.

Depth of Field (глубина резкости) - "Киноэффект", имитирующий глубину резкости (фокусное расстояние) реальной кинокамеры, при этом объекты, находящиеся в фокусе, имеют четкий вид, а остальные выглядят размытыми.

Displacement mapping (текстурирование картами смещения) - Метод моделирования мелких деталей рельефа. При его использовании специальной текстурой -- картой смещения -- задается, насколько различные части поверхности будут выпуклыми или вдавленными относительно базового треугольника, к которому применяется этот эффект. В отличие от рельефного текстурирования этот метод является "честным" и действительно изменяет геометрическую форму объекта. Пока только некоторые новейшие 3D-акселераторы непосредственно поддерживают карты смещения.

MIP-mapping - Вспомогательный метод улучшения качества и повышения скорости текстурирования, заключающийся в создании нескольких вариантов текстуры с уменьшенным разрешением (например, 128 128, 64 64, 32 32 и т. д.), называемых MIP-уровнями. По мере удаления объекта будут выбираться все более "мелкие" варианты текстуры.

Motion-blur (он же временной антиалиасинг) - Довольно новая методика более реалистичной передачи движения за счет "смазывания" изображения объектов в направлении их перемещения. Зрители привыкли к данному эффекту, характерному для кино, поэтому без него картинка кажется неживой даже при высоких FPS. Реализуется motion-blur через многократную отрисовку объекта в кадр в разных фазах его движения или же "размазыванием" изображения уже на пиксельном уровне.

Z-буфер (Z-buffer) - Z-буферизация -- один из методов удаления невидимых участков изображения. При его использовании для каждого пиксела на экране в видеопамяти хранится расстояние от этой точки до наблюдателя. Само расстояние называется глубиной сцены, а этот участок памяти -- Z-буфером. При выводе очередного пиксела на экран его глубина сравнивается с сохраненной в Z-буфере глубиной предыдущего пиксела с такими же координатами, и если она больше, то текущий пиксел не рисуется -- он будет невидимым. Если же меньше, то его цвет заносится в буфер кадра (frame buffer), а новая глубина -- в Z-буфер. Таким образом гарантируется перекрывание дальних объектов более близкими.

Альфа-канал (alpha channel) и альфа-смешивание (alpha-blending) - В текстуре наряду с информацией о цвете в RGB-формате для каждого пиксела, может храниться степень его прозрачности, называемая альфа-каналом. При рендеринге цвет нарисованных ранее пикселов будет с разной степенью "проступать" и смешиваться с цветом выводимого пиксела, что позволяет получить изображение с различным уровнем прозрачности. Это и называется альфа-смешиванием. Такой прием используется очень часто: для моделирования воды, стекла, тумана, дыма, огня и прочих полупрозрачных объектов.

Антиалиасинг (antialiasing) - Метод борьбы со "ступенчатым" эффектом и резкими границами полигонов, возникающими из-за недостаточного разрешения изображения. Чаще всего реализуется путем рендеринга изображения в разрешении, гораздо большем установленного, с последующей интерполяцией в нужное. Поэтому антиалиасинг до сих пор очень требователен к объему видеопамяти и скорости 3D-акселератора.

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

Кадровый буфер (frame buffer) - Участок видеопамяти, в котором производится работа по формированию изображения. Обычно используются два (реже три) буфера кадра: один (передний, или front-buffer) отображается на экране, а во второй (задний, или back-buffer) выполняется рендеринг. Как только очередной кадр изображения будет готов, они поменяются ролями: второй буфер будет показан на экране, а первый перерисован заново.

Карты освещенности (lightmap) - Простой и до сих пор часто применяющийся метод имитации освещения, заключающийся в наложении на основную текстуру еще одной -- карты освещенности, светлые и темные места которой соответственно осветляют или затеняют изображение базовой. Карты освещенности рассчитываются заранее, еще на этапе создания 3D-мира, и хранятся на диске. Этот метод хорошо подходит для больших, статически освещенных поверхностей.

Карты среды (environment mapping) - Имитация отражающих поверхностей с помощью специальной текстуры -- карты среды, представляющей собой изображение окружающего объект мира.

Мультитекстурирование (multitexturing) - Наложение нескольких текстур за один проход акселератора. Например, основной текстуры, карты освещенности и карты с детальной текстурой. Современные видеокарты умеют обрабатывать как минимум 3--4 текстуры за раз. Если мультитекстурирование не поддерживается (или необходимо наложить больше слоев текстур, чем это может сделать акселератор "в один прием"), то используется несколько проходов, что, естественно, гораздо медленнее.

Освещение (lighting) - Процесс расчета цвета и степени освещенности пиксела каждого треугольника в зависимости от расположенных рядом источников света с использованием одного из методов затенения. Часто применяются следующие методы:

1. Плоское затенение (flat shading). Треугольники имеют одинаковую освещенность по всей поверхности;

2. Затенение Гуро (Gouraud shading). Информация об уровне освещенности и цвете, рассчитанная для отдельных вершин треугольника, просто интерполируется по поверхности всего треугольника;

3. Затенение Фонга (Phong shading). Освещение рассчитывается индивидуально для каждого пиксела. Наиболее качественный метод.

Пиксел (pixel) - Отдельная точка на экране, минимальный элемент изображения. Характеризуется глубиной цвета в битах, определяющей максимально возможное количество цветов, и собственно значением цвета.

Пространство (space), или система координат - Некоторая часть трехмерного мира, в которой отсчет ведется от какого-то своего начала координат. Обязательно есть система мировых (world) координат, относительно начала которой измеряются положение и ориентация всех других объектов в 3D-мире, при этом у каждого из них есть своя система координат.

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

Рельефное текстурирование (bump mapping) - Эффект придания поверхности шероховатостей рельефа с помощью дополнительной текстуры, называемой картой рельефа (bump map). Геометрия поверхности при этом не меняется, так что эффект хорошо различим только при наличии динамических источников света.

Рендеринг (rendering) - Процесс визуализации трехмерного изображения. Состоит из множества этапов, в совокупности называемых конвейером.

Тексел (texel) - Пиксел, но не экрана, а текстуры. Минимальный ее элемент.

Текстурирование, или наложение текстур (texturing, или texture mapping) - Самый распространенный метод реалистичного моделирования поверхностей -- наложение на них текстур с изображением. При этом, конечно же, учитываются расстояние, перспектива, ориентация треугольника.

Текстура (texture) - Двумерное изображение -- bitmap, "натягиваемое" на 3D-объект. С помощью текстур задаются самые различные параметры материала, из которого состоит объект: его рисунок (наиболее традиционное применение), степень освещенности разных его частей (карта освещенности, или lightmap), способность отражать свет (specular map) и рассеивать его (diffuse map), неровности (bump map) и др.

Тесселяция (tesselation) - Процесс деления сложных полигонов и кривых поверхностей, описанных математическими функциями, на приемлемые для 3D-акселератора треугольники. Шаг этот зачастую необязательный, скажем, 3D-модели в большинстве игр обычно и так уже состоят из треугольников. Но вот, например, закругленные стены в Quake III: Arena -- пример объекта, для которого тесселяция необходима.

Точка, или вершина (vertex) - Точка в пространстве, заданная тремя координатами (x, y, z). Отдельные точки редко используются, но они являются основой для более сложных объектов: линий, треугольников, точечных спрайтов. Кроме самих координат, к точке могут "привязываться" другие данные: координаты текстуры, свойства освещения и тумана и т. д.

Трансформация - Общий термин для обозначения процесса многоступенчатого преобразования 3D-объектов в двумерное изображение на экране. Представляет собой перевод набора вершин из одной системы координат в другую.

Треугольник (triangle) - Практически вся трехмерная графика состоит из треугольников как самых простых и удобных для обработки примитивов -- три точки всегда однозначно задают плоскость в пространстве, чего не скажешь о более сложных многоугольниках. Все другие многоугольники и криволинейные поверхности разбиваются на треугольники (по сути -- плоские участки), котрые затем используются для вычисления освещенности и наложения текстур. Процесс этот называется тесселяцией.

Фильтрация текстур (texture filtering) - Метод улучшения качества текстурирования при изменении расстояния до наблюдателя. Простейший метод -- билинейная (bilinear) фильтрация -- использует усредненное значение цвета четырех смежных текселов текстуры. Более сложный -- трилинейная (trilinear) фильтрация -- задействует также информацию из MIP-уровней. Самый современный и качественный (а заодно и самый медленный) метод -- анизотропная (anisotropic) фильтрация, который подсчитывает результирующее значение, применяя целый набор (обычно от 8 до 32) текселов, расположенных рядом.

Шейдер (шейдер) - Небольшая программа для графического процессора (GPU) акселератора, задающая ему способ обработки трехмерной графики.

Некоторые возможности, реализуемые с помощью шейдеров

1. Оптически точное (попиксельное) освещение и мягкие тени от всех объектов, произвольные модели освещения;

2. Различные эффекты отражения и преломления лучей для моделирования воды, льда, стекла, витражей, подводных бликов и т. д.;

3. Реалистичная рябь и волны на воде;

4. "Кинематографические" эффекты Depth of Field (глубина резкости) и Motion blur;

5. Качественная, детальная анимация скелетных моделей (состоящих из системы управляющих анимацией модели "косточек"), мимика;

6. Так называемый "нефотореалистичный рендеринг" (Non-Photorealistic Rendering, NPR): имитация стилей рисования различных художников, эффект карандашного наброска или классической, рисованной 2D-анимации;

7. Реалистичная имитация ткани, меха и волос;

8. Процедурные текстуры (в том числе анимационные), не требующие затрат CPU и загрузки каждого кадра в видеопамять;

9. Полноэкранные фильтры постобработки изображения: дымка, гало, капли дождя на стекле, шумовой эффект и т. д.;

10. Объемный рендеринг: более реалистичные дым и огонь;