Избегать z-боев с совпадающими поверхностями

26

При рендеринге двух перекрывающихся копланарных поверхностей распространенной проблемой является «борьба по z», при которой средство визуализации не может решить, какая из двух поверхностей ближе к камере, создавая визуальные артефакты в области перекрытия.

Стандартным решением этого является придание поверхностям небольшого смещения при проектировании модели. Есть ли другое решение?

отметка
источник
2
Вы можете проверить логарифмические буферы глубины. Там статья о Gamasutra
Мыльный
1
Когда вы говорите «копланарный», вы имеете в виду «почти» или «точно» копланарный и, если последний, являются ли эти поверхности когда-либо одинаковыми поверхностями / треугольниками? Аппаратура рендеринга должна быть детерминированной (при условии, что вы не отправляете в случайном порядке) для последнего случая и не иметь драки. Если речь идет о неодинаковых поверхностях, но точно копланарных, не могли бы вы обновить модель, чтобы разделить поверхности на перекрывающиеся и непересекающиеся участки?
Саймон Ф,
@SimonF, под «копланарным» я подразумеваю «точно копланарный». Решение Soapy работает только в «почти копланарном» случае.
Mark
Не могли бы вы привести пример ваших поверхностей? Единственная вещь, о которой я могу думать, - это повторяющиеся треугольники, как упомянул @SimonF.
RichieSams
@RichieSams самый распространенный случай, о котором я могу вспомнить, это декали, где вам не нужны точно повторяющиеся треугольники.
ry

Ответы:

10

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

Одно из возможных решений - вообще не использовать Z-буфер. Скорее вы можете использовать алгоритм художника . Конечно, это связано со всеми проблемами алгоритма маляров. Но это решило бы Z-бой.

В вашем примере с надписью Screen Space Decals (SSD), обычным решением является использование смещения, то есть простого тонкого куба. См. Презентацию Warhammer 40k о твердотельных накопителях для справки. Или Барт Вронский в посте , который решает некоторые другие проблемы с переводными картинками, но и ссылки на несколько других презентации о SSD - накопителях

RichieSams
источник
5
Повторный рендеринг одной и той же геометрии с одинаковыми преобразованиями позволяет надежно генерировать одинаковые значения глубины каждый раз. (То есть это не сила , это воля ). Вот почему, например, работает многоходовое переднее освещение.
Натан Рид
@NathanReed Исправлено. Спасибо за разъяснения
RichieSams
1
Чтобы получить эту функциональность, вам нужно использовать спецификатор инварианта в glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu
Обратите внимание, что идентичных выражений шейдера (и входных данных, очевидно) при оценке позиций вершин может быть недостаточно для получения идентичных результатов, поскольку некоторые оптимизации могут зависеть от остальной части шейдера. GLSL имеет ключевое слово «invariant», чтобы объявить выходные данные шейдеров, которые должны оцениваться одинаково в разных шейдерах.
Firadeoclus
2

Вот как я решил это в прошлом:

  1. Нарисуйте первый объект (тот, который должен появиться позади другого объекта) путем проверки глубины, но не записи глубины
  2. Нарисуйте второй объект путем проверки глубины и записи глубины. Это не приведет к z-бою, так как мы не писали глубину в шаге 1.
  3. Нарисуйте первый объект, записывая только в буфер глубины, а не в буфер цвета. Это гарантирует, что буфер глубины актуален для любых пикселей, которые покрыты объектом 1, но не объектом 2.

Обратите внимание, что объекты должны быть нарисованы последовательно, чтобы это работало.

дефолт
источник
0

В зависимости от вашего рендерера вы можете сделать поверхности более «размытыми», применяя минимальное смещение по глубине мультисэмплинга, используя шумоподобный алгоритм. Это должно привести к некоторому эффекту смешивания для поверхностей в непосредственной близости от глубины. Насколько я знаю, установка глубины для каждого сэмпла во фрагментном шейдере довольно недавняя в OpenGL и только в качестве расширения.

OpenGL имеет PolygonOffset, но требует заранее знать, что вы собираетесь сделать что-то копланарное. Хотя это невозможно для поверхностей в пределах одной модели, это может хорошо работать, например, при рендеринге дороги, наложенной на участок земли.

Andreas
источник