[Перевод] Важно то, что внутри: о процедурной генерации органов
(Дисклеймер переводчика: на всякий случай не советую читать эту статью во время еды.)
Когда я начинаю участвовать в геймджемах, то вхожу в режим «максимального ускорения», который обычно заканчивается ужасными понедельниками на работе после бессонных ночей. Чем старше становлюсь, тем сложнее для меня набраться энтузиазма для участия. К счастью, PROCJAM очень расслабленный, что идеально мне подходит. Кроме того, читерство там совершенно не запрещено, поэтому я мог, например, вернуть из небытия мой генератор органов, над которым я работал несколько месяцев назад для Bestiarium и создать свой прототип на его основе.
Пока я готовлю версию для Vive, можно поиграть в De daemonici corporis fabrica на моей странице на itch.io.
Несмотря на то, что я не прикасался к нему уже довольно долго, в Bestiarium есть впечатляющий набор идей, живших в моей голове. Но сама игра основана на немногих «философских» пунктах. Я всегда видел её как «roguelike из одной комнаты», поэтому пространство для исследований неизбежно перемещалось «снаружи» «внутрь», что идеально описывается этой поэмой Уильяма Блейка:
Небо синее — в цветке,
В горстке праха — бесконечность;
Целый мир держать в руке,
В каждом миге видеть вечность.
Такие проекты, по-моему, получаются гораздо более интересными, если интерпретировать всё буквально. Поэтому я решил двинуться в сторону «внутренностей».
Одна из основных механик игры включает в себя извлечение материалов из существ, которых вы можете вызывать. Можно пойти стандартным путём и вытаскивать из них «кроличьи лапки» и «паучьи глаза», но наша игра ещё и про науку. Как и в науке, в ней часты пробы и ошибки (а большинство времени занято тяжёлым трудом).
Вот каким был один из пунктов в моих записях о дизайне с пометкой «наверно не сработает»: анатомирование существ для извлечения из них органов. PROCJAM, очевидно, был идеальным оправданием для создания прототипа на основе этой идеи и её проверки.
De daemonici corporis fabrica (демоническая версия De humani corporis fabrica) пытается передать ощущения древних учёных, впервые разрезающих труп. Что-то вроде «интересно, зачем нужна эта комковатая сморщенная штука?» Но я отвлёкся. Этот пост посвящён технической стороне игры. Всё началось с того… как, чёрт возьми, можно вообще процедурно генерировать органы?
Всё началось много месяцев назад с ночи просмотра видео о вскрытии животных (большинство исследований по этой теме напомнило мне об этой статье на Gamasutra). Разумеется, я мог продолжить генерировать трупы с заранее созданными моделями органов. Но я только что добавил генератор имён на цепях Маркова в прототип Invocation, и это заставило меня задуматься: может быть, стоит использовать их для генерирования органов, которые больше похожи на «реальные»?
Для цепей Маркова нам нужно несколько начальных образцов:
Да, невероятные шаблоны размером 8×8 пикселей, которые, если прищуриться, немного напоминают органы. Сначала я закодировал черные и белые пиксели как нули и единицы в строке, а затем передал её в цепь Маркова — это, как я почти был уверен, не сработает, но я хотел применить пошаговый подход.
И знаете что? Да, я был прав, создались глитчевые текстуры, потому что изображениям нужна двухмерная целостность. Поэтому следующим шагом стало кодирование изображения в группы целых двухмерных позиция для всех белых пикселей. Так на самом деле получилось сгенерировать несколько интересных результатов, достаточно убедительных вариаций входной информации.
Я решил, что нужно БОЛЬШЕ, поэтому увеличил размер образцов до 16×16 пикселей. Оказалось, что 8×8 — оптимальный размер, поэтому я не сильно искал способы повышения разрешения (и вряд ли в этом был смысл).
Ну ладно, у нас получились органоподобные формы, но у них низкое разрешение и они двухмерны. Как добавить им ещё одно измерение? Первое, что приходит в голову — использование метасфер.
В результате я просто стал преобразовывать изображение в трёхмерную сетку размером 8×8x1 и передавать её в алгоритм шагающих кубиков (marching cubes algorithm). Мы получили 3D, но слишком неуклюжее.
У меня есть привычка жадной работы над прототипами и геймджемами. Поэтому вместо возврата назад и доведения до ума метасфер, я решил добавить поверх сгенерированной сетки алгоритм сглаживания сеток.
Я просто набросил этот фильтр сеток из Unity Wiki. Это немного улучшило формы объектов. Но органы всё равно были совершенно плоскими. Тогда я добавил немного случайных смещений по оси Y для всех вершин, находящихся на плоских поверхностях (т.е. нормали которых направлены ровно вверх или вниз).
И посмотрите-ка на это. Уверен, что у меня просто парейдолия, но я чётко вижу селезёнку, лёгкое, печень… селезёнку… и… ну, всякие органоподобные формы.
Когда настало время текстурирования, я снова решил срезать углы и избежать создания UV-развёртки этих штук. Я провёл несколько экспериментов с функциями 3D-шума (вы можете взять шейдеры шума, портированные мной из этого репозитория в удобном и едва протестированном CGINC for Unity). Они выглядели довольно хорошо (и я, возможно, где-нибудь их использую), но дешёвое решение стало очень затратным, когда потребовалось создание для текстур карт нормалей.
В результате достаточно хорошей оказалась простая плоскостная UV-карта (созданная расположением координат вершин XZ, нормализованных в пространстве UV). Я смог воспользоваться нарисованными текстурами (которые не только вызвали у меня отвращение при поиске фотоисточников, но и были ретвитнуты Polycount).
«What are you up to this saturday night?»
— Yanko Oliveira (@yankooliveira) November 5, 2016
«Oh, you know, the usual, doing seamless viscera textures and stuff»#screenshotsaturday #gamedev pic.twitter.com/4ZktlppojH
— Какие у тебя планы на вечер субботы?
— Ну, знаешь, как обычно, буду рисовать бесшовные текстуры кишок, и всё такое.
М-м-м, сосисочки!
Итак, органы сгенерированы. Но как теперь засунуть их в старого доброго беса? Вскрытие грудной клетки — это довольно просто: нужно лишь добавить ещё одну ключевую фазу морфинга в модель беса. Но как разместить там органы?
Сначала я думал, что придётся создавать очень сложный алгоритм определения границ, проверяющий, всё ли «упаковано» правильно. В результате оказалось, что достаточно добавить точки спауна органов на костях существа. Но всё ещё остаётся проблема: они вылезают за пределы тела, как видно в областях, обведённых красным.
Буфер шаблона (stencil buffer) спешит на помощь! Можно использовать буфер шаблона для создания «маски» области грудной клетки, и рендерить органы только в этой области.
Сетка маски (зелёная) совершенно плоская, и если внимательно присмотреться, можно заметить её границы. Но даже при движении общий эффект достаточно хорош.
Анализируя свою работу, я думаю, что многие мои решения были избыточными. И я мог достичь лучшего результата с помощью хорошего художника, который нарисовал бы все эти органы. Но это был забавный эксперимент. В конце концов, мне кажется, что самым важным было исследование этой не нанесённой на карты территории. Она настолько странна и необычна, что, наверно, в неё ещё никто не забредал.