2013-05-13 4 views
2

Я пытаюсь добиться текстурирования ландшафта с использованием трехмерной текстуры, состоящей из нескольких слоев материала и плавного смешивания между материалами.Multi-Texturing - Интерполяция между двумя слоями 3D-текстуры

Может быть, моя иллюстрация будет объяснить это лучше:
Pretty picture

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

Вершины:
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. Спасибо за прочтение.
P.S .: Извините, если я допустил некоторые ошибки в этом тексте, английский не является моим родным языком.

ответ

1

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

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

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

  • Каждая вершина имеет 1 пара (и, v) из texure coodrinates
  • Вы должны п текстур образца в (T1, T2, T3, ..., Tn), которые представляют разные слои местности: песок, трава, скала и т. Д.
  • У вас есть текстура (ы) масок n всего в целом, где хранятся коэффициенты смешивания для каждой текстуры T в его каналах: R канал имеет альфа для T1, G канал для T2, B для T3, ... и т.д.
  • В пиксельном шейдере вы выборка текстур слоя, как обычно, и получить значение цвета 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);

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

Не уверен, но надеюсь, что это поможет! Счастливое кодирование! =)

+0

Спасибо за ваш ответ :) К сожалению, почти ничего не изменилось - я просто получил то же изображение, но сгладил, как вы можете видеть на этом скриншоте (http://i.imgur.com/kdVUswN.png). –

+0

Ничего себе, большое обновление. Похоже, я не ясно заявил, что мой ландшафт состоит из «блоков» (воксела), а подход на основе высоты не может использоваться, так как я хочу, чтобы пользователь редактировал рельеф, добавляя другие материалы. Но текстурная маскировка кажется интересной, может быть, я попробую ее добиться эффекта splating. Надеюсь, в ps_3_0 достаточно пробников текстур, я посмотрю. Спасибо, это становится немного яснее, я буду держать вас в курсе моего прогресса :) –

+0

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