Как сделать дождь в unity

Математика в Gamedev по-простому. Кривые и рябь для эффекта дождя в Unity

Всем привет! Меня зовут Гриша, и я основатель CGDevs. Продолжим говорить про математику что ли. Пожалуй, основное применение математики в геймдеве и компьютерной графики в целом – это VFX. Вот и поговорим про один такой эффект – дождь, а точнее про его основную часть, требующую математики – рябь на поверхности. Последовательно напишем шейдер для ряби на поверхности, и разберём его математику. Если интересно – добро пожаловать под кат. Гитхаб проект прилагается.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Иногда наступает такой момент в жизни, когда программист должен взяться за бубен и призвать дождь. В целом сама по себе тема моделирования дождя очень глубокая. Существует множество математических работ по разным частям этого процесса от падения капли и эффектов связанных с этим до распределения капель в объёме. Разберём только один аспект – шейдер, который позволит нам создавать эффект похожий на волну от упавшей капли. Пора браться за бубен!

При поиске в интернете находишь очень много забавных математических выражений для генерации ряби. Часто они состоят каких-то «магических» чисел и периодической функции без обоснований. Но вообще математика подобного эффекта довольно простая.

Нам понадобится всего лишь уравнение плоской волны в одномерном случае. Почему плоской и одномерной разберём чуть позже.

Уравнение плоской волны в нашем случае может быть записано как:

Aresult = A * cos(2 * PI *(x / waveLength – t * frequency));
Где:
Aresult – амплитуда в точке x, в момент времени t
А – максимальная амплитуда
wavelength – длина волны
frequency – частота волны
PI – число ПИ = 3.14159 (float)

Первое, что нам понадобится – это уравнение окружности. Волна нашего шейдера будет симметрична относительно центра. Уравнение окружности в 2д случае описывается, как:

нам понадобится радиус, так что уравнение приобретёт форму:

и это даст нам симметрию относительно точки (0, 0) в меше, что сведёт всё к одномерному случаю плоской волны.

Теперь напишем шейдер. Я не буду разбирать каждый шаг написания шейдера, так как это не цель статьи, но за основу берётся Standard Surface Shader из Unity, шаблон которого можно получить через Create->Shader->StandardSurfaceShader.

Кроме этого, добавляются проперти необходимые для волнового уравнения: _Frequency, _WaveLength и _WaveHeight. Проперти _Timer (можно было бы использовать время с гпу, но при разработке и последующем анимировании удобнее его контролировать вручную.

Напишем функцию getHeight получения высоты (сейчас это координата Z) подставив уравнение окружности в волновое уравнение

Написав шейдер с нашим волновым уравнением и уравнением окружности — получим такой эффект.

Волны есть. Но хочется, чтобы анимация начиналась и заканчивалась плоскостью. В этом нам поможет функция синуса. Домножив амплитуду на sin(_Timer * PI) получим плавное появление и исчезновение волн. Так как _Timer принимает значения от 0 до 1, а синус в нуле и в PI равен нулю, это как раз то, что нужно.

Пока совсем не похоже на падение капли. Проблема в том, что энергия волной теряется равномерно. Добавим проперти _Radius, которая будет отвечать за радиус действия эффекта. И домножим на амплитуду clamp(_Radius — rad, 0, 1) и получим уже эффект больше похожий на правду.

Ну и заключительный шаг. То, что амплитуда в каждой отдельной точке достигает своего максимума в момент времени равный 0.5 не совсем верно, эту функцию лучше заменить.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Тут мне стало немного лень считать, и я просто домножил синус на (1 — _Timer) и получил такую кривую.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

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

В итоге получился такой шейдер и эффект.

Сетка меша – это важно

Возвращаясь немного к теме предыдущей статьи. Волны реализованы вертексным шейдером, поэтому сетка меша играет достаточно большую роль. Так как известна природа движения задача упрощается, но в целом от формы сетки зависит финальный визуал. Разница становится не существенной при высокой полигональности, но для производительности чем меньше полигонов, тем лучше. Ниже картинки, иллюстрирующие разницу между сетками и визуалом.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Даже при вдвое большем числе полигонов второй меш даёт неправильный визуал (оба меша сгенерированы с помощь Triangle.Net, просто по разным алгоритмам).

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

С проектом в целом и тем, как это работает можно ознакомиться тут. Правда часть ресурсов пришлось убрать из-за ограничений по весу гитхаба (hdr skybox и машина).

Спасибо за внимание! Надеюсь, статья будет кому-то полезна, и стало чуть понятнее зачем может понадобится тригонометрия, аналитическая геометрия (всё что связано с кривыми) и другие математические дисциплины.

Читают сейчас

Редакторский дайджест

Присылаем лучшие статьи раз в месяц

Скоро на этот адрес придет письмо. Подтвердите подписку, если всё в силе.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Похожие публикации

Расширение редактора Unity через Editor Window, Scriptable Object и Custom Editor

Математика в Gamedev по-простому. Векторы и интегралы

Работа с EventSystem в Unity. Базовые вещи в работе с UI

Средняя зарплата в IT

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Минуточку внимания

Комментарии 22

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

судя по всему, когда на видео странно шевелится асфальт — это оно.

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

В шейдере с несколькими полюсами сделано вообще неоптимально, лучше параметры полюса передавать в этом случае через vertexColor, а не через текстуру. В данном случае текстура не имеет особого смысла

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

А если ввести ещё одну текстуру и накладывать её на блеск, где есть эффект ряби, то пропадёт эффект «вся дорога под водой»?

Как сделать дождь в unity. Смотреть фото Как сделать дождь в unity. Смотреть картинку Как сделать дождь в unity. Картинка про Как сделать дождь в unity. Фото Как сделать дождь в unity

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

Разберём немного способы:

Отдельный меш поверх — плохая затея. С рефракцией и альфа блендингом самой волны можно будет чокнуться. Ну точнее ничего сверх естественного нет, но получится просто лишняя сложность.

О чём я думал, не назову это способом, просто что мне приходило в голову. Тут суть не в блеске. Если думать над тем, чтобы делать «быстро» без сложной фрагментной части в целом. У нас есть 8 параметров доступных для записи (4 координаты тангентов и вертекс колоров) Если делать процедурненький алгоритм, то мы просто записываем что-то вроде нормал мапа в тангенты, а данные о полюсах в вертекс колоры меша. Для того чтобы разбросать лужи — генерируем шум (поэтому в проекте можно найти простой генератор текстуры шума перлина, так как сама генерация интегрирована в юнити) Дальше, делаем лужи хайполи, а остальную геометрию лоуполи (процедурно — это не так сложно на самом деле, просто по шуму генерируем сетку меша специальным образом) По идее в данном случае нормали в вертексе в соответствии с «кривизной лужи» дадут правильный эффект. Шум станет картой отражений (так как лужа должна отражать сильнее, чем меш под ней) и должно получиться красиво и +- универсальненько. Но условно этот проект я собирал дня 4 где-то (так как надо ещё же найти всю информацию, которую я постарался структурировано описать), а вот всё что я описал писать ещё недельку, и мне пока не до того.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *