Предотвращение перерисовки пиксель-шейдера для одного ERG
Фон
Использование gluTess для построения списка треугольников в Direct3D9 из пути GDI+ DrawString(..):
Затем для заполнения фигуры используется пиксельный шейдер (v3.0). При рисовании с непрозрачными значениями все выглядит хорошо:
Эта проблема
При определенных размерах шрифта, если цвет имеет альфа-компонент (то есть Argb #55FFFFFF), мы начинаем видеть эти неприятные артефакты тесселяции, где треугольники могут слегка перекрываться:
При больших размерах шрифта проблема иногда отсутствует:
Используя превосходный инструмент Intel GPA Frame Analyzer Pixel History, мы видим, что в тех местах, где возникают артефакты, пиксель "трогался" 3 раза от одного эргономического элемента.
Я пытаюсь понять, как я могу остановить мой пиксельный шейдер от прикосновения к одному и тому же пикселю более одного раза.
Другие решения, относящиеся к предотвращению перерисовки, похоже, связаны со стратегиями zbuffer, однако эта проблема больше связана с отрисовкой одного списка 2D-треугольников за один проход пиксельного шейдера.
Я немного растерялся, пытаясь найти решение по этому вопросу. Я надеялся, что HLSL может иметь какой-то флаг "касаться каждого пикселя только один раз", но я не смог найти ничего подобного. Самым близким, что я нашел, было установить BLENDOP на MAX вместо ADD. Но вывод неправильный при смешивании с другими цветами в сцене.
У меня также есть SRCBLEND = ONE, DSTBLEND = INVSRCALPHA. Единственная комбинация флагов, которые дают правильный вывод (хотя и с артефактами overdraw.)
Я играл с SEPARATEALPHABLENDENABLE в анализаторе кадров GPA, который звучал почти как то, что мне нужно здесь - установите смешивание на MAX, но только на "альфа-канале", однако из того, что я могу определить, влияет эта настройка (и соответствующая BLENDOPALPHA) вообще ничего
Последнее, о чем я подумал, - это запекать текст как непрозрачный для текстуры, а затем перерисовывать эту текстуру в сцену с применением соответствующего альфа-значения, однако на самом деле это не работает в этом проекте, потому что я также поддерживаю градиентные кисти, где остановка значения могут содержать альфа, что означает, что артефакты все равно будут видны, или конечный результат будет просто неправильным, если мы убрали альфу со стоп-значений перед запеканием текстуры. Также все усилия будут ужасно дорогими.
Любые намеки или указатели будут оценены. Спасибо за прочтение.
1 ответ
Проблема, которую вы видите, не должна возникать.
Если два ваших треугольника перекрываются, это потому, что вы разместили вершины таким образом, что при рисовании соседних треугольников они перекрываются. Вероятно, происходит то, что эти два смежных треугольника имеют две общие вершины, но у каждого треугольника есть своя копия каждой вершины, которая, как было рассчитано, находится в очень, очень немного другой позиции.
Решение проблемы состоит не в том, чтобы попытаться заставить пиксельный шейдер касаться пикселя только после того, как он использует индексный буфер (если вы этого еще не сделали), и если общие вершины между каждым треугольником фактически совместно используют одну и ту же вершину и не используют тот, который очень немного не находится в том же месте, что и соседний треугольник.
Если вы не контролируете используемый алгоритм тесселяции, вам, возможно, придется выполнить проход через буфер вершин после его генерации, чтобы обнаружить и объединить вершины, которые находятся в пределах очень небольшого допуска друг к другу. Даже без индексного буфера наивным решением было бы следующее:
Для каждой вершины в буфере вершин сравните ее положение с любой другой вершиной в остальном буфере вершин.
Если две вершины находятся в пределах небольшого допуска другой, замените положение второй вершины положением той, с которой вы сравниваете ее.
Это должно привести к объединению позиций двух вершин, если они достаточно близки, чтобы вы посчитали их одинаковыми.
Теперь у вас не должно быть проблем с перекрывающимися треугольниками. При повседневном рендеринге два треугольника постоянно делят края друг с другом, и вы никогда не получите эффект, когда они кажутся слегка перекрывающимися. Аппаратное обеспечение гарантирует, что точка выборки находится либо на одной стороне линии, либо на другой, но никогда не одновременно в обе стороны, независимо от того, насколько близко точка находится к линии (даже если она математически находится на линии, она все равно не срабатывает. одна сторона или другая).