Мысли о FSAA

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

С О Д Е Р Ж А Н И Е
Почему на телевизоре изображение лучше?
Идея метода
Описание
Достоинства/недостатки
Демонстрационная программа

Цель статьи - рассмотреть достаточно простой вопрос "а нужно ли нам FSAA?".

Эффект, производимый AA(antialiasing) очень сильно повышает качество изображения, но падение производительности .... Интересное наблюдение - на экране телевизора фильмы, как и игры, смотрятся совсем не так, как на мониторе. В чем дело? У монитора разрешение больше 1024 линий, а обычный телевизор лучше 400 линий вряд ли сможет показать. Так, почему же телевизор, при несопоставимо худших параметрах показывает лучше??

Попробую ответить на этот вопрос ...

  1. у монитора вывод изображения строго в сетке (например, для 1024*768 это будет 1024 точек в строке на 768 строк), у телевизора - фиксированное число строк без фиксации количества точек в строке.
  2. у монитора графическое изображение может занимать от 1 и больше точек, у телевизора это "виртуальное" число как минимум распространяется на несколько "точек". Термины "виртуальное" и "точек" поставлено в кавычки потому, что эти параметры для телевизора отсутствуют.
  3. быстрое движение на телевизоре смазывается, на мониторе ...
  4. при удалении об'екта на телевизоре изображение теряет фокус (что естественно!), на мониторе - сохраняет четкие границы в 1 пиксель.
  5. у телевизора все изображение как-бы "не в фокусе", только в разной степени, у монитора - соседние пикселы выводятся четко, взаимное попадание цвета в соседних пикселах отсутствует.
  6. у монитора есть aliasing ... впрочем, пока достаточно.

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

Для телевизора: линия будет достаточно "толстой" и будет перемещаться без каких-либо дефектов, для монитора: линия займет 1 пиксель и перемещение будет сопровождаться щелчками(дискретностью) перемещения. Какой из двух представлений понравится больше? Т.о., можно сказать, что изображение на экране монитора обладает следующими дефектами:

  • неточностью статического положения пиксела
  • неточностью динамического положения пиксела
  • триггерный эффект перемещения

Все эти дефекты получаются из того факта, что дискретность положения изображения равна его минимальному значению (один пиксель). Для телевизора это не так - размер дискретности много-много меньше, чем его четкость. Т.е., чтобы улучшить изображение на мониторе, надо сломать это равенство - размер точки = дискретности координат. Возникает вопрос - КАК?





Один из способов - использование низкокачественных мониторов с высоким разрешением и частотой развертки (полный антипод современным LCD мониторам). Да, играть на таком хорошо, а вот пользоваться им как монитором .... проще сразу купить очки - гарантированное нарушение зрения. И что остается?

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

Растеризация.

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

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

Другой способ - вначале формировать изображение в несколько раз больше, а при выводе на экран изображение уменьшать, т.е. в формировании одной точки на экране участвует несколько точек в буфере. Это и есть тот самый метод сглаживания, которым пользуются современные 3D-ускорители. Недостатки этого "метода" очевидны - огромная нагрузка на видеокарту и соответствующее падение скорости формирования изображения. Самый низкокачественный из этих методов FSAA преобразует из 4х точек в буфере одну точку на экране. Изображение становится лучше, но при трехкратном падении скорости. Т.е. только при очень слабом процессоре и очень-очень мощной видеокарте можно позволить себе такую роскошь, как FSAA .... да и то, только на очень старых и нетребовательных играх. Что же делать? Изображение надо сглаживать, и это не зависит от разрешения монитора, и для 1600*1200.

Рассмотрю три метода устранения дефектов изображения, вызванного aliasing'ом:

  • Full scene spatial anti-aliasing (FSAA) - общепринятый метод
  • Статический метод сглаживания (sAA) - сейчас и будет рассматриваться
  • Динамический метод сглаживания (dAA) - несколько другой прием, во второй части.

Full scene spatial anti-aliasing

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





Самый простой и малоресурсоемкий метод FSAA - 2х1 (по двум точкам). Впрочем, эффект настолько странный, что он практически не применяется. Хоть какое-то качество дает 2х2 (по четырем точкам, две по оси X и две по оси Y). Цвет каждой точки на экране формируется усреднением значений всех четырех точек, две по X и две по Y.

Методы FSAA детально описаны на Ректоре и очень подробно описывать, означает оскорбить читателя. Постараюсь остановиться лишь на тех моментах, которые 'остались за кадром'.

Что вытекает из подобного творения "ижынегрной" мысли? Для FSAA 2х2 это будет:

  1. падение скорости прорисовки в 4 раза, ведь надо сформировать изображение в буфере в два раза бОльше по оси Y и в два раза по X. С учетом дополнительных накладных расходов, общее падение скорости кадров будет меньше, всего в три раза. Мило!
  2. при смене яркого на темный будет генерироваться не больше двух полутонов, а если ориентация неудачна, то вообще один. Такие жуткие затраты вычислительные затраты и какой мизерный эффект....
  3. проблемы с текстом. Текст формируется программой(игрой) исходя из того разрешения, которое она установила, но при FSAA (например 2x2) разрешение в 2 раза больше по обоим осям, что может вызвать усреднение текста и пустого места или, что особенно заметно, пропадания текста. Этот эффект изображен на модели, где приведены два случая - тонкая линия (текст толщиной в 1 пиксель) слева и толстая линия (сгенерировано с учетом возможного FSAA) справа. Разметка дана для того, как думает приложение и как есть в экранном буфере.

    original

    on-grid

    no-FSAA

    FSAA 2x2

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

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

    рис.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 ...

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

Страницы материала
Страница 1 из 0
Оценитe материал

Теги

Возможно вас заинтересует

Популярные новости

Сейчас обсуждают