Способы текстурирования ландшафта

Способы текстурирования ландшафта

Привет! Если ты увлекаешься процедурным генерированием ландшафта, эта статья поможет тебе в процедурном его текстурировании.

Так, как я специализируюсь на Unity - буду рассказывать всё то, что косвенно или прямо связано с ним.

Поехали!


Первый способ - Texture Splatting

В этом случае мы создаём Shader, который имеет 4 канала, такие, как R - красный, G - зелёный, B - синий, A - прозрачность. Если ландшафт очень большой - мы делим его на отдельные регионы, где каждый регион имеет по 4 канала.


R + G + B + A = RGBA


При текстурировании ландшафта мы записываем каналы исходной текстуры в соответствующие каналы для Shader'а. То есть красный цвет исходной текстуры записывается в R-канал, зелёный, синий и прозрачность точно также.

Такой способ хорошо экономит память, но в производительности сильно отстаёт от следующего кандидата. Тест на производительность:

Я как-то замерял, у меня каждая новая текстура заметно просаживала производительность. Вот заметка, например: Измеряю градацию FPS. Делаю так: добавляю по одной текстуре на ландшафт, запускаю сцену в редакторе и в сборке. FPS меряется компонентом FPS Counter. В редакторе измеряю чисто для сравнения. И только после разогрева, не сразу после запуска Unity.
1) Без текстур - 67/88
2) 1 текстура без карт нормалей - 64/82
3) 1 текстура с картой нормалей - 57/72
4) 2 текстуры с картами нормалей - 49/58
5) 4 разные текстуры с картами нормалей - 37/43
6) 4 одинаковые текстуры с картами нормалей - 38/43
7) 5 текстур с картами нормалей - 36/41
8) 8 текстур с картами нормалей - 36/41


Второй способ - "Всё в одном"

Да, второй способ не знаю как назвать (и есть ли у него название?). Потому, как ранее не встречал статью или мануал по данному способу, а пришёл к этому вынуждено.


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


Texture1 + (NoiseMap + Texture2) = Texture3


Такой способ не нуждается в вычислениях и сразу выводит (заранее подготовленную текстуру) на ландшафт.


Помимо простого смешивания текстур, мне нужно было смешивать текстуры на определённой высоте ландшафта, например трава - на равнинах, а камень - на склонах. Не представляю как мне удалось бы сделать такое первым способом, но для этого способа я знаю решение:

  1. Необходимо генерировать ландшафт так, чтобы порядок вершин в массиве располагались по формуле y + x * height.
  2. Находим самую высокую и низкую точку ландшафта, назовём вектор (x, y) как Elevation.
  3. Создаём массив heightMap и последовательно заполняем его высотой вершин по формуле Mathf.InverseLerp(Elevation.x, Elevation.y, vertex.y).
  4. Создаём и заполняем массив heightMapColors, на каждый (RGB) канал записываем значение heightMap. Прозрачности не должно быть.
  5. Создаём Texture2D и красим его через SetPixels(heightMapColors).

6. Передаём данную текстуру нашему Blit Shader'у, а в нём в свою очередь выполняем смешивание исходя из данной текстуры.


Texture1 + (HeightMap + Texture2) = Texture3


Если будут вопросы пиши в Telegram.

Наш канал о разработке игр.

Report Page