Модели рубят, полигоны летят: как устроено рассечение 3D-объектов в играх
Разбор механики рассечения врагов, звездолётов, скал и арбузов в современных играх.
Иллюстрация: Катя Павловская для Skillbox Media
Механика разрезания трёхмерных моделей в играх — это всегда иллюзия, подобная той, что фокусники создают в трюке «распиливание женщины». Никто там человека не распиливает — просто есть ещё скрытая от глаз зрителя вторая актриса, ноги которой мы и видим.
Вариаций «распиливания женщины» очень много, как и способов сделать вид, будто игрок действительно разделил трёхмерный объект на две, на три, а то и на десять частей.
Благо разработчики игр, в отличие от фокусников, гораздо охотнее раскрывают свои секреты. Давайте же ознакомимся с некоторыми из них.
Неразрубаемый Гордиев узел
Трёхмерные объекты в играх состоят из меша — сетки полигонов. Каждый полигон — это четырёхугольник, который, в свою очередь, состоит из двух треугольников. Каждый треугольник — совокупность трёх вершин. По сути, это просто точки, которые хранят в себе по три числа — координаты вершины в пространстве по осям x, y, z.
Представьте себе шар, сделанный из проволочного каркаса, на который натянули ткань. Трёхмерная модель — это примерно вот такая вот конструкция. Если ударом острого меча рассечь ткань и проволоку, то окажется, что внутри конструкции пустота.
С трёхмерной моделью в игре произойдёт то же самое — на месте рассечения вы не обнаружите внутренних частей объекта или хотя бы просто гладкой поверхности среза. Это первая проблема, с которой сталкиваешься, когда собираешься разрезать трёхмерный объект в игре: как показать его внутреннее устройство?
Другая проблема: в реальном мире такая конструкция из проволоки и ткани при рассечении распадётся на две половинки, ведь каждая отныне живёт своей жизнью, имеет свой вес, новую форму, подчиняется физике по-своему.
Но в мире игры, даже если визуально разделить меш — например, удалив часть полигонов, — половинки всё равно останутся частью одной модели. Они будут, как и раньше, двигаться вместе, крутиться вместе, реагировать на физику вместе. Просто где-то посередине будет разрыв. Поэтому для механики рассечения всегда нужен ещё один объект, имитирующий отсечённую половину. Проблема формулируется так: где взять тот самый другой объект?
Фокусы с расчленёнкой
Одной из первых игр, в которой можно было разделить на куски трёхмерный объект, считается шутер Soldier of Fortune, вышедший 23 года назад. Это был прямолинейный боевик о секретном агентстве, лихие сотрудники которого гоняются за плохими парнями по всему миру. В 2000-м игра поражала воображение жестокостью. Выстрел из дробовика по врагу в упор вскрывал ему нутро — из него вываливались внутренности. Меткое попадание по руке или ноге отсекало конечность.
Игру разработала Raven Software. Как позже признавались авторы, расчленёнка им нужна была не чтобы шокировать общественность, а ради реализма. Для этого они создали технологию Ghoul. Суть в том, что каждая модель человека в игре была сложена, словно пазл, из отдельных фрагментов. Когда игрок стрелял в руку или ногу, то он просто «отделял» один из кусочков пазла.
«Наш программист Гил Грибб (Gil Gribb) придумал систему Ghoul. Он брал модель и разбивал её на отдельные части, чего, насколько мне известно, никогда раньше не делалось в шутерах.
Если персонажу отстреливали ногу, то у модели отключалось отображение ноги, а затем на место появившейся дыры в модели надевался „колпачок“, чтобы прикрыть её. Добавлялась торчащая кость. Чтобы рядом появилась отстреленная нога, мы создавали копию модели персонажа, у которой было отключено отображение всего, кроме ноги».
Дэн Крамер,
программист, один из разработчиков Soldier of Fortune
Позже ту же технологию, но немного доработанную, использовали в сиквеле Soldier of Fortune 2: Double Helix, а также в Star Wars Jedi Knight 2: Jedi Outcast.
Ещё один интересный подход к расчленению можно увидеть в Left4Dead 2, в которой зомби по ходу боя теряли руки и ноги. В первой части все случаи такой ампутации были заранее прописаны. Их было всего пять — потерял руку, ногу, голову… Эти ранения для зомби всегда были фатальными. Живой мертвец без руки умирал окончательно.
Во второй части разработчики хотели чуть большего разнообразия — например, сделать так, чтобы степень увечья зомби зависела от того, насколько мощным оружием воспользовался игрок. Плюс мертвяк с дырой в брюхе должен был продолжать преследовать игрока. Ситуация осложнялась тем, что в игре было 24 тысячи вариаций внешности мертвецов. И это без увечий. А сколько их будет, если для каждой создавать ещё дополнительные варианты?
В итоге разработчики придумали относительно простое решение. На той части тела, которую игрок отстрелил, появлялась невидимая геометрическая фигура, — например, сфера. Она скрывала ту часть модели, которая оказалась внутри неё.
Образовавшуюся дыру в модели закрывала специальная заплатка, которая выглядела как окровавленные внутренности и кости. Эта технология позволила разработчикам создать 54 уникальных увечья на теле зомби, не переделывая уже готовые модели.
Одна из самых известных игр про рассечение объектов, Fruit Ninja, вышла в 2010 году на мобильных устройствах. Геймплей был предельно простым, но увлекательным. Снизу экрана вылетали разные фрукты и бомбы. Игрок, водя пальцем по экрану, должен был рассекать фрукты на две половинки, не задевая при этом бомбы.
Механика настолько простая, что первый прототип разработчики из Halfbrick Studios сделали всего за один день. Дальнейшая разработка была посвящена полировке геймплея и графики.
Игра очень убедительно создаёт иллюзию рассечения трёхмерных моделей. Когда игрок проводит пальцем по арбузу или банану, тот распадается на две половинки именно в том месте, где была обозначена линия рассечения. На самом деле это лишь трюк. С самого начала каждый объект состоит из двух трёхмерных моделей. Разработчики сделали две половинки объекта и аккуратно соединили их вместе, чтобы даже стыка заметно не было.
«Чтобы разрезание фрукта ощущалось лучше, мы сделали так, что его модель поворачивается „швом“ к направлению пальца игрока. Вращение происходит мгновенно, когда игрок задевает фрукт. Благодаря этому объект распадается на две половинки именно так, как игрок его разрезал».
Люк Маскат,
геймдизайнер, автор Fruit Ninja
Присмотревшись получше, вполне можно заметить, что объект резко поворачивается нужной стороной. Разработчики постарались скрыть это брызгами сока, которые сопровождают каждое рассечение, и в целом трюк удался.
Но есть и обратная сторона такого решения: бананы всегда разделяются только поперёк, а не вдоль, и фрукты, как бы вы ни водили пальцем, всегда делятся на половинки одинакового размера. Вы не можете, например, отрезать у арбуза лишь попку.
Добавим, что во Fruit Ninja обе половинки фрукта — отдельные физические объекты. При падении они могут вести себя по-разному. Другая хитрость: невидимые границы каждого фрукта, так называемый collision box, значительно больше, чем сама модель. Объект будет разрезан, даже если вы просто проведёте пальцем рядом с ним, а не по нему. И напротив, у бомб, которые иногда вылетают снизу и которые разрезать нельзя, границы значительно меньше, чем сама бомба. Это сделано для того, чтобы облегчить игроку жизнь в случаях, когда фрукты и бомбы на экране оказываются в одной куче.
Любопытно, что в версии для Kinect разработчикам пришлось немного модифицировать систему разрезания. Проблема в том, что провести прямую линию пальцем по экрану проще, чем рукой по воздуху, стоя перед телевизором. При игре с Kinect точность меньше. Поэтому разработчикам пришлось создать систему, которая угадывала, как именно игрок хочет провести линию разреза, и дорисовывала её с двух сторон. Причём на эти дополнения реагировали только фрукты. Бомбы — нет.
Но если во Fruit Ninja модели можно было разделить лишь на две одинаковые половины, то в другой популярной мобильной игре — Stack — трёхмерный объект рассекается в произвольном месте на два неравных куска.
Stack — пространственная головоломка, в которой нужно строить башню из пластин. Задача игрока — укладывать эти пластины друг на друга. Если не успеть положить новый блок на старый и он выйдет за края башни, то от него отвалится кусок.
Отсечение выглядит настолько органично, что кажется, будто и правда кто-то отрезает от блока кусок. Но это опять же лишь иллюзия.
В момент, когда игрок тапает по экрану смартфона, игра вычисляет расстояние, на которое новый блок вышел за границы своего предшественника. Например, блок выдвинулся на два сантиметра. Вот на эти два сантиметра игра и укорачивает его. По сути, она просто сужает модель на это число, меняя её параметр scale по оси x, y, или z в зависимости от того, с какой стороны надо сузить блок.
Следующий шаг — игра создаёт новый блок шириной как раз в те самые два сантиметра и ставит его впритык к старому. Все эти перестановки происходят мгновенно, и игрок просто не замечает, что та часть блока, которая вышла за границу башни, теперь отдельный блок. Тут важно не забыть добавить физику — в частности, гравитацию, — чтобы он отвалился и улетел вниз.
Что внутри чёрного ящика
Игр, в которых система разрезания позволяет разделить объект на ломтики любой толщины, а потом и сами ломтики нарезать кубиками, можно пересчитать по пальцам одной руки. Самая известная из них, пожалуй, Metal Gear Rising: Revengeance 2013 года. Но к ней мы вернёмся чуть позже.
К реализации этой механики разработчики подходят по-разному, но в основе практически всегда один принцип. Мы на самом деле не разрезаем объект, а создаём две новые модели, которые выглядят как две половинки изначального объекта, разделённого в произвольном месте.
Есть отличный пример. Эту механику на движке Unity реализовала старший инженер-программист из Копенгагена Кристин Лагу (Kristin Lague), ведущая канал о разработке игр на YouTube. Код со своей реализацией она выложила в открытом доступе на GitHub. Ниже мы воспользовались её алгоритмом, чтобы показать рассечение наглядно.
Допустим, у нас есть сцена с геометрической фигурой — например, кубом. Сначала игрок зажимает кнопку мыши в любом месте экрана, а затем проводит линию в любую точку. В момент, когда игрок отпустит кнопку мыши, программа создаст невидимый и очень большой плоский прямоугольник, который будет идти сквозь геометрическую фигуру прямо по контуру нарисованной линии, как бы рассекая трёхмерный объект. На самом деле рассечения на этом этапе ещё нет. Плоскость определяет, прошла ли она через трёхмерный объект. Если да, далее выполняется метод уже для рассечения.
Здесь нужно вернуться к тому, что такое меш, из которого состоят трёхмерные объекты.
При выполнении метода рассечения программа запоминает, по какую сторону от плоскости оказались все треугольники, из которых состоит модель. Допустим, какие треугольники находятся слева от плоскости, а какие справа. Эти направления условны. Точно так же можно говорить, что какие-то оказались сверху от неё, а какие-то снизу.
Если каждая из трёх вершин треугольника находится слева от плоскости, значит, весь треугольник слева. Если все вершины справа, то и весь треугольник справа. Так программа сортирует треугольники на две кучки.
Если же линия среза проходит прямо сквозь треугольник, то есть одна вершина у него слева, а две другие справа, тогда программа делит у себя в уме этот треугольник на три новых (см. рисунок выше) и уже потом распределяет эти новые треугольники на те, что слева, и те, что справа.
Тут важно понимать, что рассечения на этом этапе ещё не произошло. Треугольники программа поделила только в уме: запомнила, какие и где находятся. Далее она берёт координаты вершин треугольников, оказавшихся справа, и на их основе создаёт новый меш, новый трёхмерный объект. А затем точно так же она поступает с координатами вершин треугольников, оказавшихся слева. Старый меш целой фигуры удаляется, вместо него у нас теперь есть два новых меша в виде его половинок. Вот теперь рассечение случилось. Но дело ещё не завершено.
В месте разреза обоих мешей теперь пустота. Они будто полые. Поэтому программа для каждого нового меша на месте среза создаёт полигоны, используя координаты вершин, формирующих срез.
Дальше дело техники — добавить каждому объекту компонент для расчёта физики, чтобы половинки красиво распадались, а также компонент, который обозначает границы новых моделей. Без этого меш — бесплотный дух, который, словно привидение, проходит сквозь предметы и людей.
Подобную механику можно встретить в инди-игре 2012 года Tiny & Big in Grandpa’s Leftovers. Это был пазл-платформер с упором на физику. Исследуя гористую местность, с помощью специального устройства игрок мог подтягивать к себе валуны или отталкивать их, освобождая дорогу, и, главное, разрезать скалы лазером, указывая мышкой, как пройдёт линия рассечения.
Игра выросла из прототипа Tiny & Big: Up That Mountain, который в 2009 году небольшая команда разработчиков, основателей Black Pants Studio, готовила к фестивалю независимых игр — Independent Games Festival. Разработка велась на собственном движке команды — Scape. В те далёкие времена такого раздолья бесплатных и хороших движков, как сейчас, ещё не было — приходилось что-то придумывать самостоятельно.
Механика нарезания скал лазером настолько понравилась игрокам, что разработчики решили расширить проект до полноценной игры. Правда, были у этой механики и проблемы. Особенность механики лазера в том, что игрок мог отрезать от любой скалы произвольный кусочек. Можно было повторить процедуру сколько угодно раз и превратить каменный блок в горку щебёнки, в которой просчитывается физика каждого камешка. Компьютер такой нагрузке, понятно, был не рад.
«Производительность была для нас большой проблемой. Дайте игроку инструмент, который разрезает мир на куски, и кто-нибудь обязательно начнёт делать это, не заботясь о том, как это повлияет на частоту кадров. Один парень прислал скриншот, на котором Тайни [главный герой] гордо стоит между сотнями кусочков, которые он вырезал из одной колонны. Он был в восторге от того, что это возможно, но в процессе игра стала неиграбельной. Поэтому мы оптимизировали её множество раз, чтобы предотвратить падение частоты кадров, и усовершенствовали физический движок [для полной версии игры]. <…>
С огромной мощью (в виде крутого лазера) приходит и большая ответственность (для игрока в песочнице). Используйте лазер, и вы сможете изменить весь мир, но будьте осторожны, чтобы не разрушить свой путь к концу уровня или даже не вывести игру из строя. В этом заключается идея лазера в Tiny & Big!»
Себастьян Шульц,
один из разработчиков Tiny & Big in Grandpa’s Leftovers
Чтобы не перегружать процессор, разработчики позаботились о том, чтобы самые мелкие фрагменты всё-таки исчезали.
О том, как именно устроена механика рассечения, разработчики Tiny & Big in Grandpa’s Leftovers восемь лет назад рассказали на Reddit в канале r/gamedev. В общих чертах: они построили алгоритм разрезания по принципу конструктивной твердотельной геометрии (constructive solid geometry, или просто CSG).
Звучит страшно, но это просто одна из технологий моделирования объектов в трёхмерной графике. Принцип в том, что сложная геометрическая фигура, которую компьютеру, по идее, трудно обсчитывать, — это на самом деле лишь набор из нескольких примитивных геометрических фигур (куб, сфера, цилиндр). Просто над ними выполнена одна из трёх логических операций — слияние, вычитание или пересечение.
Возьмите куб, погрузите в него сферу, чтобы она лишь по чуть-чуть выглядывала с каждой стороны. Затем вычтите из куба сферу, и вы получите сложную геометрическую фигуру в виде куба, внутри которого находится полость в виде сферы.
Возьмите сферу и погрузите её наполовину в другую сферу, чуть побольше. Примените вычитание, и вот у вас получилось что-то вроде чаши.
Возьмите цилиндр, погрузите его наполовину в куб под углом. Вычтите из цилиндра куб. И вот вы будто отрезали от цилиндра кусок наискосок (правда, вторая половинка при этом исчезнет).
Для своей игры разработчики Tiny & Big in Grandpa’s Leftovers этот принцип немного доработали.
«По сути, вы распределяете вершины меша по двум половинам, затем в месте среза (который запросто может проходить по пространству между вершинами. — Авт.) генерируете вершины рёбер с помощью интерполяции, так что у вас теперь есть два меша, которые по-прежнему выглядят как один. Не хватает только поверхности среза. Вы генерируете её, соединяя случайную рёберную вершину места среза со всеми остальными рёберными вершинами!»
Разработчики Tiny & Big in Grandpa’s Leftovers
Metal Gear Rising: Revengeance, которую мы упоминали выше, разрабатывала студия Platinum Games. Это был спин-офф к серии Metal Gear Solid о приключениях Райдена — главного героя второй части. Он, получив тело киберниндзя, всю игру кромсал киборгов мечом.
На то, чтобы реализовать механику разрезания, у разработчиков ушло три месяца. Они назвали её Blade Mode. Объекты можно рассекать и в режиме реального времени, и в режиме замедления. Во втором случае появляется голографическая линия среза, которую можно вращать, выбирая, какую часть противника или предмета хочешь отсечь.
Как рассказал программист Цуёши Одера (Tsuyoshi Odera) механика разрезания потребляла больше памяти, чем любой другой процесс. Поэтому разработчики распределили её выполнение по нескольким кадрам.
Для понимания: каждая игра — это тот же мультфильм, который состоит из кадров, сменяющих друг друга. Но в игре программа каждый кадр проверяет, не изменилось ли что-то — не нажал ли игрок кнопку, например. Если нажал, то следующие кадры создаются уже с учётом изменения условий. Соответственно, вычисления проводятся каждый кадр, нагружая процессор. А если сложные вычисления распределить по нескольким кадрам, то нагрузка будет меньше и FPS возрастёт.
Разработчики Metal Gear Rising должны были соблюдать одно ограничение — вычисления можно было проводить лишь в кадрах, которые отводились на взмах меча.
«Мы рассчитали скорость, с которой Райден размахивает своим мечом, и убедились, что процесс (вычисления разрезания объекта) будет завершён до конца замаха и игрок почувствует, что всё правильно. Это, наряду с несколькими другими приёмами, помогло нам создать своего рода свободу действий, которую игроки до сих пор нечасто могли ощутить в других экшен-играх».
Цуеши Одера,
программист, разработавший систему рассечения объектов в Metal Gear Rising: Revengeance
Отрезанные куски через время исчезают — это сделали, чтобы экономить ресурсы. Вам не удастся насыпать в локации горы из кубиков, в которых вы превратили своих врагов.
Интересно и то, как разработчики подошли к изображению поверхности среза. Разделяя камень в Tiny & Big in Grandpa’s Leftovers, ты не ждёшь, что внутри него будет что-то кроме камня. Поэтому на поверхность среза достаточно натянуть ту же текстуру, что и на все остальные поверхности камня.
Но как быть с киборгом, которому ты отсёк руку или ногу? Какую текстуру наносить на место среза, чтобы правдоподобно показать внутреннее строение частей его тела?
Допустим, мы сделаем для руки текстуру руки в разрезе, а для ноги, соответственно, текстуру ноги. Но что, если игрок начнёт разрезать конечность не поперёк, а вдоль? Ведь в режиме Blade Mode, когда время замедляется, игрок может повернуть линию рассечения как ему вздумается.
Разработчики решили эту проблему, привязав текстуру для среза к углу нанесения рассекающего удара. Масаки Ёритоми (Masaki Yoritomi), специализировавшийся на моделировании персонажей, объяснил принцип на модифицированной модельке арбуза.
«Когда мы начали работать с мехами и киборгами, нам пришлось сделать отдельную текстуру поверхности среза для каждой части тела. Если мы рассекаем голову, нам надо что-то, что выглядит как голова. То же самое касается рук, кистей, ног… Нам также надо было подготовить различные текстуры поверхности среза под каждый угол нанесения удара по каждой части тела. Внутреннее строение должно выглядеть по-разному в зависимости от того, был разрез вертикальным, горизонтальным, диагональным или ещё каким-то.
Нам пришлось продумывать не только то, как персонаж или робот выглядят снаружи, но и то, как он устроен внутри. Мы до ночи сидели и обсуждали, как тот или иной парень должен выглядеть изнутри при разрезе с определённого угла, где у него должна быть кость и так далее. При нормальной игре многие их этих поверхностей сложно разглядеть. Но мы довольно специфично подошли к деталям».
Масаки Ёритоми,
моделлер Metal Gear Rising: Revengeance
Так же тщательно разработчики создавали реакции противника на то, какую часть тела вы ему отсекли. Разработчики буквально сделали для каждой ситуации уникальную реакцию.
Другой хороший пример — Hardspace: Shipbreaker 2022 года. Там весь геймплей строится на демонтаже космических кораблей в условиях невесомости. Летая в скафандре вокруг списанного корабля, игрок должен корректно отсекать от него детали лазером и сортировать их для переработки. Металлические листы обшивки — в печь, оборудование — на повторное использование.
Это своеобразный пазл, ведь просто так отрезать от корабля кусок нельзя. Попытаешься — лазер обязательно заденет взрывоопасные системы, и космонавт погибнет. Чтобы реализовать такой геймплей, разработчикам пришлось поломать голову над вопросом, а что вообще такое корабли в игре.
«Изначально корабли представляли собой 40-метровые меши, текстурированные так, чтобы казалось, будто они сделаны из разных панелей и блоков. Но учитывая, как работает наше разрезание, все 40 метров корабля разрезались за один раз. Игроки жаловались: „Почему это произошло? Это же глупо!“ Поэтому каждый корабль пришлось делать из отдельных компонентов, соединённых вместе. Большинство из них состоят из четырёхметровых панелей, будто из гигантских кубиков Lego. Некоторые детали восьмиметровые. Всё, что больше, ощущалось при разрезании странно».
Эллиот Хадсон,
креативный директор Hardspace: Shipbreaker
Разрезание происходит с помощью лазера, который выстреливает в поверхность двумя расходящимися в стороны лучами. К такому визуальному решению разработчики пришли, когда поняли, что один луч будет слишком долго идти по поверхности и игрок заскучает, пока будет ждать завершения анимации.
Помимо лазера, в инструментарии был прибор, стреляющий лучом. Его надо было использовать для уничтожения узлов, удерживающих вместе крупные детали. Он их просто испепелял целиком, не деля на части. Разработчики ввели его, чтобы механика демонтажа не ограничивалась разрезанием. Ведь порой по другой стороне стены, которую резал игрок, проходили взрывоопасные трубы, которые трогать было нельзя.
Технически разрезать можно абсолютно любую деталь корабля. Но, чтобы игровой процесс не превратился в скучную нарезку звездолётов, разработчики ввели несколько ограничений. Каждый корабль состоит из двух слоёв. Это капсула внутри капсулы. Внешняя капсула — оболочка корабля. Внутренняя — его помещения. Между ними есть пространство. Внешняя оболочка соединена с внутренней несколькими балками, благодаря чему внутренняя будто подвешена внутри.
На первых порах у вас слабый резак, которому внешняя оболочка не по зубам. Зато внутреннюю вы как раз можете кромсать сколько душе угодно. А после того как вы уничтожите все узлы, благодаря которым внешняя оболочка крепится к внутренней, внешняя сама развалится на несколько частей, которые вы с лёгкостью сможете рассортировать по туннелям переработки. В этом особое удовольствие — делаешь рутинную работу внутри корабля, а потом замечаешь, что звездолёт постепенно разваливается на куски
Защиту от ненужной нагрузки компьютера разработчики тоже предусмотрели. Если вы отрежете от корабля слишком уж маленький кусочек, тот просто дезинтегрируется.
К созданию поверхностей среза разработчики Hardspace: Shipbreaker подошли так же творчески, как и создатели Metal Gear Rising: Revengeance. Чтобы листы, отрезанные от корабля, казались объёмными изнутри, они разместили на срезе текстуру с добавлением parallax mapping. Это технология, которая создаёт иллюзию объёма. Рисунок на текстуре будет преображаться в зависимости от того, под каким углом вы на неё посмотрите.
Благодаря этому абсолютно плоская стена в старинном замке будет выглядеть так, будто она сложена из объёмных выпирающих камней. А в окнах жилой высотки будут объёмные комнаты, хотя на самом деле это плоская картинка. Подобное можно увидеть, например, в Marvel’s Spider-Man и Cyberpunk 2077.
Правда, если приглядываться к поверхности среза в Hardspace: Shipbreaker, заметен минус этого подхода. Кажется, будто изнутри деталь гораздо больше, чем снаружи.
* * *
Механика разрезания трёхмерных объектов по-прежнему кажется чем-то экзотичным. Даже сейчас она может стать главной фишкой любой игры — несмотря на то, что ей больше десяти лет. И это неудивительно. Она очень требовательна к ресурсам компьютера, и разработчикам нужно приложить немало усилий, чтобы она выглядела органично.
Но результат того стоит: это добавляет в цифровой мир капельку реализма, создавая иллюзию, будто вокруг героя не декорации, а реальные предметы, внутри которых есть что-то кроме пустоты.