July 23, 2019

Хитрости игровой разработки #6

В этой части мы поговорим о создании взрывов в играх.

Заметки пишутся от лица Simon Trümpler.

Другие части:

Первая часть

Вторая часть

Третья часть

Четвертая часть

Пятая часть

Приятного чтения!

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬

И так, сегодня у нас интересная задача - понять, как в Bethesda сделали этот классный эффект взрыва.

Если вы не в курсе сложности создания эффектов такого рода - продолжайте читать. А если вам просто интересно прочесть решение этой задачи - пролистайте до раздела “Решение”

Реальная жизнь


Почему так сложно сделать грибовидный взрыв в игре? Давайте взглянем на пример из реального мира:

Верхняя часть взрывного облака содержит в себе сложные движения частиц, которые крутятся вокруг цента, закручиваясь внутрь и образуя форму пончика:

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

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

Частицы


В старых играх разработчики чаще всего не показывали сам момент формирования взрывного облака, а вставляли в этот момент эффект ослепления ярким светом, а по мере того, как эффект ослабевал, перед игроком появлялся уже вставленный деревоподобный шейп,который сам по себе чаще всего никак не двигался. Вот пример из Mercenaries 2: World in Flames:

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

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

Это (R.U.S.E.) пример того, как разработчики используя эту технику достигли довольно таки хорошего результата:

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

UV Анимация

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

Конкретно в этом случае Bethesda использовала технику UV анимацию, что по своей сути означает движение текстуры по какой-либо оси вдоль геометрии. 

▬▬▬
(прим. от переводчика: я использовал похожую технику для создания фейкового движения листвы под воздействием ветра в одном своем маленьком проекте. Посмотреть его можно тут - https://www.artstation.com/artwork/8lOzDE)

Фейковое движение листвы из моего проекта

▬▬▬

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

Ниже я оставлю пример того, как анимированная текстура из Fallout выглядит на тестовой геометрии(я дополнительно использовал смешивание и vertex color, чтобы убрать жесткие грани на краях геометрии:

В Fallout 4 используется схожая техника текстурной анимации(без участия геометрии, как в Fallout 3). Выглядит так, будто бы облако крутится всегда по отношению к центру взрыва:

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

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

Я не мог понять, как можно сделать такой взрыв без использования программ симуляции, но потом мне на глаза попался похожий элемент из battlefield 4: 

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

Анимация текстур


Мое единственное предположение заключалось в том, что это, возможно, приготовленный заранее эффект, например из FumeFx. Вот пример того, что можно симулировать в такого рода софте(не в real time конечно же) 

По факту, некоторые студии, типа Epic games, просто запекают результаты симуляции кадр за кадром в текстуру. Если хотите узнать немного больше про этот подход, это видео для вас.

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

Решение


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

Это атлас текстур и он ведет себя превосходно при проигрывании..а ещё он зацикленный!

Хм...Но тут ведь нет огня!?

Я подумал что что-то пропустил, но позже вспомнил про gradient mapping. Больше о нем вы можете узнать тут. Но вот быстрый пример его работы для понимания: 

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

Выглядит классно, но возникает две проблемы:

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

2) Мы не видим силуэт облака и если попробуем применить прозрачность исходя из альфа канала текстуры, то получится вот что:

Меня сбило с толку то, что согласно информации из альфа канала, большая часть текстуры имеет прозрачность около 50%, что не соответствует увиденному в игре, где взрыв в большей степени непрозрачный.

И опять таки решение проблемы заключалось в gradient mapping'e..

Разработчики использовали альфа канал, чтобы вырезать форму облака, но переопределяли его значения через gradient mapping, с помощью чего и достигали внутри игры нужного уровня прозрачности:

Fallout записывал эти градиенты в текстуру. Какой сюрприз. Давайте взглянем на неё:

Что это такое? При стандартном подходе, для использования gradient mapping'a хватит текстуры с высотой в 1px. В таком случае, зачем разработчики использовали квадратную текстуру? Причина кроется в том, что они использовали разные линии пикселей(снизу-вверх) в зависимости от индекса времени жизни частицы.

Гениально! Это дает возможность создавать огненный эффект в самом начале, а потом, в зависимости от того, как долго живет частица, превращать его в черный дым.

Они также немного меняют форму облака взрыва с помощью изменений в альфа канале.

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

Думаю, можно сказать: 

Задача решена!

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

В этом примере я присвоил разные цвета нижней и верхней частям текстуры градиента и, как и ожидалось, в определенный момент после рождения частицы, её цвет изменился: 

Тут я сделал то же самое, но с разными цветами слева и справа. Один цвет находится в значениях от 0 до 127, а второй от 128 до 255:

А вот тут вышло немного странно. Я изменил альфа канал текстуры градиента(закрасил всё черным, кроме одной линии в пиксель внизу). Я надеялся, что это заставит частицы быстрее пропадать... В общем-то, вы можете сами взглянуть на результат: 

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


В своем последнем примере я заставил альфа канал прятать всё больше и больше видимой информации из текстуры в зависимости от времени жизнь партиклов:

В конце оригинала остался доп материал. Советую заглянуть!

*Ляна, спасибо за тему для перевода*

Также, если у вас есть какая-то классная статья, перевод которой вы бы хотели видеть - смело присылайте её мне в личку телеграмма @DenisNik.

Спасибо за внимание!

▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬

P.S

Если хотите видеть переводы раньше всех - подписывайтесь на телеграм канал - https://t.me/CGTranslate

Все советы, предложения и критику пишите в мою личку телеграма @DenisNik или на почту [email protected]

Перевод был подготовлен в рамках проекта CgTranslate.