Преобразовать набор текстур и геометрических примитивов в двумерную картинку, которую мы видим на экране, — задача не из легких. Чтобы отобразить один кадр трехмерной игры, графическая плата проделывает массу трудоемких операций. Разбиение трехмерного объекта на примитивы, нанесение на них текстур, применение всех необходимых эффектов — это лишь часть того, чем занимается видеокарта, пока мы наслаждаемся виртуальными приключениями.
Для создания фотореалистичного изображения мало одних только высокополигональных моделей или множества сложных шейдерных эффектов. Здесь не обойтись без операций фильтрации текстур и сглаживания. О них — наш сегодняшний рассказ.
Некоторые термины |
Приводим объяснения некоторых терминов, встречающихся по тексту. Знакомство с этим словариком позволит вам легче ориентироваться в мире современных графических технологий. Пиксель (Pixel) — самый маленький графический элемент, точка на экране. Полигон (Polygon) — пространственный многоугольник. В компьютерной графике чаще всего используется его простейший вариант — треугольник. Видеокарта, получив в свое распоряжение трехмерную модель, разбивает ее на полигоны, и все операции проводятся уже над ними. Тексель (Texel) — мельчайший графический элемент (точка) текстуры. Текстура (Texture) — двумерное (плоское) изображение определенного формата, предназначенное для нанесения на полигон. Чем выше его разрешение, тем четче и детальней картинка. Ширина шины памяти — важная характеристика видеокарты. Чем «шире» шина, тем больше информации она может передать за один такт. |
Максимальная четкость
Перед выводом какого-либо объекта на экран видеокарта должна точно определить цвет каждой его точки. Допустим, надо отобразить деревянный кубик. В наличии: три грани (остальные не видны), расположенные под определенным углом друг к другу, и текстура дерева, которая нанесена на каждую из них. Цвет экранного пикселя будет вычисляться на основе цветов текселей — точек на текстуре. Для грани, которая расположена перпендикулярно оси зрения, все просто: пикселю на дисплее соответствует тексель на текстуре (с учетом достаточного разрешения текстуры и отображения ее в масштабе 1:1). Для двух оставшихся граней ситуация осложняется тем, что они будут изображены под наклоном: в одной точке на экране будут одновременно находиться несколько текселей текстуры. А уж если объект начнет двигаться или вращаться, сложность определения цвета пикселя возрастет еще больше. И здесь уже не обойтись без помощи текстурной фильтрации.
Простейший способ фильтрации текстур — это, так называемый, point sampling. В рамках данного алгоритма каждому пикселю присваивается цвет того текселя, который расположен ближе всего к его центру. Для более или менее однородных текстур с малым количеством цветов это, может быть, и выход. Однако в современной 3D-графике уже давно используются 32-битные изображения, а это свыше четырех миллиардов оттенков.
Если нанести на кубик 32-битную подробную текстуру и затем применить к нему point sampling, исчезнет большая часть деталей, картинка размоется, и на выходе получится непонятно что. Когда размер текстуры меньше размера грани, будет наблюдаться эффект блочности: сразу несколько близлежащих пикселей обретут цвет одного и того же текселя. Взгляните на незабвенный DOOM, и вы поймете, о чем речь. При вращении куба точки начнут мерцать и перескакивать с одного места на другое. Удручающая картина.
К счастью для всех нас, point sampling давно канул в лета. В конце прошлого века он был вытеснен билинейной фильтрацией, которая на тот момент демонстрировала гораздо лучшие результаты.
Билинейная фильтрация (bilinear filtering) несколько отличается от point sampling: она выдает цвет экранного пикселя, аппроксимируя (усредняя) значения цветов четырех текселей текстуры, расположенных ближе всего к его центру. В минусы уходят мерцание точек и блочность изображения, но боковые грани кубика все равно останутся размытыми. Дело в том, что усреднение выполняется корректно лишь для тех объектов, которые расположены параллельно плоскости экрана. Так что ни о какой четкости не может быть и речи.
Трилинейная фильтрация (trilinear filtering) — это, по сути, та же самая билинейная фильтрация, но выполняющаяся на двух соседних MIP-уровнях. Опс... Новый термин. Давайте ненадолго отвлечемся и выясним, что такое эти самые «MIP-уровни».
В современных компьютерных играх текстуры зачастую обладают очень большими размерами. Представьте, к примеру, бесконечную стену, расположенную почти перпендикулярно плоскости экрана. Для той части стены, которая расположена ближе всего к наблюдателю, надо использовать текстуру высокого разрешения. Только тогда будут видны плавные цветовые переходы и всякие мелкие детали. Однако применять ее же для дальнего сегмента, размеры которого в десятки раз меньше самой текстуры, неразумно: корректно провести фильтрацию в этом случае не получится. К тому же шина памяти у видеокарты не резиновая, так что негоже лишний раз нагружать ее ненужными данными.
Здесь на помощь приходит процесс, именуемый MIP-текстурированием (mip-mapping). Его суть проста: в памяти видеокарты создается ряд уменьшенных копий исходной текстуры, каждая следующая — меньше предыдущей. Эти изображения как раз и называются MIP-уровнями. При нанесении текстуры на полигон видеокарта учитывает расстояние от наблюдателя до объекта и выбирает необходимый MIP-уровень. Иначе говоря, находит текстуру подходящих размеров — такую, чтобы в дальнейшем проводить над ней минимум лишних расчетов.
Ну а теперь вернемся к нашей теме обсуждения. У нас есть два соседних MIP-уровня: две текстуры, одна из которых — уменьшенная копия другой. На каждом из них при помощи билинейной фильтрации выбирается окрас пикселя по цветам четырех текселей. Получаются два значения цвета, усреднив которые мы вычислим итоговый цвет пикселя. Качество немного возрастет, но все проблемы билинейной фильтрации останутся. Вдобавок удвоится нагрузка на видеокарту.
Анизотропная фильтрация (anisotropic filtering), которая с успехом применяется до сих пор, одним махом решила все проблемы. При определении цвета точки она использует большое количество текселей, что гарантирует высокое качество картинки. Вдобавок она учитывает положение полигонов по отношению к экрану и не теряется, когда объект приходит в движение. Уровень анизотропной фильтрации определяется числом текселей, которые обрабатываются при вычислении цвета пикселя. Эти значения вам наверняка знакомы: 2x (16 текселей), 4x (32 текселя), 8x (64 текселя) и 16x (128 текселей). При повышении уровня фильтрации возрастает нагрузка на шину данных видеокарты. Однако для современных графических плат это уже несущественно.
Проблема грубых границ
Итак, видеокарта точно рассчитала цвета всех пикселей, применила все необходимые спецэффекты и вывела наш с вами кубик на экран. Все хорошо, вот только боковые ребра выглядят как-то странно. Вместо прямых линий отображаются ступеньки из множества углов. Виной тому пресловутый aliasing, который в народе также известен как «лесенка».
Основная причина его возникновения кроется в несовершенстве наших мониторов. Сколько ни увеличивай разрешение экрана, картинка на нем все равно будет состоять их точек определенных размеров. Вот и получается, что мы хотим вывести на дисплей окружность, а получаем замкнутую последовательность из отдельных пикселей. Здесь можно провести аналогию с мозаикой: издалека вся она выглядит цельной картиной, но если присмотреться или подойти поближе, будут видны составляющие отдельные кирпичики.
А теперь все то же самое, но с точки зрения 3D-технологий. В режиме «без сглаживания» цвет экранной точки соответствует цвету того объекта, в котором находится ее центр. Простейший пример — граница черного и белого. Когда центр пикселя попадает в черную зону, он окрашивается в ее цвет без учета процентного соотношения белого и черного цветов. При движении объекта все еще хуже: пограничные точки начинают мерцать, становясь то белыми, то черными.
Как с этим бороться? Одно из очевидных решений — обрабатывать изображение таким образом, чтобы «лесенка» не была заметна при обычных разрешениях, то есть повышалась точность передачи оттенков на границах полигонов. Собственно, именно этим и занимается anti-aliasing, или полноэкранное сглаживание.
Впервые некое подобие этого алгоритма продемонстрировала компания 3dfx на примере ее легендарной видеокарты Voodoo. Этот видеоадаптер рисовал полупрозрачные линии на границах объектов, тем самым пытаясь сгладить цветовые переходы. К сожалению, результат подобной процедуры выглядел удручающе. Инженеры 3dfx вскоре осознали свою ошибку и предложили принципиально новый алгоритм, получивший название supersampling (SSAA). Впервые он был использован в видеокартах Voodoo 4/5.
Принцип работы SSAA прост, как все гениальное: кадр сначала строится в увеличенном разрешении, а при выводе на экран сжимается до требуемых размеров. Уровень сглаживания показывает, во сколько раз увеличивается площадь изображения относительно первоначального. Таким образом, если кадр с разрешением 800х600 сглаживается с помощью 4x supersampling, видеокарта проводит все этапы построения изображения на картинке с размерами 1600х1200. При переходе к изначальному разрешению цвета четырех точек, соответствующих одному исходному пикселю, усредняются. Таким образом, пиксель, находящийся на границе черного и белого объектов, может быть светло-серым, серым и темно-серым. Все бы ничего, но нагрузка на видеокарту при использовании метода возрастает неимоверно. Хотите четырехкратный supersampling? Миритесь с четырехкратным падением производительности. К счастью, SSAA — это лишь первый удачный опыт разработчиков видеокарт на пути к идеальному сглаживанию.
Направленное действие
Главный недостаток supersampling в том, что он делает много лишней работы, сглаживая не границы объектов, а все изображение целиком. Разработчики долго корпели над решением этой проблемы и в итоге создали новый, более экономичный метод. Он получил название multisampling (MSAA). Первой видеокартой, которая научилась использовать MSAA, стала революционная GeForce 3 от NVIDIA.
При использовании multisampling кадр все так же строится в увеличенном разрешении, однако над пикселями, находящимися внутри полигонов, никаких расчетов не производится. Другое дело — пиксели на границах объектов. Для них в зависимости от уровня сглаживания строятся две, четыре и более дополнительных точек (sub-samples), по которым и определяется итоговый цвет пикселя. Уровень MSAA соответствует количеству используемых точек: 2x — две, 4x — четыре, и так далее.
Помимо вышеперечисленных режимов GeForce 3 поддерживала также Quincunx и 4х 9-tap. В них при расчете цвета пикселя учитывались цвета не только его sub-samples, но и соседних пикселей. Проще говоря, соседние пиксели также оказывали влияние на конечный цвет, но с меньшим коэффициентом влияния. Картинка в результате получалась красивой, но смазанной.
Следующим знаменательным событием стало появление видеокарты Radeon 9700 и сопутствующей ей технологии ATI Smoothvision 2.0 — именно она повысила планку качества сглаживания, достигаемого при помощи multisampling.
Если в более ранних версиях алгоритма дополнительные точки в режиме 4х располагались самым простым образом (по углам от квадрата, вписанного в пиксель), то ATI повернула этот квадрат на 30 градусов. В чем же секрет успеха?
Дело в том, что разные искажения картинки бросаются в глаза по-разному. И особенно заметны они на «почти вертикальных» и «почти горизонтальных» линиях. А ведь они обычно и составляют значительную часть 3D-сцены. В случае классического расположения дополнительных точек такие линии практически не сглаживались — и именно эту проблему успешно решил метод, предложенный ATI. С выходом GeForce 6800 NVIDIA начала применять аналогичную технологию: «решетка» также повернулась на 30 градусов, только в противоположном направлении.
С этого момента multisampling на долгое время прекратил свое развитие. Были доведены до ума некоторые алгоритмы, появились методики сглаживания прозрачных текстур, однако существенные изменения внесла лишь GeForce 8800.
Передовые методы
Вместе с видеокартами GeForce восьмой серии публике был представлен режим сглаживания coverage sampling (CSAA). Инженеры NVIDIA провели ряд исследований, которые показали, что при расчете цвета «пограничного» пикселя важны не столько значения цвета соседних пикселей, сколько точная информация о расположении пикселя относительно цветовой границы.
В случае CSAA вокруг центра «пограничного» пикселя располагаются не только добавочные точки, определяющие значение цвета, но и так называемые coverage-samples (значения перекрытия), передающие информацию о своем местонахождении. На основе сведений, получаемых от значений перекрытия, видеокарта делает выводы о соотношении площадей объектов, пересекающихся в данном пикселе. Учитывая эти данные, а также цвета перекрывающихся объектов, карта высчитывает итоговый цвет пикселя.
Настройки сглаживания в панели управления NVIDIA ForceWare | |||
Режим | Тип сглаживания | Кол-во sub-samples | Кол-во значений перекрытия |
2х | MSAA | 2 | - |
4х | MSAA | 4 | - |
8х | CSAA | 4 | 8 |
8xQ | MSAA | 8 | - |
16x | CSAA | 4 | 16 |
16xQ | CSAA | 8 | 16 |
При одинаковых степенях сглаживания coverage sampling незначительно уступает multisampling по качеству, зато ресурсов новый метод потребляет намного меньше. 8-кратный MSAA требует увеличения исходного кадра в восемь раз, что с трудом дается даже платам GeForce 8800 GTX/Ultra. А информация о том, попадает ли sub-sample на полигон, выражается всего лишь двумя значениями — да или нет, 1 или 0. Это серьезно экономит память видеокарты и снижает нагрузку на шину данных.
В драйверах ForceWare, предназначенных для восьмого поколения видеокарт NVIDIA, появилось четыре новых настройки сглаживания. Заметим, что полноценный 8-кратный multisampling обеспечивают лишь режимы 8xQ и 16xQ. Они выдают картинку очень высокого качества, но расплатой за красоту стало сильное падение производительности. Режимы 8x и 16x используют только четыре дополнительных точки цвета, а различаются количеством задействованных значений перекрытия: 8 и 16 соответственно.
В ответ на CSAA ATI (точнее, уже AMD) наделила видеокарты семейства Radeon HD 2000 целым рядом новых режимов сглаживания. В Catalyst Control Center появились четыре типа так называемых фильтров: box, narrow-tent, wide-tent, edge-detect. Box — это обычный multisampling, способный работать в режимах 2х, 4х и 8х. Narrow-tent и wide-tent — всего лишь идейные наследники технологии NVIDIA Quincunx: на итоговый цвет пикселя влияют дополнительные точки соседних пикселей.
Настройки сглаживания AMD Catalyst Control Center | ||
Режим | Кол-во внутренних sub-samples | Кол-во внешних sub-samples |
2х narrow-tent | 2 | 2 |
4x narrow-tent | 4 | 2 |
8x narrow-tent | 8 | 4 |
2x wide-tent | 2 | 4 |
4x wide-tent | 4 | 4 |
8x wide-tent | 8 | 8 |
Но самым интересным, безусловно, стал фильтр edge-detect, появившийся только в драйверах Catalyst 7.7. Алгоритм edge-detect находит пиксель, попадающий на границу резкого цветового перехода, и увеличивает количество sub-samples, по которым рассчитывается значение цвета этого пикселя. При этом «пограничные» точки, в которых вариация цветов незначительна, обрабатываются обычным multisampling. Например, в режиме 4х edge-detect количество дополнительных точек для пикселей с контрастными переходами возрастает до двенадцати, а для остальных это значение равно четырем. При режиме 8х edge-detect оба значения удваиваются. По качеству сглаживания технология не уступает coverage sampling, а зачастую и превосходит его. Увы, но при использовании edge-detect наблюдается чудовищное падение производительности. Отметим, что для использования альтернативных режимов сглаживания, вроде CSAA и narrow-tent, необходимо форсировать их из драйверов, так как почти все игры по умолчанию сглаживают картинку посредством multisampling.
И последнее: в грядущем DirectX 10.1 алгоритмы сглаживания стандартизированы, а все DX10.1-карты обязаны их поддерживать. Похоже, что вездесущая Microsoft положила конец гонке технологий, а разница в качестве сглаживания между видеокартами AMD и NVIDIA стала уделом прошлого.