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