Я работаю над движком, похожим на Minecraft, в качестве хобби-проекта, чтобы посмотреть, насколько далеко можно продвинуть концепцию воксельных ландшафтов на современном оборудовании и OpenGL >= 3. Итак, вся моя геометрия состоит из четырехугольников или квадратов, если быть точным.
Я построил raycaster для оценки окружающего затенения и использовал технику «изогнутых нормалей» для освещения. Так что мои нормали не перпендикулярны к четырехугольнику и не имеют единичной длины; скорее, они указывают примерно на пространство, где происходит наименьшая окклюзия, и становятся короче, когда квадроцикл получает меньше света. Преимущество этого метода в том, что он требует только одноразового расчета окклюзии и практически бесплатен во время рендеринга.
Однако у меня возникают проблемы, когда я пытаюсь назначить разные нормали для разных вершин одного и того же четырехугольника, чтобы получить плавное освещение. Поскольку четырехугольник разбит на треугольники, а линейная интерполяция происходит по каждому треугольнику, результат интерполяции ясно показывает присутствие треугольников как уродливых диагональных артефактов:
Проблема в том, что OpenGL использует барицентрическую интерполяцию для каждого треугольника, которая представляет собой взвешенную сумму по 3 из 4 углов. В идеале я хотел бы использовать билинейную интерполяцию, когда при вычислении результата используются все 4 угла.
Я могу придумать некоторые обходные пути:
Вставьте нормали в текстуру RGB 2x2 и позвольте процессору текстур выполнить билинейную интерполяцию. Это происходит за счет поиска текстуры во фрагментном шейдере. Мне также нужно было бы упаковать все эти мини-текстуры в более крупные для эффективности.
Используйте атрибуты вершин, чтобы прикрепить все 4 нормали к каждой вершине. Также прикрепите к каждой вершине некоторые коэффициенты [0..1], очень похожие на текстурные координаты, и выполните билинейную интерполяцию во фрагментном шейдере. Это происходит за счет передачи шейдеру 4 нормалей вместо 1.
Я думаю, что обе эти техники можно заставить работать, но они кажутся мне бесполезными для чего-то, что должно быть намного проще. Возможно, я мог бы как-то трансформировать нормали, чтобы интерполяция OpenGL давала результат, не зависящий от конкретной используемой триангуляции.
(Обратите внимание, что проблема не специфична для нормалей; она в равной степени применима к цветам или любым другим значениям, которые необходимо плавно интерполировать в четырехугольнике.)
Любые идеи, как еще подойти к этой проблеме? Если нет, то какой из двух вышеперечисленных методов будет лучшим?