Мысли о FSAA

18 декабря 2003, четверг 01:01
Serj для раздела Лаборатория
Попытка описать то, каким должно быть ... это сглаживание.

С О Д Е Р Ж А Н И Е

и как есть в .

рис.1 желаемое изображение

рис.2 добавлена сетка режимов и

рис.3 что получается без FSAA

рис.4 для FSAA 2x2

Что происходит? При включении FSAA при двукратном повышением точности формирования изображения левая линяя просто исчезает! Дело в том, что при переходе на 2х представление сетка сдвигается относительно базовой. Т.о., две точки экранного буфера, из которых в последствии сформируется одна точка на экране монитора, стоят симметрично относительно базовой, но, и это важно не совпадают с базовой сеткой. Ну и выходит, если линия достаточно тонкая, тоньше 1/2 шага базовой сетки, то она может просто исчезнуть. Это есть в графике, но для текста сие просто катастрофа. Если применен режим FSAA с нечетным количеством точек, то подобного дефекта нет. Минимальный режим, это 3х3 и его скорость.... (без комментариев).

Что, от FSAA так мало пользы? А как же столь значимое общее повышение качества картинки? Нет, в FSAA есть и полезные свойства, он повышает качество изображения за счет 'вычисления' границ пикселов. Помните, я выше говорил о точном позиционировании?

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

рис.5 полосатое изображение

рис.6 результат FSAA 2x2

рис.7 без FSAA для нечетных отсчетов

рис.8 без FSAA для четных отсчетов

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

Сложность аппаратной поддержки FSAA

Для поддержки режима FSAA, например 2х2 нужна очень незначительная коррекция hardware. А именно - в RAMDAC в блок считывания ввести доработку, заставляющую его считывать не одну ячейку памяти (разрядность 16 или 32) при формировании точки на экране монитора, а считывать 4 ячейки - две по соседним адресам (2 точки в одной строке) и еще две соседние ячейки в следующей строке. Цвет формируется по этим четырем отсчетам. Аппаратная реализация настолько 'тупа', что я просто диву даюсь ...

Какой метод FSAA, мультисемплинг или субсемплинг используется и какая разрядность метода - неважно, алгоритм тот-же, больше чтений.

Нужно ли сглаживание вообще?

Приведу screenschot Unreal II с настройками на максимальное качество.

И тоже самое, но для режима FSAA 2x2:

Это самая современная игра, даже больше - это один из самых современных игровых движков. Сие особенно важно, ведь Unreal II не просто игра, наверняка на нем будут строить другие игры, как это было раньше с Unreal и Unreal Tournament. Что видно по картинке? ... жаль, что нельзя показать динамику, она просто жуткая.

  1. качество поверхностей, сгенерированных текстурами - очень красивое.
  2. стыки полигонов ..... батюшки мои, а зачем тогда 32-битный цвет и прочее, если творится такая мерзость??
  3. тонкие линии. Они присутствуют в прорисовке столбов фонарей на верху здания и лестницы прямо у оранжевой двери. Режим FSAA 2х2 с его двукратной точностью частично маскирует дефект - фонари теряют разрывы, а лестница получает горизонтальные перекладины.

О скорости с FSAA говорить не стоит, если без него скорость порядка 30FPS на весьма неслабом компьютере. Что же выходит? .... FSAA принципиально нужен, иначе бессмысленны 32х цвет и генерация качественной картинки, а вот скоростные результаты FSAA прямо исключают его применение.

Не стоит думать, что эта ситуация когда-нибудь изменится - при умощнении 3D-ускорителей в 2-4-8-16 раз во столько же раз будут расти аппетиты игр, а в 'старые' никто играть и не будет. Т.о., выходит глупость - метод нужен, а нельзя. Что же делать???

Я бы хотел представить альтернативные методы улучшения изображения. При их разработке учитывались 3 требования:

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

Ниже будут описаны две различные реализации метода сглаживания: sAA, основанный на технологии 'точного позиционирования' и динамический AA (dAA).

sAA

sAA не метод сглаживания, эффект antialiasing является его побочным следствием. Чтобы не очень отходить от темы, условно назову его статическим AA (sAA). Идея заключается в том, что к описанию пиксела добавляется новая компонента Delta.

Т.е. на каждую точку есть следующие описания:

  • цвета R, G, B
  • прозрачность
  • номер строки
  • номер позиции в строке (и другая информация, она не существенна).

К ним добавляется еще и Delta - остаток округления от номера строки и номера позиции в строке. Delta получается в момент вычисления координат и не принимает участие в каких-либо вычислениях цвета и видимости пиксела. Для упрощения положим, что эта компонента просто лежит без изменения. Как я говорил выше, Delta для точек внутри отрезка будет = 0, ведь отрезок разбивается на точки строго "в сетке" и проблемными будут именно те самые краевые точки. После формирования пиксела и выяснения видимости его на экране, производится запись его в видеобуфер. Причем, записываются следующие компоненты:

  • цвета R, G, B
  • прозрачность не записывается
  • на место прозрачности записывается Delta (прозрачность может потребоваться, о ней позже)

Если пиксель уже записан на экран, то параметр "прозрачность" ему уже не нужен и туда можно поместить Delta. Т.о., никаких существенных изменений в алгоритмах работы видеокарты и 3D API не происходит, все выполняется обычным способом.

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

  1. заводится специальный конвейер, считывающий входной буфер и записывающий новый. Или - записывающий поверх старого.
  2. при при выводе точки на экран монитора считывать 5 точек (текущая, X+1/Y, X-1/Y, X/Y+1, X/Y-1) и по ним вычислять цвет выводимой точки.

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

