Помогите мне понять Анизотропная фильтрация (AF)

8

В последнее время я читал о фильтрации текстур, а именно: фильтрация ближайших соседей, билинейная фильтрация, трилинейная фильтрация, анизотропная фильтрация, карты MIP, карты RIP и так далее.

С точки зрения высокого уровня, я думаю, что могу понять эти методы, как работают и почему они существуют, за исключением анизотропной фильтрации. Анизотропная фильтрация сводит меня с ума.

Я вижу проблему необходимости текстурирования поверхности, которая находится под углом относительно камеры, но я не понимаю, как выборка трапециевидных следов могла бы решить эту проблему (хотя я вижу результат). Вероятно, это потому, что я НЕ понимаю, как рассчитывается трапециевидный след и как взвешиваются закрытые телексы для выборки текстуры.

Эта статья от Nvidia смущает меня еще больше, используя предложения, как « когда тексель трапециевидный » или « анизотропная фильтрация масштабирует либо высоту, либо ширину мип-карты в соотношении относительно искажения текстуры в перспективе ». Трапециевидный тексель? Масштабирование MIP-карты? Что это вообще значит?

Не могли бы вы помочь мне понять, как работают AF и AF уровни?

Обратите внимание, что моя цель не в том, чтобы иметь реализацию OpenGL или DirectX AF, а в том, чтобы понять, как AF работает с точки зрения высокого уровня.

Никола Масотти
источник

Ответы:

10

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

Термин «наложение текстуры» означает назначение позиций на объекте местоположениям в текстуре. Это позволяет растеризатору / шейдеру для каждой позиции на объекте извлекать соответствующие данные из текстуры. Традиционный метод для этого - назначить каждой вершине объекта текстурную координату, которая напрямую отображает эту позицию в местоположение в текстуре. Растеризатор будет интерполировать эту текстурную координату по граням различных треугольников, чтобы получить текстурную координату, используемую для извлечения цвета из текстуры.

Теперь давайте подумаем о процессе растеризации. Как это работает? Он берет треугольник и разбивает его на блоки размером с пиксель, которые мы будем называть «фрагментами». Теперь эти блоки размером в пиксель имеют размер в пикселях относительно экрана.

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

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

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

Это также будет очень медленно .

В интересах производительности, мы вместо этого пытаемся приблизить реальный ответ. Мы основываем вещи на одной текстурной координате, а не на 4, которые покрывают всю область фрагмента в пространстве текселей.

Фильтрация на основе MipMap использует изображения с более низким разрешением. Эти изображения в основном являются ярлыком для идеального метода, предварительно вычисляя, как будут выглядеть большие блоки цветов при смешивании. Поэтому, когда он выбирает более низкую карту, он использует предварительно вычисленные значения, где каждый тексель представляет область текстуры.

Анизотропная фильтрация работает путем аппроксимации идеального метода (который может и должен сочетаться с mipmapping) путем отбора фиксированного числа дополнительных образцов. Но как он вычисляет область в пространстве текселей для выборки, поскольку ей все еще дается только одна координата текстуры?

В основном это обманывает. Поскольку фрагментные шейдеры выполняются в соседних блоках 2x2, можно вычислить производную любого значения в фрагментном шейдере в экранном пространстве X и Y. Затем он использует эти производные в сочетании с фактической координатой текстуры, чтобы вычислить приближение какой будет фактический след текстуры фрагмента. И затем он выполняет ряд образцов в этой области.

Вот диаграмма, чтобы помочь объяснить это:

Фрагмент следа и анизотропные образцы.  К вашему сведению: если вы видели это раньше, это мое.

Черно-белые квадраты представляют нашу текстуру. Это просто шахматная доска из 2х2 белого и черного текселей.

Оранжевая точка - это координата текстуры для рассматриваемого фрагмента. Красный контур - это фрагмент фрагмента, который центрирован по координате текстуры.

Зеленые прямоугольники представляют тексели, к которым может обращаться реализация анизотропной фильтрации (детали алгоритмов анизотропной фильтрации зависят от платформы, поэтому я могу объяснить только общую идею).

Эта конкретная диаграмма предполагает, что реализация может получить доступ к 4 текселям. О, да, зеленые ящики покрывают 7 из них, но зеленая коробка в центре может быть получена из меньшего mipmap, таким образом, выбирая эквивалент 4 текселей за один выбор. Реализация, конечно, будет взвешивать среднее значение для этой выборки на 4 по сравнению с единичными текселями.

Если предел анизотропной фильтрации был 2, а не 4 (или выше), то реализация выбрала бы 2 из этих выборок, чтобы представить отпечаток фрагмента.

Николь Болас
источник
Спасибо, что объяснили это, и извините за задержку с ответом, но я должен был найти время, чтобы прочитать это очень внимательно. Я чувствую, что единственный абзац, который я не совсем понимаю, это тот, где вы говорите о фрагментных шейдерах и их производных. Что именно выводится в экранном пространстве X и Y? Это значение координат текстуры?
Никола
@NicolaMasotti: «Производный» - это исчисляемый термин. В данном случае это скорость изменения координаты текстуры по поверхности треугольника в пространстве экрана X или Y. Если вы не знаете исчисление, я не смогу объяснить его Вам в одном посте.
Никол Болас,
К счастью, я знаю, что такое производная. Есть ли место, где я могу посмотреть точную математику?
Никола
Кроме того, я бы предложил несколько изменений в вашем ответе, то есть « это зависит от того, как многоугольник отображается на текстуру » вместо « это зависит от того, как текстура отображается на многоугольник ». Кроме того, когда вы говорите: « используя покрытие для масштабирования цветов на границе », вы на самом деле имеете в виду « весовые цвета на границе »?
Никола
3

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

Итак, давайте сначала подумаем об этом с точки зрения размытия. Размытие это тип свертки. Мы берем ядро ​​свертки и умножаем его на все пиксели в области, а затем складываем их вместе и делим на вес. Это дает нам вывод одного пикселя. Затем мы перемещаем его и делаем снова для следующего пикселя, и снова, и т. Д.

Это действительно дорого, поэтому есть способ обмануть. Некоторые ядра свертки (в частности, ядро ​​размытия по Гауссу и ядро ​​размытия коробки) можно разделить на горизонтальный и вертикальный проход. Вы можете сначала отфильтровать все с помощью только горизонтального ядра, затем взять результат и отфильтровать его только с вертикальным ядром, и результат будет идентичен выполнению более дорогого вычисления в каждой точке. Вот пример:

Оригинал:

Гавайи

Горизонтальное размытие:

Гавайи размыты по горизонтали

Горизонтальное, за которым следует вертикальное размытие:

Гавайи размыты по горизонтали, а затем по вертикали

Таким образом, мы можем разделить фильтрацию на вертикальный и горизонтальный проход. И что? Что ж, получается, что мы можем сделать то же самое для пространственных преобразований. Если вы думаете о повороте перспективы, вот так:

Гавайи повернуты вокруг оси Y

Это можно разбить на шкалу Х:

введите описание изображения здесь

сопровождаемый масштабом каждого столбца немного другим количеством:

Гавайи масштабируются по X, а затем пропорционально по Y

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

Слово «анизотропия» происходит от греческого «an» означает «не», «isos» означает «равный» и «tropos» означает «направление». Так что это означает «не равны во всех направлениях». И это именно то, что мы видим - масштабирование и фильтрация выполняются в разном количестве в каждом направлении.

user1118321
источник