Различные векторы OpenGL / GLSL: как избежать звездных всплесков вокруг вершин? - PullRequest
0 голосов
/ 01 января 2012

В OpenGL 2.1 я передаю позицию и вектор нормали своему вершинному шейдеру.Затем вершинный шейдер устанавливает varying на вектор нормали, поэтому теоретически он линейно интерполирует нормали по каждому треугольнику.(Как я понимаю, это основа затенения Фонга.)

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

Вот пример, не из моего собственного рендеринга, а демонстрирующий точно такой же эффект (см. Золотую сферуна полпути вниз по странице): http://pages.cpsc.ucalgary.ca/~slongay/pmwiki-2.2.1/pmwiki.php?n=CPSC453W11.Lab12

Википедия говорит: это проблема с затенением Гауро.Но насколько я понимаю, интерполируя нормали и выполняя расчеты освещения для каждого фрагмента, я использую модель Фонга, а не Гуро.Это правильно?

Если бы я использовал гораздо более мелкую сетку, я предполагаю, что эти звездные всплески были бы гораздо менее заметны.Но является ли добавление большего количества треугольников единственным способом решения этой проблемы?Я думаю, что был бы способ получить плавную интерполяцию без эффекта звездообразования.(Я, конечно, видел совершенно плавное затенение на грубых сетках в других местах, например, в 3D Studio Max. Но, возможно, они делают что-то более сложное, чем просто интерполяция нормалей.)

Ответы [ 2 ]

5 голосов
/ 01 января 2012

Это не точный тот же эффект.То, что вы видите, является одной из двух вещей.

  1. Результат не нормализации нормалей перед их использованием в вашем фрагментном шейдере.

  2. Anоптическая иллюзия, созданная столкновением линейных градиентов по краям треугольников.Действительно.

    Раздел «Вопросы градиента» в нижней части этой страницы (примечание: в интересах полного раскрытия, это мое руководство) объясняет это явление в деталях.Простая диффузная отражательная способность Ламберта с использованием интерполированных нормалей эффективно создает более или менее линейный свет через треугольник.Треугольник с другим набором нормалей будет иметь другой градиент.Он будет непрерывным C0 (цвета по краям одинаковы), но не непрерывным C1 (цвета по двум градиентам изменяются с разной скоростью).

    Человеческое зрение обнаруживает подобные градиентные различия и создаетони выделяются.Таким образом, мы рассматриваем их как жесткие грани, когда на самом деле они не являются.

    Единственное реальное решение здесь - это либо тесселяция сетки дальше, либо использование карт нормалей, созданных из более тонкой версии сетки, вместо интерполированных нормалей.

2 голосов
/ 01 января 2012

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

...