Multi-Texturing - интерполяция между двумя слоями 3D-текстуры

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

Возможно моя иллюстрация объяснит это лучше:
Приятная картина

Просто представьте, что каждый цвет представляет собой классную текстуру местности, такую ​​как трава, камень и т. Д.
Я хочу, чтобы они были правильно смешаны, но при текущем подходе я получаю все текстуры между запрошенными, кроме текстур, которые я хочу отображать (это кажется логичным, потому что, как я прочитал, 3D-текстура рассматривается как трехмерный массив вместо столбов текстуры).
Текущий (и, конечно, глупый) подход прост как круговая диаграмма ("текущий" результат отображается с использованием точечной интерполяции, желаемый результат расписывается вручную):

Вершины:
Vertex 1: Position = Vector3.Zero, UVW = Vector3.Zero
Vertex 2: Position = Vector3(0, 1, 0), UVW = Vector3(0, 1, 0.75f)
Vertex 3: Position = Vector3(0, 0, 1), UVW = Vector3(1, 0, 1)
Как видите, первая вершина треугольника использует первый материал (красный), вторая вершина использует третий материал (синий), а третья вершина использует последний четвертый материал (желтый).

Вот как это делается в пиксельном шейдере (UVW передается напрямую без изменений):
float3 texColor = tex3D(ColorTextureSampler, input.UVW);
return float4(texColor, 1);
Причина моего выбора - моя структура местности. Ландшафт создается из вокселей (каждый воксель содержит идентификатор материала) с использованием марширующих кубов. Каждая вершина "сварена", потому что сетки довольно большие, и я не хочу делать каждый треугольник индивидуальным (но я все еще могу сделать это, если нет способа решить мой вопрос, используя связанные вершины).
Недавно я пришел к мысли о том, чтобы хранить идентификаторы материала двух других вершин треугольника и их коэффициенты смешения (у меня будет пара float2 UV, float3 для идентификаторов материала и float3 для коэффициента смешения каждого идентификатора материала) в каждой вершине, но я не вижу способа сделать это, не разбив мою сетку на отдельные треугольники.
Любая помощь будет принята с благодарностью. Я нацеливаюсь на SlimDX с C# и Direct3D 9 API. Спасибо за прочтение.
PS: извините, если я допустил некоторые ошибки в этом тексте, английский не мой родной язык.

1 ответ

Решение

Возможно, ваш ColorTextureSampler с использованием точечной фильтрации (D3DTEXF_POINT). Используйте либо D3DTEXF_LINEAR или же D3DTEXF_ANISOTROPIC достичь желаемого эффекта интерполяции. Я не очень знаком с SlimDX 9, но у вас есть идея.

Кстати, хорошая иллюстрация =)

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

  • Каждая вершина имеет 1 пару (u, v) текстурных coodrinates
  • У вас есть n текстур для выборки (T1, T2, T3, ..., Tn), которые представляют разные слои ландшафта: песок, трава, камень и т. Д.
  • Вы имеете маску текстуры (ов) в общей сложности n каналов, которая хранит коэффициенты смешивания для каждой текстуры T в своих каналах: R канал содержит альфа для T1, G канал для Т2, B для Т3,... и т. д.
  • В пиксельном шейдере вы выбираете обычные текстуры слоев и получаете значения цвета float4 val1, val2, val3...
  • Затем вы выбираете текстуру маски для соответствующих коэффициентов смешивания и получаете float blend1, blend2, blend3, ...
  • Затем вы применяете некоторый алгоритм смешивания, например, простую линейную интерполяцию:
float4 terrainColor = lerp( val1, val2, blend1 );
terrainColor = lerp( terrainColor, val3, blend2);
terrainColor = lerp( terrainColor, ..., blendN );

Например, если ваш T1 - трава, и у вас есть большое поле травы в середине вашей карты, вы будете махать большим красным полем в середине.

Этот алгоритм немного медленный из-за большой выборки текстур, но прост в реализации, дает хорошие визуальные результаты и наиболее гибок. Вы можете использовать не только маску в качестве коэффициентов смешения, но и любые значения: например, высоту (выборка большего количества снега в горных вершинах, скалы в горах, грязь в низине), уклон (скала на крутом склоне, трава на ровной поверхности), даже фиксированные значения, и т.д. Или перепутайте все это. Также вы можете варьировать смешивание: используйте встроенный lerp или что-то более сложное (предупреждение! этот пример глуп):

float4 terrainColor = val1 * val2 * blend1 + val2 * val3 * blend2;
terrainColor = saturate(terrainColor);

Игра с blend algo - самая интересная часть этого подхода. И вы можете найти много-много методов в Google.

Не уверен, но надеюсь, что это поможет! Удачного кодирования! знак равно

Другие вопросы по тегам