
Привет! В этой статье я расскажу о том, как сделал шейдер речной воды для нашей игры. Предполагается, что читатель уже знаком с базовыми понятиями компьютерной графики, такими как карты нормалей и высот, имеет некоторое представление о работе шейдеров, и интересуется примерами реализации некоторых эффектов. Нашу игру мы делаем на Unity, и шейдер написан на HLSL, но статья описывает общий подход и практически не содержит специфики, характерной для этих инструментов. Я надеюсь, что она может быть полезна любому, кто интересуется практической компьютерной графикой для игр.
Сначала нам нужно определить форму волн. Берем normal map волн и поворачиваем в каждой точке в направлении, определяемом картой течений, которая задается тоже как normal map. В результате получим полную карту нормалей для всей поверхности реки:
Добавляем движение: смещаем волны по X в зависимости от текущего времени:
К постоянным волнам от течения реки добавляем динамические волны от объектов в игре, взаимодействующих с водой (таких как лодки и их весла, плещущиеся рыбы и прочее). Для этого во время игры на серой текстуре каждый фрейм рисуем карту высот: осветляем там, где волны выше общего уровня, и затемняем там, где ниже. Затем в шейдере считаем нормали этой карты высот и складываем их с нормалями из предыдущего пункта:
Используем итоговую карту нормалей для получения отражения неба в воде: для каждого пикселя воды мы рисуем пиксель с текстуры неба, смещенный в зависимости от положения относительно центра экрана плюс нормали:
Вода искажает то, что находится за ней, в зависимости от толщины слоя. Используем GrabPass, чтобы получить текстуру с фоновым изображением, и сместим итоговое изображение в зависимости от карты глубины, задаваемой еще одной текстурой на входе шейдера:
Волны тоже влияют на толщину слоя воды в каждой отдельной точке, так что карту нормалей из предыдущих пунктов мы также учитываем для этого эффекта:
Теперь мы складываем все эти эффекты вместе в определенной пропорции (зависящей от глубины и произвольно заданных параметров), и также добавляем собственный цвет воды:
Бонус: разберем параметры шейдера
- Stream Matrix: Карта нормалей, определяющая направление течения.
- Depth Map: Карта глубины реки.
- Water Texture: Текстура, определяющая собственный цвет реки.
- Waves Normal Map: Карта нормалей волн.
- Waves Overlay: Карта высот динамических волн (в игровой сцене это RenderTexture).
- Skysphere Texture: Текстура неба.
- Segments: Количество сегментов, на которые разбивается область, в каждом сегменте текстура волн поворачивается независимо.
- Blend Threshold: Определяет гладкость смешивания соседних сегментов.
- Speed: Скорость течения.
- Waves Reflection Scale: Насколько сильно волны искажают отражение неба.
- Camera Reflection Scale: Масштаб неба относительно изображения на экране.
- Depth Scale: Насколько сильно глубина влияет на искажение дна.
- Waves Height Scale: Насколько сильно волны влияют на искажение дна.
- Min Share of Bottom: Насколько хорошо дно видно на максимальной глубине, этот параметр вместе с глубиной в конкретной точке влияет на долю дна в окончательном результате.
- Sky/Water: Взаимные доли отражения неба и собственного цвета воды в окончательном результате.
Вступайте в наше сообщество, следите за новостями и делитесь нашими статьями с друзьями!
Смотрите также:
Комментарии
Очень любопытно!
Вот только меня интересует такой вопрос: а как вы складываете карту нормалей с картой высот? нормали это все таки вектор направления, а не высота. Было бы любопытно взглянуть на идею преобразования нормали в высоту.
И я правильно понимаю, что это происходит для всего экрана и карта течения и остальные генерируются на ходу? Было бы интересно почитать тоже по этому поводу
<a href= http://mosros.flybb.ru/viewtopic.php?f=2&t=635>Процесс получения диплома стоматолога: реально ли это сделать быстро?</a>