Эта запись является краткой историей про то как я выполнял тектурирование ландшафта в своем движке.
Все началось несколько месяцев назад, когда я писал игру на конкурс стратегий: нужно было отрисовывать ландшафт.
Тогда я удовлетворился очень простым решением, а именно:
никакого куллинга (а зачем если весь ландшафт 128х128 квадов? )
простое смешивание 2х текстур в шейдере.
Смотрится оно просто:
Однако, где-то неделю назад захотелось сделать лучше.
Что мы хотим?
поддержку большого количества текстур, например 32 текстуры.
процедурное смешивание.
Что имеем?
openGL 2.1 + GLSL 1.0
SM3
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 4 (что-бы запускалось, и на домашнем ПК, и на ноутбуке)
Что делать?
На таком GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS развернуться довольно сложно, но можно:
1. Рисуем ладшафт в отдельный фрейм-буффер: во фрагмент пишем: ( RG = texCoord, B - освещенность, A - не используется )
результат:
2. Включаем аддитивный бленд и для каждой задействованой текстурки рисуем FSQ(full screen quad):
В шейдер передаем:
1 - текстура подученная на этапе №1.
2 - дуффузная текстура ( трава/песок/eth ).
3 - маска, в которой находится вклад текстуры(2) в каждый из тайлов.
4 - текстура с 2d шумом.
В шейдере:
читаем из текстуры №1 uv координаты.
к uv прибавляем значение полученное из текстуры с шумом.
вычисляем по uv координатам номер тайла + используя uv координаты, делаем выборку из диффузной текстуры.
вычисляем освещение( я вычислял по Ламберту )
Результат
- я доволен.
PS
1. лучше рисовать треугольник, вместо квадрата.
Дело в том, что в связи в особенностями реализации функции texture2D может появиться диагональная полоса посередине экрана, при использовании квадрата.
2. Шейдер: http://pastebin.com/wqCmN2HU
3. Хороший результат получается, если вместо текстуры шума использовать карту нормалей.
4. На новеньком железе такие приключения совсем не обязательны.
5. Фрагментный шейдер очень тяжелый - стараемся экономить на фрагментах.
6. Надеюсь, что не сильно накосячил с орфографией :-)