Как сделать билинейную интерполяцию нормалей по квадру? - PullRequest
13 голосов
/ 11 февраля 2012

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

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

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

Diagonal lines visible in the rendered result

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

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

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 11 февраля 2012

Как вы ясно понимаете, треугольная интерполяция, которую сделает GL, - это не то, что вам нужно.Поэтому обычные данные не могут поступать непосредственно из данных вершин.

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

Есть несколько хитростейВы можете сделать, чтобы несколько упростить процесс, хотя.

  • Использование идентификатора вершины может помочь вам определить, какой «угол» вершины будет проходить от вершины к фрагментному шейдеру (наши значения [0..1]).Простой битовый тест на младших 2 битах может дать вам знать, какой угол пройти, без фактического ввода вершинных данных.Если вы упаковываете данные текстуры, вам все равно нужно передать идентификатор внутри текстуры, так что это может быть спорным.
  • Если вы используете текстуры 2x2 для интерполяции, есть (были?) Некоторые ошибки.Некоторые текстурные интерполяторы не обязательно дают высокоточную интерполяцию, если источник с низкой точностью для начала.Для этого может потребоваться изменить тип данных текстуры на более точный, чтобы избежать появления артефактов полосатости.
0 голосов
/ 11 февраля 2012

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

Другим способом были бы некоторые уловкив пиксельном шейдере ... один из возможных способов - вы можете фактически интерполировать текстуру самостоятельно (и не использовать встроенный интерполятор) в пиксельном шейдере, что может вам очень помочь.И вы не ограничены только билинейной интерполяцией, вы могли бы добиться большего, Fe бикубическая интерполяция;)

...