Как вычисляются уровни mipmap в металле?

14

Мой вопрос касается конкретно Metal, так как я не знаю, изменится ли ответ для другого API.

То, что я считаю, я понимаю до сих пор это:

  • Текстура с mip-map имеет предварительно вычисленные «уровни детализации», где более низкие уровни детализации создаются путем понижения исходной текстуры каким-либо значимым образом.

  • Уровни MipMap упоминаются в нисходящем уровне детализации, где уровень 0- это исходная текстура, а более высокие уровни - ее уменьшение в два раза.

  • Большинство графических процессоров реализуют трилинейную фильтрацию, которая выбирает два соседних уровня mipmap для каждой выборки, выборки с каждого уровня с использованием билинейной фильтрации, а затем линейно смешивает эти выборки.

Я не совсем понимаю, как выбираются эти уровни mipmap. В документации стандартной библиотеки Metal я вижу, что образцы могут быть взяты с указанием или без указания экземпляра lod_optionsтипа. Я бы предположил, что этот аргумент меняет способ выбора уровней mipmap, и, по-видимому, существует три вида lod_options2D-текстур:

  • bias(float value)
  • level(float lod)
  • gradient2d(float2 dPdx, float2 dPdy)

К сожалению, документация не объясняет, что делает любая из этих опций. Я могу догадаться, что bias()смещает некоторый автоматически выбранный уровень детализации, но тогда что означает смещение value? В каком масштабе он работает? Точно так же, как это lodв level()переводе на дискретные уровни MIPMAP? И, работая в предположении, что gradient2d()использует градиент координат текстуры, как он использует этот градиент для выбора уровня mipmap?

Что еще более важно, если я опущу lod_options, как тогда выбираются уровни mipmap? Отличается ли это в зависимости от типа выполняемой функции?

И, если заданная по умолчанию операция no-lod-options-option sample()функции заключается в том, чтобы сделать что-то вроде gradient2D()(по крайней мере в фрагментном шейдере), использует ли она простые производные экранного пространства, или она работает напрямую с растеризатором и интерполированными координатами текстуры рассчитать точный градиент?

И, наконец, насколько последовательно это поведение от устройства к устройству? Старая статья (старая, как в DirectX 9), которую я прочитал, ссылалась на сложный выбор mipmap для конкретного устройства, но я не знаю, лучше ли выбран mipmap на новых архитектурах.

lcmylin
источник

Ответы:

17

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

Хорошее место, чтобы прочитать о выборе mip подробно в спецификации OpenGL, раздел 8.14, «Минимизация текстуры» . Я бы предположил, что это работает так же, как в металле. (Apple могла бы что-то изменить, учитывая, что они производят и оборудование, и API ... но я сомневаюсь, что они это сделали.) Я подведу итог здесь.

Выбор мипа по умолчанию (без использования lod_optionsмодификаторов) использует градиенты экранного пространства текстурных координат для выбора уровней мипа. По сути, он пытается выбрать уровни mip, которые производят как можно ближе к отображению 1: 1 текселей в пиксели. Например, если градиенты имеют длину 4 текселя на пиксель, он выберет мип 2-го уровня (что составляет 1/4 размера уровня 0 и, следовательно, дает 1 фиксированный тексель на пиксель).

С трилинейной фильтрацией, поскольку вы обычно не получаете точного отображения 1: 1, он выбирает два ближайших уровня и линейно интерполирует между ними, так что у вас есть плавный переход между уровнями mip, когда камера или объекты в вашей сцене движутся вокруг.

λλλλзнак равно2,8

λжурнал2(1/4)знак равно-2

Теперь, что касается параметров модификатора:

  • biasλ
  • levelλλlod
  • gradient2dпозволяет вам добавлять собственные градиентные векторы, которые заменяют неявные градиенты экранного пространства текстурных координат. Остальная часть процесса выбора и отбора мипов идет как обычно, но с измененными градиентами. Это позволяет настроить анизотропную фильтрацию.

В других типах шейдеров, кроме фрагментных шейдеров, нет понятия «градиенты экранного пространства», поэтому обычно разрешены только две последние операции - любая операция, которая пытается использовать неявные градиенты, приведет к ошибке компиляции. Я не уверен, что это именно так, как это делает Metal, но этого я и ожидал от работы с другими API.

Натан Рид
источник