4.2. Рендеринг
Не претендуя на полноту объяснения всех хитростей технологии создания трехмерных изображений, обсудим некоторые ее основные моменты и поясним связанные с ними термины.
Вполне понятно, что рендеринг модели может производиться только поэлементно. Результатом тесселяции является набор многоугольников (обычно четырехугольников или треугольников, с которыми манипулировать проще), аппроксимирующих поверхности объектов. Плоское растровое представление должно формироваться с учетом взаимного расположения элементов (их поверхностей) — те из них, что ближе к наблюдателю, естественно, будут перекрывать изображение более удаленных элементов. Многоугольники, оставшиеся после удаления невидимых поверхностей, сортируются по глубине: реалистичную картину удобнее получать, начиная обработку с наиболее удаленных элементов. Для учета взаимного расположения применяют так называемый Z-буфер, названный по имени координаты третьего измерения (X и Y — координаты в плоскости экрана). Этот буфер представляет собой матрицу ячеек памяти, каждая из которых соответствует ячейке видеопамяти, хранящей цвет одного пиксела. В процессе рендеринга для очередного элемента формируется его растровое изображение (bitmap) и для каждого пиксела этого фрагмента вычисляется параметр глубины Z (координатой его можно назвать лишь условно). В видеопамять этот фрагмент поступает с учетом результата попикселного сравнения информации из Z-буфера, с его собственными значениями. Если глубина Z данного пиксела фрагмента оказывается меньше величины Z той ячейки видеопамяти, куда должен попасть этот фрагмент, это означает, что выводимый элемент оказался ближе к наблюдателю, чем ранее обработанные, отображение которых уже находится в видеопамяти. В этом случае выполняется модификация пиксела видеопамяти, а в ячейку Z-буфера видеопамяти помещается новая величина, взятая от данного фрагмента (что подразумевается под модификацией, поясним позже). Если же результат сравнения иной, то текущий пиксел фрагмента оказывается перекрытым прежде сформированными элементами, и его параметр глубины в Z-буфер не попадет. Однако цвет пиксела видеопамяти, возможно, все равно придется модифицировать: ведь перекрывающий элемент может оказаться прозрачным. Итак, Z-буфер позволяет определить взаимное расположение текущего и ранее сформированного пиксела, которое учитывается при формировании нового значения пиксела в видеопамяти. От разрядности Z-буфера зависит разрешающая способность графического конвейера по глубине. При малой разрядности (например, 8 бит) для близко расположенных элементов рассчитанные значения Z могут совпасть, в результате картина перекрытий исказится. Большая разрядность буфера требует большого объема памяти, доступного графическому процессору. По нынешним меркам минимальная разрядность Z-буфера — 16 бит, профессиональные графические системы используют 32-битный Z-буфер.
Теперь обсудим модификацию цвета пиксела видеопамяти. В общем случае у нас есть два значения цвета — С1 для того образа, который «ближе», С2 для того, что «дальше» (по Z-параметру). Результирующий цвет определяется обоими значениями и свойством «прозрачности» ближнего. Для получения нового значения цвета обычно используют так называемый альфа-блендиш (Alpha-blending). Мерой прозрачности объекта является коэффициент а (0 < а < 1), единица соответствует полной непрозрачности. Результирующий цвет пиксела вычисляется по формуле С = С1ха+С2х(1-а), причем за этой формулой стоит в три раза больше операций, поскольку цвет определяется тремя значениями базисных цветов (R, G и В). Ну и нетрудно догадаться, что для реализации данного метода требуется и свой альфа-буфер с количеством ячеек, по меньшей мере равным числу пикселов на экране. Часто 8-битный коэффициент прозрачности для каждого пиксела хранят прямо в видеопамяти: при 24-битном кодировании цвета от двойного слова (32 бит), выделяемого на пиксел для упрощения адресации и ускорения обмена, как раз остается 8 бит. Такой формат видеопамяти называют RGBA.
Объекты, входящие в модель и представляющие их элементы (тессели), не обязательно однородны по цвету: на их поверхности могут быть наложены текстуры — растровые картинки, исходно плоские, но как бы к ним приклеенные. Текстура состоит из элементов, называемых текселами (Texel — Texture Element). Здесь уместна аналогия с созвучным термином пиксел (Picture Element), который относится к элементу изображения на экране и его образу в видеопамяти. Текстуры (в виде матриц текселов) хранятся в памяти. Для каждого многоугольника-частицы отображаемой поверхности вычисляется соответствующий ему участок текстуры — тоже многоугольник. Далее этот участок должен быть отображен в видеопамять — текселы должны быть отображены в пикселы. Что должно происходить с рисунком текстуры при изменении положения плоскости, на которую она наносится, легко представить, повертев перед глазами спичечный коробок и наблюдая за этикеткой. Кроме искажения формы при поворотах учитываются и изменения размера картинки текстуры при приближении и удалении объекта от наблюдателя, а также перспектива. Масштабирование и повороты текстур могут приводить к различным искажениям: к примеру, увеличенное и повернутое изображение гладкого горизонтального (или вертикального) отрезка превратится в грубую ступенчатую линию. Кроме того, могут появляться «рваные» края у текстур по линиям их сопряжения. Для улучшения качества представления одной и той же текстуры в разном масштабе применяют так называемый MlPmap — набор нескольких версий одной и той же текстуры, выполненных с различным разрешением (обычно очередная версия имеет размер в четверть от предыдущей). При рендеринге выбирается та версия, у которой масштаб ближе к требуемому. Дефекты, обусловленные растровым представлением текстуры (векторные изображения в отличие от растровых масштабируются и трансформируются без потери информации), могут быть устранены путем фильтрации — билинейной, или более сложной — трилинейной. При билинейной фильтрации (Bilinear Filtering) цвет очередного пиксела, записываемого в видеопамять, определяется с учетом цветов прилегающих к нему четырех соседних пикселов. Трилинейная фильтрация (Trilinear Filtering) сложнее — здесь билинейная фильтрация выполняется дважды для двух соседних уровней MlPmap, ближайших к требуемому масштабу. Окончательный цвет пиксела определяется интерполяцией этих двух результатов.
Наложение текстур при всех хлопотах, связанных с его реализацией, позволяет упростить описание объектов и ускорить их рендеринг. Так, например, фасад кирпичного здания можно построить «по-честному», задав поверхности всех кирпичиков, оконных и дверных проемов и т. п.. Но если это изображение нужно получить, например, в игре, где воображаемый наблюдатель должен приближаться и удаляться от стены, а также менять угол зрения достаточно быстро, то проще представить ее одной плоскостью с «нарисованными» кирпичами и прочими деталями (вспомним каморку папы Карло). На одни и те же объекты часто накладывают несколько текстур — для имитации освещенности, теней, отражений, рельефа и т. д.
И, наконец, когда все объекты, расположенные на сцене, уже прорисованы, для большего эффекта объемности можно ввести эффект атмосферной перспективы — сильно удаленные объекты подернуть дымкой (туманом). Это несложно сделать, используя для попикселного смешивания цветов тумана и объектов информацию о глубине из Z-буфера: чем больше Z, тем больше на результирующий цвет влияет туман и меньше цвет исходного пиксела. В последнее время стали использовать и трехмерные текстуры (3D textures) — трехмерные массивы пикселов. Они позволяют, например, имитировать объемный туман, динамические источники света (языки пламени).
4.3. Реализация трехмерной графики
Теперь примерим задачи трехмерной графики к возможностям рядового PC-совместимого компьютера. Реализация рендеринга требует значительного объема вычислений и оперирования с большими объемами информации, причем конечная цель потока обработанных данных — видеопамять графического адаптера. Еще с 2В-графикой стало ясно, что центральный процессор х86 (даже с расширением ММХ) не способен быстро формировать движущиеся изображения, а шина расширения (даже PCI) является «узким горлышком» для потоков данных, участвующих в видеопостроениях. Решением проблемы вывода трехмерной графики, как и раньше, явилось усиление «интеллекта» графической карты — появились 3B-акселераторы, реализующие значительную часть графического конвейера. На долю центрального процессора (возможно, с графическим сопроцессором) обычно выпадает начало конвейера (от трансформации до тесселяции), а его окончание (растеризация) выполняется акселератором графической карты.