Всем привет. Сегодня я покажу вам, как можно создавать 2.5D уровни в изометрии с помощью быстрого прототипирования техникой grayboxing, и генеративного искусственного интеллекта, а именно Stable Diffusion. Практически весь процесс, описываемый в статье легко автоматизируется.
Шаг 1: Создаем прототип геометрии уровня через грейбоксинг
Грейбоксинг (Grayboxing) - техника в гейм дизайне, когда геометрия уровня прототипируется с помощью простых примитивов. Данный шаг можно выполнить в Unity или Blender. Создание геометрии сразу в Unity (с помощью примитивов или Probuilder) позволяет сразу запечь navmesh и протестировать навигацию и логику работы уровня, перед тем как мы перейдем к визуальной части.
Шаг 2: Экспорт рендера грейбокс уровня
Следующим шагом мы экспортируем рандер геометрии уровня в таком ракурсе, в котором его будет видеть игрок. Это необходимо для того, чтобы в дальнейшем мы могли правильно спроецировать текстуру уровня на геометрию. Например, мы используем камеру с углами поворота (54.7°, 0, 45°) в координатах Blender и (35.3°, 135°, 0) в Unity соответственно. Для создания скриншота используется отдельная сцена (Scene) с заранее заданными настройками камеры освещения.
Вариант 2: Экспорт depth map напрямую из Unity/Blender
В качестве дополнительной опции, вместо экспорта освещенной грейбокс-геометрии, можно сразу отрендерить карту глубины напрямую из Blender или Unity (с помощью DepthTextureMode.Depth). Это позволит пропустить следующий шаг. Возможно, это дает лучший результат при генерации текстуры уровня в некоторых случаях, но я не заметил существенной разницы.
Установка и подготовка Stable Diffusion
Я не буду подробно описывать процесс установки Stable Diffusion, на эту тему уже написано много статей. В данной статье мы будем использовать Stable Diffusion Webui, он же Automatic1111. Однако ничего не мешает для автоматизации процесса использовать ComfyUI или Stable Diffusion напрямую из Python скрипта.
Мы используем stable diffusion webui в Docker контейнере, запускаемый на GPU серверах Paperspace с Ampere A4000 (16 GB VRAM).
В качестве базовой модели будем использовать Stable Diffusion XL (SDXL 1.0). Ее можно скачать с Huggingface (копируем в папку models/Stable-diffusion).
Нам так же понадобятся два расширения - LoRA (уже встроена в automatic1111) и ControlNet (ссылка). Для установки поддержки ControlNet в automatic1111, просто перейдите во вкладку Extension и скопируйте ссылку на git репозиторий в поле "URL for extension's git repository", после чего нажмите Install и перезапустите ваш Automatic1111.
LoRA (Low-Rank Adaptation of Large Language Models) - это легковесные модели, которые можно использовать в дополнение к базовой модели для получения конкретного стиля, элемента, персонажа, или другого влияния на результат генерации изображения. Чекпоинты и LoRA - это то чем сегодня живет и дышит комьюнити Stable Diffusion. Civitai - самый известный сайт для поиска и обмена различными чекпоинтами, LoRA и не только. Мы будем использовать LoRA под названием "Zavy's Cute Isometric Tiles - SDXL" - она позволяет создавать арты в изометрии, это как раз то, что нам нужно. Однако, ничто не мешает вам натренировать свою LoRA.
ControlNets - как и LoRA, это модели которые используются в дополнение к базовой, для контроля результата генерации. В отличии от LORA, они никак не влияют на стиль изображения, но зато позволяют влиять на его форму. Например, вы можете использовать скелет в формате OpenPose для задания конкретной позы персонажу. Скачать различные ControlNet модели для SDXL можно с Huggingface.
Мы будем использовать diffusers_xl_depth_full.safetensors, чтобы использовать карту глубины для создания конкретного плана уровня. Она скачивается в папку models/ControlNet.
Шаг 3. Генерируем карту глубины
Переходим во вкладку ControlNet и выбираем наш скриншот геометрии. Выставляем Enable, после чего выбираем Control Type - depth. Выбираем препроцессор depth_midas и модель которую мы установили - diffusers_xl_depth_full.safetensors
Выставим вес контрольной сети (Control Weight) в 0.9. Чем выше это число, тем ближе результат будет к заданному изображению, но если оно слишком высоко, то теряется изюминка и результат будет скучным.
Так же выставим My Prompt is more important, это позволяет немного усилить влияние текстового промта.
Нажмем на оранжевую иконку между препроцессором и моделью - это позволит сгенерировать карту глубины и посмотреть её превью.
Если вместо освещенного грейбокса вы сразу экспортировали карту глубины из Blender/Unity, то можете пропустить шаг с генерацией и просто выберите none в качестве вашего препроцессора.
На данном этапе настройка Control Net завершена, мы готовы сгенерировать наше изображение.
Шаг 4: Генерация текстуры уровня
Для основной генерации я использовал следующие настройки:
Sampling method: DPM++ 3M SDE Exponential
Sampling steps: 40
Width, Height: 1200, 1200
CFG Scale: 7
Промт:
An ancient, dimly lit chamber with ornate carvings on the walls, Pressure plates are visible on the floor, surrounded by torches emitting flickering light, ancient, dimly lit, chamber, ornate carvings, pressure plates, torches, isometric, zavy-ctsmtrc, art, masterpiece, breathtaking, monument valley, lara croft go, empty background, <lora:zavy-ctsmtrc-sdxl:1>
Негативный промт:
photography, cropped, crop
Можем увеличить Batch Size и меняя промпт, подобрать тот дизайн, который вам нужен.
Шаг 4: Экспорт карт albedo, specular, normal
Для создания реалистичного 2.5D освещения, нам понадобятся различные текстурные карты. Вы можете создать карту нормалей с помощью img2img, или просто с помощью препроцессора Normal Map, по аналогии с созданием карты глубины из третьего шага. Отдельный экспорт albedo позволяет "удалить освещение", и наложить его после средствами игрового движка.
К сожалению, я не нашел open-source решения для экспорта карт albedo и specular. Это можно сделать платно с помощью сервиса SwitchLight. Пишите в комментарии, если вы знаете способы сделать это с помощью Stable Diffusion.
Шаг 5: Доработка текстур и удаление деталей с помощью Inpaint
Наша текстура почти готова, но для создания геймплея было-бы неплохо удалить некоторые элементы такие как фон или огонь (его мы добавим частицами). Так же можно доработать текстуру для интерактивных элементов, таких как двери, кнопки, рычаги итд. Для этого отлично подходит инструмент inpaint, расположенный во вкладке img2img.
Используем masked content - fill и настройки, схожие с оригинальной генерации. В качестве промта используем то, что хотим дорисовать, например для закрытой двери: closed stone door, zavy-ctsmtrc, isometric, <lora:zavy-ctsmtrc-sdxl:1>
Шаг 6: Репроекция текстуры
Наша текстура готова, осталось использовать её в игре. Для этого можно использовать различные техники, схожие с фотограмметрией. Однако самый простой способ, который можно использовать для большого количества схожих уровней - это просто создать шаблон UV развертки на куб изнутри.
Результат:
Немного саморекламы:
Мы - небольшая удаленная инди-студия, которая создает мобильные игры. Мы будем рады, если вы попробуете нашу последнюю игру Bifrost: Heroes of Midgard которая вышла в прошлом году на iOS и Android.