Попробую изобразить способы растеризации:

рис.9 до растеризации

рис.10 без FSAA

рис.11 FSAA 2x2 в экранном буфере

рис.12 FSAA 2x2 на мониторе

рис.13 точная растеризации

рис.14 на мониторе

Увеличенная часть рисунка 14

Выделим самый интересный фрагмент рисунка 14 - тот, где есть вершина черного треугольника с добавлением зеленой плоскости. Условно, поделим фрагмент на 5 столбцов и 4 строки. Интерес представляют точки 01, 11, 12, 13, 22, 23, 34, ведь только в них присутствует ненулевая компонента DELTA из-за смещения этих точек от центра. Приводя расчеты, я буду указывать номера точек, что будет соответствовать их цвету. При пост-растеризации в формулах подставляются цвета точек до пост-растеризации. В моем примере это будет чистый белый, чистый черный и чистый зеленый цвета. Итерационный режим заполнения цвета не используется.

По каждой точке:

  • 01: точка смещена на 50% вправо,т.е. ее цвет будет определяться как 75%*01+25%*02. Точка 01 смещена только вправо, что означает отсутствие влияния других точек на эту.
  • 11: точка смещена на 99% вправо(почти посередине), 11=11*51%+12*49%
  • 12: точка смещена на 50% вправо, 12=12*75%+13*25%
  • 13: точка смещена на 50% влево, 13=13*75%+12*25%
  • 23: точка смещена на 50% вправо, 23=23*75%+24*25%
  • 34: точка смещена на 50% влево, 34=34*75%+33*25%
  • 22: точка смещена на 50% влево, и на 75% вверх. У нее есть усреднение еще с одной точкой. 22=(22*75%+21*25% + 22*63%+12*37%)/2

Но и это не все, точки, соприкасающиеся с ними также подвергаются коррекции на них действует обратная составляющая коэффициентов смещения DELTA других точек.

  • 00: нет изменений
  • 10: нет изменений
  • 20: нет изменений
  • 30: нет изменений
  • 21: из-за горизонтального смещения точки 22, эта точка изменяет цвет: 21=21*75%+22*25%
  • 31: нет изменений
  • 32: нет изменений
  • 33: из-за смещения точки 34 влево, ее цвет смешивается с 33: 33*75%+34*25%
  • 04: нет изменений
  • 14: нет изменений
  • 24: нет изменения

Наверно, запутал окончательно? Приведу еще более простой пример:

Есть две точки: 33=белая и 34=зеленая. Точка 33 находится строго в сетке, а 34 смещена относительно центра сетки ровно наполовину. Причем, белый был подзеленой, иначе откуда взяться смещению у зеленой? Визуально, смещение точки 34 влево, должно выражаться в небольшой засветке соседней точки 33 ее цветом. Степень засветки определяется величиной смещения. Яркость самой точки 34 также уменьшится, ведь она ушла из центра. Т.о., количество 'цвета' осталось постоянным, просто оно перераспределилось между соседними точками пропорционально смещению точки 34. Например, если б точка 34 сместилась на самую границу 33-34, то цвет точек 33 и 34 был бы одинаковый и составлял полусумму цветов 33 и 34. Но, в данном случае, точка 34 смещена на 50%, что и задает коэффициенты влияния как 75% и 25% одной и другой точек. Короче говоря, применяется экстраполяция координат в цвета.

Описание довольно сложное, а вот аппаратная реализация до смешного проста.

У описанного метода есть существенный недостаток - поддержка прозрачности. Если сцена обрисовывается от фона к переднему плану, то прозрачность точек не требуется, а при обратном - нужна. Способ устранения этого недостатка - введение идентификатора о наличии прозрачности или DELTA. Т.е., на полупрозрачных поверхностях при обрисовке перед-фон сглаживание не будет производиться. Впрочем, такие поверхности встречаются редко, да и сами 'полупрозрачные', как правило, имеют весьма сложную структуру и дефект нивелируется. И ... перед-фон обрисовка встречается крайне редко из-за возможных проблем с Z координатой и косвенно об этом можно судить по низкой эффективности технологии удаления невидимых поверхностей HSR.

Алгоритм дан в виде, какой был на момент генерации идеи.

Демонстрационная программа

К сожалению, никакими иллюстрациями нельзя описать динамику, так что .... сделал небольшую программу (3 КБ), показывающую эффект метода.

Hotkey:

  • s - включение/выключение желтых линий
  • space - пауза/движение
  • 0 - обычный режим
  • 1,2,3 - предложенный метод с разной степенью аппроксимации.
  • ESС - выход.

Ограничение программы - запускается только на видеокартах от NVidia и только в реальном режиме процессора. Последнее можно получить путем загрузки с дискеты без config.sys или под Windows9x по пункту "Safe mode command promt only". Эти ограничения вызваны тем фактом, что я выполняю прямую запись в память видеокарты. Из-за древности, программа будет работать только на любых nVidia видеокартах и вряд ли корректно запустится на материнских платах nForce. Когда программа писалась, то nForce еще не было и программа определяет наличие видеокарты по VendorId 'nVidia'.

dAA

to be continued ...

Ветка в конференции, посвящённая обсуждению статьи.

Теги