Шумные края, сглаживание краев между гранями через фрагментарный шейдер

У меня есть сгенерированный ландшафт с гексагональной геометрией, как показано на скриншоте ниже:

 введите описание изображения здесь>> </a> </p>

<p> Затем я создаю биомы, но, как вы видите, границы между ними действительно уродливые и прямые. Чтобы скрыть это шестиугольное происхождение, мне нужно было бы сгладить границы между биомами. Так выглядит теперь в каркасе с реальными треугольными гранями: </p>

<p> <a href= введите описание изображения здесь>> </a> </p>

<p> То, что я стремлюсь, - это нечто большее: </p>

<p> <a href= введите описание изображения здесь>> </a> </p>

<p> Каждая вершина имеет атрибут, который содержит тип биома, я также могу добавить специальные атрибуты к вершинам на границе между двумя биомами, но я просто не могу понять, как это сделать в шейдерном коде , здесь явно задействован шум, но как сделать его непрерывным через несколько лиц и всю границу нескольких биомов? </p>

<p> Я выполняю рендеринг с помощью WebGL с помощью THREE.js </p></body></html>

9 голосов | спросил user1617735 29 MarpmWed, 29 Mar 2017 23:49:50 +03002017-03-29T23:49:50+03:0011 2017, 23:49:50

3 ответа


9

Другие ответы здесь предлагают использовать текстуру. Вот техника, которая не использует текстуры.

Вы хотите, чтобы границы между шестиугольниками были интересными. Легче сделать интересные границы, когда вы перемещаете их в центр того, что вы рисуете. Вместо того, чтобы рисовать плитки напрямую, вы рисуете «двойную» плитки. Этот метод называется «угловая плитка» ( здесь и здесь и здесь ). Двойной шестиугольник является треугольником, поэтому мы будем рисовать эти треугольники вместо шестиугольников:

 треугольные двойники шестиугольника

Границы между шестиугольниками теперь находятся посередине отображаемых треугольников, поэтому мы будем делать с ними более интересные вещи. Бонус: вам нужно всего лишь выделить два треугольника на шестиугольник вместо шести (или двадцать четыре, как вы сейчас делаете).

Внутри каждого из этих треугольников мы хотим, чтобы шейдер фрагмента рисовал шестиугольники. Мы можем сделать это с помощью барицентрических координат . Положите (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; }

Это для прямых линий.

Если вы хотите шумные края, вы можете добавить шум в барицентрические координаты:

 шестиугольник с шумными краями

Играя с амплитудой длины волны /частотой шума, вы можете получить некоторые интересные эффекты:

 шестиугольник с еще более шумными краями

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

Я сделал интерактивную демонстрацию здесь . (Для демонстрации я не реализовал шестнадцатеричный идентификатор или некоторые другие вещи, которые вам могут понадобиться, если вы делаете эту работу в реальном проекте - это просто быстрое и грязное демо)

ответил amitp 30 J000000Sunday17 2017, 19:16:32
0

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

Текстуры должны иметь версии для каждого типа ландшафта плюс версии для каждого типа перехода.

Это похоже на то, как много систем на основе плитки делают рельеф. Вот пример из 2d игр .

Еще одна возможность - просто иметь текстуры для различных типов ландшафта (вода, снег, грязь, трава) и добавить количество миксов в каждую вершину шестиугольника, чтобы решить, как их смешивать.

В этой статье показана идея смешивания текстур ландшафта. Я не предлагаю следовать их реализации, но он показывает эту идею.

ответил gman 31 MarpmFri, 31 Mar 2017 13:11:11 +03002017-03-31T13:11:11+03:0001 2017, 13:11:11
0

Сначала сделайте свои биомы текстурой. Сопоставьте треугольники с texcoords. Вы можете сделать это, используя проекцию меркатора, или, лучше, карта куба . Теперь, в шейдере фрагмента, сделайте что-то вроде этого:

// frequency and magnitude of the noise in texels.
uniform float frequency;
uniform float magnitude;

// This function should just look like random smooth noise in x,y
// This one isn't great, but you can experiment.
vec2 noise(vec3 vertexPos) {
    return vec2(sin(vertexPos.x * frequency + vertexPos.y * frequency) * magnitude, 
                cos(vertexPos.y * frequency * 2 + vertexPos.z * frequency) * magnitude);
}

// Sample the texture and preturb it with noise based on the world
// position of the fragment.
vec4 frag(vec2 texCoord, vec3 fragmentPos) {
   return texture(mySampler, texCoord + noise(fragmentPos));
}

где noise - некоторая псевдослучайная функция (используя, скажем, синусоиды) в 3D-положении вершины в пространстве модели, которая возвращает шумное смещение к координате текстуры. Пример текстуры с использованием GL_NEAREST для сохранения четких границ.

ответил mklingen 10 J000000Monday17 2017, 22:17:33

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132