Почему графические процессоры делят пространство клипа Z на W для позиции?

8

Предыстория:
я обнаружил, что очень просто использовать линейный буфер глубины, используя лишь небольшую модификацию канонического преобразования вершин. Самый простой способ находится внизу https://www.mvps.org/directx/articles/linear_z/linearz.htm .

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

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

Почему это сделано? X и Y должны быть разделены на расстояние от камеры, а координата Z - нет, чтобы идеально вписаться в поле NDC.

Джесси
источник

Ответы:

13

Если вы делаете перспективное изображение и ваша модель имеет неявные пересечения, то, если вы используете «линейный Z», эти пересечения появятся в неправильных местах.

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

Я извиняюсь за неэстетичное качество следующих иллюстраций, но я сделал их еще в 97 году.

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

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

Это второе изображение показывает результат использования невзаимного буфера глубины: (Извинения за изменение масштаба - они были скопированы из старого документа MS Word, и я не знаю, что случилось с масштабированием.)

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

Как видите, результаты неверны.

С другой стороны, вы действительно хотите линейное представление Z? Если вы визуализируете перспективу, конечно, вам нужно больше точности ближе к камере, чем на расстоянии?

Re ваш последующий комментарий:

«Если они не интерполируются с 1 / Z», что я не понимаю. Что это за интерполяция?

Первое, на что следует обратить внимание, это то, что при стандартной перспективной проекции прямые линии в мировом пространстве остаются прямыми линиями в перспективном пространстве. Расстояния / длины, однако, не сохраняются.

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

ИксSсрееNзнак равноИксWорLdZWорLd
YSсрееNзнак равноYWорLdZWорLd
Мы также должны вычислить обратную глубину экранного пространства, например
ZSсрееNзнак равно1ZWорLd
но для линейного Z в буфере глубины мне потребуется что-то вроде:
ZSсрееNзнак равноsсaLе*ZWорLd
(Здесь можно предположить, что масштаб = 1)

Давайте предположим, что у нас есть линия с конечными точками мирового пространства

[001]aNd[200010]
С перспективным отображением этих карт на экран координат пространства
[001]aNd[2000,1]

Система / оборудование рендеринга будет линейно интерполировать пространство экрана z, поэтому в точке пути 1/2 линии, как это отображается на экране, то есть в пикселе (10, 0), мы получили бы проецируемое (обратное) значение Z значение 0,55, что соответствует значению Z мирового пространства ~ 1,818. Учитывая начальные и конечные значения Z, это составляет около 20% по длине линии.

Если бы вместо этого мы попытались интерполировать, используя исходные значения Z, мы бы получили Z, соответствующее значению мирового пространства 5,5. Пока ничто не пересекается, вы можете быть в порядке (я не думал об этом слишком тщательно), но все с неявными пересечениями будет неправильным.

Что я не упомянул, так это то, что после того, как вы введете перспективное правильное текстурирование (или даже перспективное правильное затенение), вы должны выполнить интерполяцию по пикселям 1 / w и, кроме того, также вычислить, по пикселю, обратную величину этого интерполированного значения.

Саймон Ф
источник
Я не думаю, что смогу понять этот ответ без большего количества математики / диаграмм. И да, большая точность, ближе, вероятно, имеет смысл, но масштабирование от линейного far / z, которое является стандартным, не имеет смысла. Это дает буфер глубины, который становится более линейным, чем ближе две плоскости отсечения друг к другу. Это похоже на сочетание двух понятий: экранно-линейная Z и отображение буфера непостоянной глубины для взлома производительности.
Джесси,
В частности, это «если они не интерполируются с 1 / Z», что я не понимаю. Что это за интерполяция?
Джесси
1
Я добавлю некоторый дополнительный текст, чтобы надеяться объяснить
Саймон Ф
Спасибо! Я думаю, что проблема сводится к «Система визуализации / аппаратное обеспечение будет линейно интерполировать пространство экрана z». У меня сложилось впечатление, что позиция NDC будет вычисляться как (x, y, z) / wдля фрагмента, но, по-видимому, вместо этого мы имеем дело с линейно-интерполированной версией (x/w, y/w, z/w)? Это не кажется мне разумным в 2018 году, но было бы неплохо знать, если мы все равно будем жить с этим взломом!
Джесси
Чтобы выполнить корректное перспективное текстурирование / затенение / что угодно, вам необходимо линейно интерполировать (Val / w) значения, а затем, для каждого фрагмента, выполнить деление на линейно интерполированное 1 / w. Это немного сложно объяснить только в комментарии, но есть немного объяснения в computergraphics.stackexchange.com/a/4799/209 . Кроме того, можно выполнить поиск статьи Джима Блинна "Гиперболическая интерполяция"
Саймон Ф.
6

Использование Z / W для буфера глубины идет глубже, чем просто отсечение по ближним и дальним плоскостям. Как намекал Саймон, это связано с интерполяцией между вершинами треугольника во время растеризации.

Z / W - это уникальная опция, которая позволяет правильно рассчитывать значения глубины NDC для точек внутри треугольника, просто линейно интерполируя значения глубины NDC из вершин в пространстве экрана . В принципе, мы могли бы использовать любую функцию, которая нам нравится, чтобы отобразить пространство камеры Z в значение буфера глубины, но любой другой выбор, кроме Z / W, потребовал бы более сложной математики для каждого пикселя, которая была бы медленнее и труднее встроить аппаратное обеспечение.

Обратите внимание, что если вы используете буфер линейной глубины, то, конечно, линейная интерполяция значений глубины будет правильной в мировом пространстве ... но не, вообще, в экранном пространстве! И именно растровое пространство имеет значение для растеризации, поскольку нам нужно иметь возможность генерировать правильные в перспективе значения глубины (и другие значения атрибутов, например, UV) для каждого центра пикселя или другой точки выборки в пределах границ экранного пространства растровый треугольник.

Натан Рид
источник
Я не знаю, как спроектировать графический процессор, но мне кажется, что все, что нужно, это интерполировать Z вместо Z / W для линейной глубины, и после этого Z / W интерполяция может все же произойти для всего видимого. Я до сих пор не могу сказать, является ли это вопросом хорошего рассуждения или одним из «никого не волнует, поэтому мы не беспокоимся об обновлении».
Джесси
Интерполяция Z вместо Z / W не дает правильных результатов в пространстве экрана. Z / W делает.
Натан Рид
Правильно. Но если буфер глубины квантуется с более низкой точностью, чем положение, то, кроме производительности, когда он работает, не очень хорошая идея хранить масштабированный кусок экранного пространства Z. Если линейная интерполяция - это все, что мы получаем, то отсечение необходимо произойти в поле зрения. И Z нужно интерполировать перед делением на W, для буфера глубины, и после него, для того, что вы прошли. Так есть ли ответ на мой вопрос: «потому что графические процессоры всегда интерполируются только в пространстве клипов, потому что это было единственное практическое решение для первых графических процессоров, и с тех пор оно работало достаточно хорошо»?
Джесси
Я не слежу за тем, что вы имеете в виду под «квантованием с меньшей точностью, чем положение», или «сохранением масштабированного фрагмента пространства экрана Z».
Натан Рид
1
Кроме того, «Z должен быть интерполирован перед делением на W для буфера глубины» - нет. Это то, что я пытался объяснить. Вы получаете неправильные ответы если интерполируете Z (или что-либо еще) в пространстве экрана, не деля его сначала на W. Вы, похоже, застряли на этой идее, что линейный Z-буфер просто работал бы, если бы мы не делили на W. Но он не будет работать - он не будет правильно интерполироваться в пространстве экрана.
Натан Рид