У меня есть сгенерированный ландшафт с шестиугольной геометрией, как показано на скриншоте ниже:
Затем я создаю биомы, но, как вы видите, границы между ними действительно некрасивые и прямые. Чтобы скрыть это гексагональное происхождение, мне нужно сгладить границы между биомами. Вот как это выглядит сейчас в каркасах с настоящими трингулярными гранями:
То, к чему я стремлюсь, это что-то вроде этого:
У каждой вершины есть атрибут, который содержит тип биома, я также могу добавить специальные атрибуты к вершинам на границе между двумя биомами, но я просто не могу понять, как осуществить это в шейдерном коде, очевидно, шум участвует здесь, но как мне сделать его непрерывным на нескольких лицах и на всей границе нескольких биомов?
Я рендеринг с WebGL с использованием THREE.js
Ответы:
Другие ответы здесь предлагают использовать текстуру. Вот техника, которая не использует текстуры.
Вы хотите, чтобы границы между шестиугольниками были интересными. Проще сделать интересные границы, когда вы перемещаете их в центр того, что рисуете. Вместо того, чтобы рисовать плитки напрямую, вы рисуете «двойник» плитки. Эта техника называется «угловая плитка» ( здесь и здесь, и здесь ). Двойником шестиугольника является треугольник, поэтому мы будем рисовать эти треугольники вместо шестиугольников:
Границы между шестиугольниками теперь находятся в середине визуализированных треугольников, так что это позволит нам делать с ними более интересные вещи. Бонус: вам нужно нарисовать только два треугольника на шестиугольник вместо шести (или двадцати четырех, как вы делаете сейчас).
Внутри каждого из этих треугольников мы хотим, чтобы фрагментный шейдер рисовал шестиугольники. Мы можем сделать это с помощью барицентрических координат . Положите (1,0,0), (0,1,0) и (0,0,1) в каждой вершине треугольника. Внутри треугольника эти координаты будут интерполированы. Фрагментный шейдер получит (a, b, c) и может посмотреть, какое значение является наибольшим - это скажет нам, какой из трех шестиугольников следует нарисовать в этой точке.
float max_n = max(barycentric.r, max(barycentric.g, barycentric.b)); if (max_n == barycentric.r) { color = v_color0; } else if (max_n == barycentric.g) { color = v_color1; } else if (max_n == barycentric.b) { color = v_color2; }
Это для прямых.
Если вы хотите шумные ребра, вы можете добавить шум к барицентрическим координатам:
Играя с амплитудой длина волны / частота шума, вы можете получить некоторые интересные эффекты:
Вы должны быть осторожны с шумом, следя за тем, чтобы он соответствовал границам треугольника. Один из способов сделать это - передать шестнадцатеричный идентификатор и использовать его в качестве начального значения для каждого из трех значений шума, добавляемых к барицентрическим координатам.
Я сделал интерактивную демонстрацию здесь . (Для демонстрации я не реализовал шестнадцатеричный идентификатор или некоторые другие вещи, которые могут вам понадобиться, если вы выполняли эту работу в реальном проекте - это просто быстрая и грязная демонстрация)
источник
Я уверен, что «можно» решить с помощью какого-либо алгоритма изображения, но если бы это был я, я бы, вероятно, решил это с помощью текстур. Я делал гексагональные текстуры, помещал их все в текстурный атлас, затем для каждого шестиугольника смотрел на его соседей и решал, какую текстуру применять.
Текстуры должны иметь версии для каждого типа местности плюс версии для каждого типа перехода.
Это похоже на то, сколько систем на основе плиток делают рельеф. Вот пример из 2d игр .
Другой возможностью было бы просто иметь свои текстуры для различных типов местности (вода, снег, грязь, трава) и добавлять количество миксов к каждой вершине шестиугольника, чтобы решить, как их смешивать.
Эта статья демонстрирует идею смешивания текстур ландшафта. Я не предлагаю следовать их реализации, но это показывает идею.
источник
Во-первых, сделайте ваши биомы текстурными. Сопоставьте треугольники с текскордами. Вы можете сделать это, используя проекцию Меркатора, или, что лучше, карту куба . Теперь, во фрагментном шейдере, сделайте что-то вроде этого:
где
noise
- некоторая псевдослучайная функция (использующая, скажем, синусоиды) в трехмерном положении вершины в пространстве модели, которая возвращает шумовое смещение к координате текстуры. Пример текстуры,GL_NEAREST
чтобы сохранить четкие границы.источник