{"id":3824,"url":"\/distributions\/3824\/click?bit=1&hash=a0d33ab5520cacbcd921c07a49fc8ac5b78623b57936b992ce15c804b99210d4","title":"\u041a\u0430\u043a\u0443\u044e \u0440\u0435\u043a\u043b\u0430\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0442\u044c \u043d\u0430 DTF \u0438 \u043a\u0442\u043e \u0435\u0451 \u0443\u0432\u0438\u0434\u0438\u0442","buttonText":"\u0423\u0437\u043d\u0430\u0442\u044c","imageUuid":"75ec9ef4-cad0-549d-bbed-1482dc44e8ee","isPaidAndBannersEnabled":false}
Gamedev
Yegor Zhumikov

Как мы делали красивую двумерную воду в Unity Статьи редакции

Cоздание почти трёхмерного окружения без трёхмерной графики.

Мы — это я, Егор, и Юра, наш художник, которому я упорно создаю след в сети, но он не торопится этим пользоваться. И, собственно, мы очень неспешно работаем над нашей игрой и иногда выкладываем всякие заметки о том, что там и как. В этот раз речь пойдёт о том, как мы захотели добавить водички в игру, но не смогли остановиться на слишком простом решении.

Сразу оговорюсь, что работаем мы в Unity и используем Universal Render Pipeline для отрисовки, но общие идеи можно перенести, конечно, и в другие пайплайны отрисовки и даже движки.

Макет

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

Макет

Сразу выделим, какие детали нужно будет реализовать:

  1. собственно, вода;
  2. пенка у колон и камней;
  3. туман.

План

Так как вся игра в 2D, доступа к высотам в точках у меня нет, и просто перенести 3D подход возможности не было. Поэтому я придумал другую хитрость — сделать отдельную камеру, копирующую основную, подменять в ней спрайты с помощью URP Renderer и дополнительных текстур и рисовать собственную карту высот, используя её. А по ней уже строить очертания моря и тумана.

Тут оговорюсь для людей, незнакомых с Unity, что URP (Universal Render Pipeline) — это один из вариантов пайплайнов отрисовки, который позволяет гибко настраивать, собственно, отрисовку. И идея тут в том, чтобы создать специальный способ отрисовки в специальной камере для некоторых игровых объектов.

Карта высот

Для начала нужно придумать, как её вообще рисовать. В обычном 3D она рисуется автоматически по мере записи в Depth Buffer (иногда и иначе, не будем задерживаться на этом), остаётся только взять её и использовать. Но так как у нас 2D-спрайты, то нам это, конечно же, не подходит.

Самый простой способ, как мне показалось, — это нарисовать специальную текстуру, копирующую текстуру колоны, где в каждом пикселе в B-канале (можно любой другой, это не так важно) будет записано, насколько этот пиксель текстуры ниже, чем точка «нуля».

В редакторе спрайтов Unity потом достаточно просто добавить вторичную текстуру и дать ей название.

Теперь нужно написать шейдер, который будет, собственно, заменять основную текстуру на дополнительную. Помимо этого, он должен немного перекодировать данные, потому что в текстуру влезет всего 256 значений (если она не sRGB, то больше, но это детали), а высота может быть раньше. В шейдер добавляем проперти _Meta и используем те же UV-координаты + вешаем математику сверху.

После я создал URP Renderer и добавил в него фичу для подмены материалов.

Теперь остаётся только создать камеру, поменять ей Renderer и настроить слои, получаем две картинки, одна из которых выводится на экран.

Вуаля, карта высот готова.

Вода

Изначально я хотел сделать поверх всего экрана спрайт, который был бы прозрачным там, где он «ниже», чем объект. И я даже это сделал, но создалось несколько проблем:

  • нужно было бы заносить в карты высот вообще всё, а значит рисовать высоты вообще для всего;
  • спрайт постоянно мешался, потому что отрисовывался вообще всегда даже на сцене.

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

Собираем это всё и смотрим на море.

До макета еще далековато

Оживляем море

Для отрисовки пены изначально я взял карту высот, прошёлся по ней блюром и пастеризовал в цветах воды. Сразу заметил, что пенка появляется и сверху картинки рядом с колонами, а не под ними, потому что не понимает, что колоны над ней.

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

На практике это выглядело вот так.

Уже получше. Далее я быстренько накинул шум, чтобы было что-то двигающееся. Выглядело оно так себе.

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

Но пена нам всё-таки не понравилась, решили переделать.

Пена 2.0

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

Теперь добавляем новую пену и делаем так, чтобы волны бились по угасающей синусоиде.

Туман

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

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

Переписав всё это добро, мы поигрались с самыми разными параметрами и добавили коня-колосса.

Для коня, кстати, руками рисовалась карта высот и вообще весь процесс довольно весело выглядел.

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

0
37 комментариев
Написать комментарий...
Евгений Серегин

Водичка чисто партиклами поверх голубой плоскости.

Ответить
Развернуть ветку
Садовый ящик

Интересно выглядит) А можно скрин редактора с Gizmos иконками или описание в двух словах как оно работает? Здесь несколько систем частиц, стандартный ли эмитер или вы кастомили создание частиц.

Ответить
Развернуть ветку
Евгений Серегин

Сейчас уже не найду тот проект.
Суть такова: В инете была найдена гифка с каустикой воды. Из нее была сделана несложная 16 кадровая текстура с фейдом по краям каждого кадра. Потом на плоскости воды в рандомных местах появляются 1-3 билборда на 0,7-1,5 сек с этой текстурой. Каустика готова :)
Пена ко краям объектов еще проще - это расставленные вручную такие же партикл системы, где спавнятся так же несколько билбордов, но уже с однокадровой текстурой. К двигающимся объектам, типа лодок, ящиков эти системы просто прилинкованы, чтобы двигаться вместе с ними. Ничего сложного.
Дело лишь за красиво нарисованным градиентом глубины воды на основном плейне, имитирующем воду.

