Способы текстурирования ландшафта
Привет! Если ты увлекаешься процедурным генерированием ландшафта, эта статья поможет тебе в процедурном его текстурировании.Так, как я специализируюсь на Unity - буду рассказывать всё то, что косвенно или прямо связано с ним.
Поехали!
Первый способ - Texture Splatting
В этом случае мы создаём Shader, который имеет 4 канала, такие, как R - красный, G - зелёный, B - синий, A - прозрачность. Если ландшафт очень большой - мы делим его на отдельные регионы, где каждый регион имеет по 4 канала.

При текстурировании ландшафта мы записываем каналы исходной текстуры в соответствующие каналы для 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, который будет смешивать текстуры между собой и выводить "скомпонованный" результат, как одну текстуру.

Такой способ не нуждается в вычислениях и сразу выводит (заранее подготовленную текстуру) на ландшафт.
Помимо простого смешивания текстур, мне нужно было смешивать текстуры на определённой высоте ландшафта, например трава - на равнинах, а камень - на склонах. Не представляю как мне удалось бы сделать такое первым способом, но для этого способа я знаю решение:
- Необходимо генерировать ландшафт так, чтобы порядок вершин в массиве располагались по формуле y + x * height.
- Находим самую высокую и низкую точку ландшафта, назовём вектор (x, y) как Elevation.
- Создаём массив heightMap и последовательно заполняем его высотой вершин по формуле Mathf.InverseLerp(Elevation.x, Elevation.y, vertex.y).
- Создаём и заполняем массив heightMapColors, на каждый (RGB) канал записываем значение heightMap. Прозрачности не должно быть.
- Создаём Texture2D и красим его через SetPixels(heightMapColors).
6. Передаём данную текстуру нашему Blit Shader'у, а в нём в свою очередь выполняем смешивание исходя из данной текстуры.

Если будут вопросы пиши в Telegram.
Наш канал о разработке игр.