Как сделать билинейную интерполяцию нормалей по четырехугольнику?

Я работаю над движком, похожим на Minecraft, в качестве хобби-проекта, чтобы увидеть, насколько далеко концепция вокселей terrains можно протолкнуть на современном оборудовании и OpenGL> = 3. Итак, вся моя геометрия состоит из четырехугольников или, если быть точным, квадратов.

Я построил raycaster для оценки окружающей окклюзии и использовал технику "изогнутых нормалей" для освещения. Так что мои нормали не перпендикулярны квадрату и не имеют единичной длины; скорее, они указывают примерно на пространство, где меньше всего окклюзии, и становятся короче, когда квад получает меньше света. Преимущество этого метода состоит в том, что он просто требует единовременного расчета окклюзии и практически бесплатен во время рендеринга.

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

Diagonal lines visible in the rendered result

Проблема в том, что OpenGL использует барицентрическую интерполяцию для каждого треугольника, что представляет собой взвешенную сумму по 3 из 4 углов. В идеале я бы хотел использовать билинейную интерполяцию, когда все 4 угла используются для вычисления результата.

Я могу придумать некоторые обходные пути:

  1. Вставьте нормали в текстуру 2x2 RGB и позвольте текстурному процессору выполнить билинейную интерполяцию. Это происходит за счет поиска текстуры во фрагментном шейдере. Мне также нужно было бы упаковать все эти мини-текстуры в более крупные для повышения эффективности.

  2. Используйте атрибуты вершин, чтобы прикрепить все 4 нормали к каждой вершине. Также прикрепите некоторые коэффициенты [0..1] к каждой вершине, как координаты текстуры, и выполните билинейную интерполяцию во фрагментном шейдере. Это происходит за счет передачи в шейдер 4 нормалей вместо одной.

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

(Обратите внимание, что проблема не специфична для нормалей; она в равной степени применима к цветам или любому другому значению, которое необходимо плавно интерполировать по квадрату.)

Есть идеи, как еще подойти к этой проблеме? Если нет, какой из двух вышеперечисленных методов будет лучшим?

13
задан Thomas 11 February 2012 в 12:36
поделиться