Ответить
Развернуть ветку
Садовый ящик

Круто, спасибо) Плюс-минус так и представлял себе)

Ответить
Развернуть ветку
Антон Батон

Выглядит очень хорошо!

Ответить
Развернуть ветку
Евгений Серегин

И без всяких шейдеров :)

Ответить
Развернуть ветку
Yegor Zhumikov
Автор

Будто партиклы рисуются сами по себе :)

Ответить
Развернуть ветку
Yes, Your Grace

Эээ... 🤔🤔🤔

Ответить
Развернуть ветку
Антон Батон

Любой вывод графики в современном ПО осуществляется шейдерами. Даже современные браузеры рендерят картинку на GPU.
Шейдер это программа. Если это пиксельный шейдер, то это программа которая принимая на входе некоторые данные (например координаты), выдаёт значение цвета одного пикселя. Если эту программу запустить для каждого пикселя на экране, то мы увидим изображение сформированное шейдером. Есть и другие шейдера, например работающие не в пространстве экрана или не с пикселями, но в любом случае каждая игра выводит АБСОЛЮТНО всю графику при помощи шейдеров.

P.S. Тьфу. Ответ не вам адресовался. Ну да и фиг с ним. =)

Ответить
Развернуть ветку
Yes, Your Grace

@Евгений Серегин тут тебе ответ пришёл 
@Антон Батон я помогу)

Ответить
Развернуть ветку
Евгений Серегин

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

Ответить
Развернуть ветку
Абу Давид Буль-Нуль Джотар

- Вы в воде купаете?
- Нет, просто показываем, как сделали.
- Красивое.

Ответить
Развернуть ветку
Марик Омаргалиев

На asset store продаете?

Ответить
Развернуть ветку
Аккаунт удален

Комментарий недоступен

Ответить
Развернуть ветку
Yegor Zhumikov
Автор

Я не умею пользоваться реддитом, а Юра говорит, чтобы я разбирался. Ну а дальше мне лениво и как-то вот!

Ответить
Развернуть ветку
vertopolkaLF

Он по сути тот же дтф, только больше

Ответить
Развернуть ветку
Yegor Zhumikov
Автор

Не, ну я на самом деле понимаю, просто пытаюсь спихнуть это на Юру, который там много времени проводит, а он отказывается

Комьюнити менеджмент на высоте, так сказать

Ответить
Развернуть ветку
Андрей Торчинский

Отличный материал!
Я правда не сразу понял, что туман это туман. Думал, что часть камней под водой и еще удивился почему волны бьются о подводные камни :) 

Ответить
Развернуть ветку
Yegor Zhumikov
Автор

Да, это многие замечают. Мы думали, как сделать туман менее водным, но каких-то супер очевидных идей у нас не было, поэтому мы решили забить. Все таки, основная идея "подсветить" активные тайлы и с этой задачей декор справляется. А все эти мис-андерстендинги некритичны и вообще красиво же :)

Ответить
Развернуть ветку
Андрей Торчинский

Так может просто сделать туман водой и сделать так, чтобы волны бились о более высокие камни? Сейчас камни, которые как-будто утоплены под водой дают гораздо лучший эффект глубины (есть мелководье, а есть глубокая вода). А подсвеченая игровая зона при этом останется без изменений.

Ответить
Развернуть ветку
Денис Пряхин

Сделайте его белым

Ответить
Развернуть ветку
Igorious

Ах, так это туман! )
А я усиленно ищу его на картинке и не понимаю, где он.

Ответить
Развернуть ветку
Бурный яд

Водичка и правда хорошечная 

Ответить
Развернуть ветку
I'm Qugurun

А вот что у меня получилось.
Каустика - шейдер, натянутый на спрайт с картинкой. 
Пена и волны у суши, отдельные спрайты с простым шейдером колыхания.

Я выложил данный шейдер и с ним можно поиграться.
https://www.shadertoy.com/view/wt2GRt

Ответить
Развернуть ветку
Kirill Kolpakov
Ответить
Развернуть ветку
Жека все напишет!

Красивое решение, изощренное, я бы даже сказал! Кайф

Ответить
Развернуть ветку
Dany Sterkhov

Круто!

Ответить
Развернуть ветку
Mewton Games

Классно выглядит :)

Ответить
Развернуть ветку
Кукалякин

Красивое...

Ответить
Развернуть ветку
Садовый ящик

Вышло очень сочно)

Ответить
Развернуть ветку
ДЕЛА ИГРОДЕЛА

21 век, а мы по прежнему ломаем голову над созданием воды. Я в том числе. 
Спасибо за статью

Ответить
Развернуть ветку
Ирина Котович

Очень здорово выглядит! Красавчики)

Ответить
Развернуть ветку
Дмитро Журавльов

Чисто ради интереса, если хотите посмотреть на красивую воду, поиграйте в недавний вышедший Капитан Блад. Игра на любителя, но водичка в морских сражениях на загляденье.

Ответить
Развернуть ветку
cltfname

hl2, gta 4, rdr 2, far cry 5

Ответить
Развернуть ветку
Дмитро Журавльов

ну это всё дорогие проекты и ожидать там чего-то некрасивого удивительно, а Блад - явная категория Б и там заморочились с водичкой))

Ответить
Развернуть ветку
Даниил Кожевников

полезная статья, сохраню себе на будущее :)

Ответить
Развернуть ветку
Petr Matafonov

Совсем не то же самое, но тоже про воду.

Мне почему-то оч запомнилось это видео.

Ответить
Развернуть ветку
Читать все 37 комментариев
null