Подводная каустика в Unity

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

Загляните на YouTube, если вам интересно, как может выглядеть окончательный результат.

Что такое каустика?

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

Расчет этих преломлений света — трудоемкий процесс, особенно если вы делаете графику в реальном времени, поэтому обычной практикой является использование предварительно рассчитанных текстур каустики. Программное обеспечение Caustics Generator можно использовать для создания текстур каустики, которые могут быть мозаичными и зацикленными, что идеально подходит для создания графики в реальном времени.

Как использовать текстуры каустики?

Основной принцип текстурирования каустики заключается в том, что вы проецируете плоскую текстуру света по одной координате на геометрию вашей сцены.

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


Текстурирование излучения в UV-координатах с использованием стандартного шейдера Unity

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


Проэцированная текстура Emissive канала в мировом пространстве

Создание проецирования шейдера в эмиссии

Базовое текстурирование объектов с использованием стандартного шейдера в Unity выполняется в файле с именем UnityStandardCore.cginc. Есть две функции, которые выполняют текстурирование; FragForwardBase () и fragDeferred (). Первый используется, когда ваша камера настроен на использование прямого пути рендеринга, а последний — когда вы используете путь отложенного рендеринга.

Модификация, которую мы собираемся внести в эмиссионную часть шейдера, одинакова для обоих методов рендеринга. Мы собираемся немного изменить вызов Emission () в этих функциях.

Мы не хотим использовать UV-координаты объекта, то есть выражение i.tex.xy, для нашего текстурирования. Вместо этого мы хотим вычислить угловую проекцию текстуры каустики в мировом пространстве. Давайте углубимся в код, который нам нужен для этого.
Этот код включает немного более причудливых вещей, которые улучшают текстурирование каустики, но мы рассмотрим его постепенно, чтобы объяснить, что происходит.
Как сказано в комментарии, мы хотим, чтобы каустические паттерны появлялись только на тех частях объекта, которые находятся ниже поверхности воды. Поэтому мы вводим переменную с именем _CausticsStartLevel, которая представляет собой Y-координату мирового пространства, в которой начнут появляться каустики.
Ветер, воздействующий на водную поверхность, заставляет волны перемещаться по направлению ветра. Чтобы каустика выглядела более естественно, мы перемещаем образцы каустики для имитации движения поверхности. _CausticsDrift — это мировой вектор, задающий скорость движения.
На мелководье не так много каустических эффектов из-за небольшого схождения света. Поэтому мы вводим расстояние затухания от начального уровня каустики по оси Y. Это также делает текстурирование более плавным, так как не будет внезапного начала каустики, когда линия воды нарушит другую геометрию.
Еще один фактор, который стоит принять во внимание, — это то, что свет почти всегда идет сверху. Это означает, что дно объектов, помещенных в воду, не освещается каустиками. Однако мы немного расширим края дна с +0,5 значения косинуса, заданного операцией с точкой, чтобы имитировать, что свет может входить под углом из-за преломления воды.
Самая важная часть всего процесса текстурирования — это вычисление проекции текстуры каустики в мировое пространство. Поэтому мы берем мировую координату текселя, который вычисляется, и вращаем этот тексел, используя матрицу ориентации света, которая в основном представляет направление падающего света. Позже мы рассмотрим, как рассчитывается эта матрица. Взяв координаты X и Y из плоскости XY повернутой координаты текселя, мы теперь имеем координату текстуры для нашей текстуры каустики.
Заключительная часть всего процесса — использовать вычисленную координату текстуры и образец из текстуры каустики с использованием исходной функции Emission (). Затем мы компенсируем факторы затухания и дна, которые устраняют нежелательные нам части излучения каустики.

Анимация и направление света

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

Мы выполняем анимацию текстуры, добавляя сценарий в Unity к одному из объектов, использующих материал с нашим новым шейдером.

Скрипт просто заменяет текстуру излучения новой через заданные промежутки времени. Как и было обещано в предыдущей главе, здесь мы также обеспечиваем расчет матрицы ориентации света, которая использовалась для расчета проекции в шейдере. Если вы не хотите постоянно пересчитывать матрицу проекции света, вы можете вставить предварительно вычисленную матрицу прямо в код шейдера.
Почему мы используем наклонную матрицу проекции, а не просто проекцию с плоским верхом по оси Y? Что ж, если вы выполняете текстурирование ландшафта, будет совершенно нормально, и, возможно, даже лучше, использовать плоскую проекцию мира по оси вниз. Однако, если вы делаете бассейн, вам также нужны каустики на вертикальных стенках бассейна. Наклоняя угол проецирования, вы получите красивый выступ даже на вертикальных стенах

Итог

Текстурирование Caustics обеспечивает последний штрих ко всему рендерингу воды и является обязательным для каждой современной симуляции воды. В этой статье предлагается способ его реализации, который не увеличивает дополнительных затрат на конвейер рендеринга. Пакет, содержащий полностью модифицированные стандартные шейдеры для Unity 5, можно скачать по ссылке ниже. Вы можете свободно использовать этот код в своих собственных проектах Unity. Код в этой статье и модификации стандартных шейдеров Unity предоставляются без лицензии (Public Domain).

Дополнительная информация

Скачать полный код шейдера каустики Сылка

Скачайте с официального сайта: Caustics Generator

Статья взята из сайта

Дополнительная информация о каустике

Ещё один урок о каустике