Во-первых, полезно знать, что графические процессоры всегда оценивают фрагментные / пиксельные шейдеры по 2x2 блокам пикселей одновременно. (Даже если в конечном итоге необходимо нарисовать только некоторые из этих пикселей, в то время как другие находятся за пределами многоугольника или перекрыты - ненужные фрагменты маскируются вместо того, чтобы записываться в конце).
Производная пространства экрана от переменной (или выражения) v
в вашем шейдере - это разница в значении v
(в этой точке кода) от одной стороны этого квадрата 2x2 пикселей к другой. то есть. ddx
значение v
в правом пикселе минус значение v
в левом, и аналогично для ddy
по вертикали.
Это отвечает «насколько быстро v
увеличивается или уменьшается, когда мы движемся горизонтально (ddx) или вертикально (ddy) по экрану?» - т.е. в терминах исчисления, он аппроксимирует частные производные вашей переменной (приблизительный, потому что он использует дискретные выборки в каждом фрагменте, а не математически оценивает бесконечно малое поведение функции)
Для скалярных величин мы также можем рассматривать это как вектор градиента, ∇v = float2(ddx(v), ddy(v))
который указывает вдоль направления пространства экрана, в котором v
наиболее быстро увеличивается.
Этот тип информации часто используется для выбора подходящего mipmap или ядра анизотропной фильтрации для поиска текстур. Например, если моя камера выглядит почти параллельно вертикальному uv
направлению текстурированной плоскости пола, ddy(uv.y)
она будет очень большой по сравнению с ddx(uv.x)
(так как вертикальная ось укорочена на экране - один шаг пикселя по вертикали покрывает более длинный участок текстурного пространства), что сообщает аппаратуре выборки текстуры, что мне нужна анизотропная фильтрация, чтобы размыть вертикальное направление текстуры больше, чем горизонтальное, чтобы избежать наложения артефактов.
Для большинства простых эффектов вам не нужно использовать эти производные, так как базовые методы выборки двухмерных текстур обрабатывают это для вас. Но, как отмечает Le Comte du Merde-fou в комментарии выше, при искажении поиска текстур вам может потребоваться вручную извлечь и / или обработать используемые производные пространства экрана, чтобы помочь аппаратному обеспечению выбрать соответствующую фильтрацию (например, через tex2Dlod
в HLSL)
Декали пространства экрана являются одним из таких случаев, когда один блок 2x2 может покрыть большой скачок скачка в вычисленной координате текстуры, приводя к размытому или псевдонимному краю, если вы позволите системе наивно рассчитать уровень фильтрации. В этой статье подробно рассказывается об этом артефакте и подходах к его смягчению .
Эти производные также могут быть полезны, когда вы используете шумовые функции в процедурной генерации текстур. Скажем, если вы хотите превратить процедурный шум в карту нормалей, ddx и ddy дают простой, хотя и приблизительный, способ рассчитать, как значение шума изменяется вблизи текущего фрагмента и как он наклоняется, так что вы можно построить соответствующий нормальный.
Методы рендеринга сглаженных линий или пересечений могут также использовать производные пространства экрана, чтобы гарантировать, что толщина / спад постоянны и не зависят от геометрии или угла обзора.
В этом выступлении о рендеринге песка в журнале «Путешествие» оратор упоминает, что они могли бы использовать эти производные функции для управления тем, насколько блестящим является песок по скользящим краям ... если бы они знали о них в то время (вместо этого они использовали трюк с отображением, который под капотом работает на этих видах производных в любом случае)
Последнее замечание: производные пространства экрана могут быть вычислены с «грубой» / низкой точностью (это означает, что одна пара производных является общей для четырехугольника) или «с высокой» / высокой точностью (то есть каждый пиксель сравнивается только с его непосредственным соседи в кваде, которые могли бы дать четыре четкие пары производных по квадру). Обычно это достаточно, но если вы заметили, что в вашем эффекте видны блоки 2х2, это хорошая подсказка, которую вы хотите переключить на высокую / высокую точность. ;)
(На диаграмме вверху я использовал вычисления для мелких производных, но остерегайтесь того, что только ddx / ddy сам по себе может по умолчанию давать грубые производные)