Странный результат с MSAA
MSAA с использованием OpenGL.
Я просто нарисовал белую сферу, используя 'glutSolidSphere', и залил черным, где 'точка (Normal, CameraVec) <порог "для силуэта.
И я нашел странный результат на контуре внутреннего белого круга. Похоже, MSAA не работал.
Кстати, он хорошо работал на контуре (крайнем) черного круга.
Если я увеличу количество образцов, это будет хорошо работать даже на контуре внутреннего белого круга.
Я думаю, что это должно работать хорошо независимо от количества образцов, потому что разрешение образцов происходит после фрагмента шейдера.
Это правильный результат? Если да, то почему?
Ниже приведен результат 4 образцов (слева) и 32 образцов (справа).
1 ответ
MSAA помогает только сгладить края и пересечения многоугольников. Это не делает ничего, чтобы сгладить резкие переходы, созданные вашим кодом шейдера.
Основная идея MSAA заключается в том, что фрагментный шейдер все еще выполняется только один раз для фрагмента. Каждый фрагмент имеет несколько выборок, и охват определяется выборкой. Это означает, что некоторые образцы фрагмента могут находиться внутри визуализированного многоугольника, а некоторые - снаружи. Вывод фрагмента шейдера затем записывается только в покрытые образцы. Но все покрытые образцы внутри фрагмента получают одинаковое значение.
Буфер глубины также имеет разрешение на выборку, что означает, что пересечения между полигонами также выигрывают от сглаживания, производимого MSAA.
Как только вы осознаете, как работает MSAA, становится понятным, что он ничего не делает для резких переходов внутри полигонов, которые могут быть результатом логики, применяемой в шейдере. Чтобы добиться сглаживания в этом случае, вам придется оценивать фрагментный шейдер на образец, чего не происходит с MSAA.
MSAA привлекателен, потому что он выполняет достаточное сглаживание для многих случаев использования с относительно минимальными издержками. Но, как вы заметили, этого явно недостаточно для всех случаев.
Что вы можете сделать по этому поводу выходит за рамки ответа здесь. Есть два основных направления:
- Вы можете избежать генерации резких переходов в вашем шейдерном коде. Если вы используете стандартное текстурирование, может помочь использование mipmaps. Для процедурных переходов вы можете сгладить их в своем коде, возможно, основываясь на значениях градиента.
- Вы можете использовать другой метод сглаживания. Слишком много, чтобы упомянуть здесь. Легко получить идеальное сглаживание с суперсэмплингом, но это очень дорого. Большинство методов пытаются достичь компромисса в получении лучших результатов, чем простой MSAA, не добавляя при этом слишком много накладных расходов.
Я несколько озадачен тем фактом, что вы получаете некоторое сглаживание по внутреннему краю с 32-кратным MSAA. Я не думаю, что это ожидается. Интересно, происходит ли что-то во время понижающей дискретизации, которая производит некоторую форму сглаживания.