Как сделать рендер карты майнкрафт
Как известно, для игры Minecraft разработано большое количество разнообразных программных продуктов, каждый из которых имеет в своем функционале полезные инструменты. Это и создание различных скинов, утилиты для просмотра карт, редактирование уже готовых локаций, разработка собственных модов и многое другое. Сегодня мы вам расскажем про еще один продукт, который сочетает в себе большое количество разнообразных функций. Основная, это рендер карт. То есть, вы можете открыть определенную локацию, сделать скриншот и отредактировать его так, как в Photoshop.
Но и это еще не все. Программа Chunky minecraft позволяет просматривать карты. Допустим, вы загружаете или указываете путь к сохранению. Далее просто используете параметры рендера картинки и сохраняете ее. При этом вы можете использовать функции встроенного зума, добавить текстуры, выбрать нижний или верхний мир, выбрать определенные координаты локации и многое другое. На самом деле эта утилита очень полезная. Лично я ее использую больше для создания красивых макетов карты, чем для рендера. К сожалению, редактирование занимает довольно таки продолжительное время, поэтому использую в этих целях крайне редко, но вам все же советую.
У нас на сайте практически в каждом материале, который связан с картами, выкладывается скрин, в котором представлен полный макет определенной локации. Для этого используется данная утилита. Если говорить конкретно о рендере, то сразу вам скажу, что его возможности просто безграничны. Видели когда-нибудь в интернете картинки с красивыми постройками? Допустим, где с высоты птичьего полета виден весь замок, и прилегающая к нему территория. При этом нет никаких проблем с прогрузкой чанков. Это также было реализовано при помощи этого продукта.
В целом, программа Chunky позволяет настраивать конечный результат так, как вы хотите. Например, вы можете добавить собственные текстуры облаков или выбрать картинку в интернете. Будет выглядеть очень красиво. Дополнительно можно настраивать позиции камеры, выбирать качество изображения, делать многочисленные скриншоты в процессе рендера, добавлять свои текстуры, настраивать угол наклона и захода солнца, отблески, ветер, туман и многое другое. В общем, это универсальный продукт, который предназначен именно для игры Minecraft. Если вы хотите удивить друзей, да и сами научиться работать с изображениями, то вам обязательно нужно использовать эту утилиту.
Переделывание и ускорение базового тайлера
Изначально тайлер имел внешний вид стандартной консольной утилиты, через args задавались параметры рендеринга и он начинал жужать. Для удобства использования, я решил переделать его под ООП и прикрутить минимальный графический интерфейс, в качестве решения проблем с быстродействием сделал его многопоточным. В итоге получилось что то такое:
Структура обновлённого тайлера
После ввода всех данных для отрисовки, стартует интерфейс, который проверяет введены ли все параметры и если да, начинает построение очереди на рендеринг. Класс построения очереди(QueueBuilder) стартует в отдельном потоке и служит для того, чтобы иметь представление о том, сколько тайлов всего, сколько осталось, и чтобы на этапе рендеринга не собиралась инфа о тайле а сразу переходило к делу по готовым данным. Информацию о тайлах в очереди я решил размещать во временные файлы, для того, чтобы они не лежали в оперативной памяти, потому как её не хватит даже на 18 зумов Беларуси, а когда очередь лежит в файлах по 30 миллионов тайлов, при загрузке вектор с ними занимает 2гб оперативы, что было в переделах разумного для моего пк.
Код формирования очереди
После того как очередь создана, QueueBuilder не завершает свою работу а остаётся до конца, для выдачи каждому потоку рендера следующего тайла. И здесь стартуют потоки рендера, как определить количество потоков на текущем пк я так и не узнал (возможно кто то в комментах подскажет), поэтому создаю 4 потока, рендерер ничего интересного не делает, просто создаёт директорию в которую будут сохраняться тайлы и начинает свои тёмные дела (полное описание рендеринга займёт ещё одну статью), после окончания отрисовки тайла, запрашивает следующий и так пока солнце не зашло. По окончанию отрисовки всех тайлов уходит сигнал в интерфейс и интерфейс стартует класс пересохранения тайлов.
Обзор технологии
Какую конкретно задачу пытается решить GANcraft?
GANcraft нацелен на решение задачи преобразования одного мира в другой мир. Имея семантически размеченный мир, например, такой, который используется в популярной игре Minecraft, GANcraft способен преобразовать его в новый мир, имеющий ту же структуру, но с добавленным фотореализмом. После этого новый мир можно рендерить с произвольных точек обзора, получая фотореалистичные видео и изображения, сохраняющие внешний вид при смене точек обзора. GANcraft упрощает процесc 3D-моделирования сложных ландшафтных сцен, на создание которых потребовались бы многие годы практики.
По сути, GANcraft превращает любого игрока Minecraft в 3D-художника!
Вопрос: "Почему просто не использовать преобразование im2im?"
Так как исходных истинных фотореалистичных рендеров для созданного пользователем блочного мира не существует, нам приходится обучать модели при помощи непрямого контроля.
Хорошими кандидатами являются некоторые уже существующие решения. Например, можно использовать методики преобразования «изображение-изображение» (image-to-image, im2im), в частности, MUNIT and SPADE, изначально обучавшуюся только на 2D-данных, чтобы конвертировать покадровые маски сегментации, спроецированные из блочного мира, в реалистично выглядящие изображения.
Также можно использовать wc-vid2vid — методику, учитывающую 3D-объём, для генерации изображений с постоянным внешним видом при помощи 2D-ретуширования и 3D-искажений, применяя в качестве 3D-геометрии поверхности вокселей.
Эти модели нужно обучать на преобразовании реальных карт сегментации в реальные изображения, а затем применить в Minecraft.
В качестве ещё одной альтернативы можно обучить NeRF-W, изучающую поле 3D-излучения от нефотометрической, но позиционированной и 3D-неизменной коллекции изображений. Её можно обучить по прогнозируемым изображениям из методики im2im (псевдоистинных данных, о которых будет рассказано в следующем разделе), то есть данных, которые максимально близки к требованиям.
Слева направо: MUNIT, SPADE, wc-vid2vid, NSVF-W (NSVF + NeRF-W), GANcraft(наша методика)
Сравнивая результаты различных методик, мы сразу же можем заменить некоторые проблемы:
- Методики im2im наподобие MUNIT и SPADE не сохраняют внешний вид объектов вне зависимости от точки обзора, потому что они не имеют знаний о 3D-геометрии и каждый кадр генерируется отдельно. создаёт видео с постоянным внешним видом объектов, но со временем качество изображения быстро портится из-за накопления погрешностей блочной геометрии и недостаточного количества данных для тестового обучения.
- NSVF-W (наша реализация NeRF-W с добавленной воксельной подготовкой в стиле NSVF) тоже создаёт результаты с постоянным внешним видом объектов, но результат выглядит скучным и ему не хватает мелких деталей.
Несовпадение распределения и псевдоистинные данные
Допустим, у нас есть подходящая модель нейронного рендеринга с воксельной подготовкой, способная создавать фотореалистичный мир. Нам всё равно нужен какой-то способ её обучения без истинных изображений с указанным расположением камеры. Adversarial training достигло определённого успеха на задачах нейронного рендеринга малого размера без условий, когда изображения с указанием их позиции недоступны. Однако для GANcraft проблема ещё более сложна. В отличие от реального мира, блочные миры из Minecraft обычно имеют гораздо более разнообразное распределение меток. Например, некоторые сцены могут быть полностью покрыты снегом, песком или водой. Существуют также сцены, в которых на небольшой площади пересекается множество биомов. Кроме того, невозможно сопоставить сэмплируемое распределение камер с распределением на фотографиями из Интернета при случайном сэмплировании точек обзора из модели нейронного рендеринга.
Примеры изображений, сгенерированных без псевдоистинных данных:
Примеры изображений, сгенерированных с псевдоистинными данными:
Как видно на первых примерах, adversarial training с помощью фотографий из Интернета из-за сложности задачи приводит к нереалистичным результатам.
Создание и использование псевдоистинных данных для обучения стало одним из самых важных вкладов нашей работы и значительно улучшило результаты (вторые примеры).
Генерирование псевдоистинных данных
Псевдоистинные данные — это фотореалистичные изображения, сгенерированные из масок сегментации с помощью предварительно обученной модели SPADE. Так как маски сегментации сэмплируются из блочного мира, псевдоистинные данные имеют те же метки и позиции камер, что и изображения, сгенерированные для тех же точек обзора. Это не только снижает рассогласование распределения меток и камер, но и позволяет нам использовать более сильные потери, например, функции перцептуальных потерь и L2, для более быстрого и стабильного обучения.
Гибридный нейронный рендеринг, ограниченный вокселами
В GANcraft мы задаём фотореалистичную сцену сочетанием объёмного 3D-рендерера и рендерера изображений 2D-пространства. Мы задаём нейронное поле свечения, ограниченное вокселями: имея данные блочного мира, мы назначаем каждому углу блоков вектор характеристик, и используем трилинейную интерполяцию для задания кода расположения в произвольных местах внутри вокселя. Благодаря этому можно задать поле излучения при помощи MLP, получающего на входе код локации, семантическую метку и код общего стиля, а на выходе создающего точечный объект (схожий с данными излучения) и плотность его объёма. Зная параметры камеры, мы рендерим поле излучения для получения карты 2D-характеристик, которая при помощи CNN преобразуется в изображение.
Полная архитектура GANcraft
Такая двухэтапная архитектура значительно улучшает качество изображений, сокращая при этом объёмы вычислений и занимаемой памяти, потому что поле излучения можно смоделировать более простым MLP. Предложенная нами архитектура способна обрабатывать очень большие миры. В своих экспериментах мы использовали воксельные сетки размером 512x512x256, что эквивалентно 0,26 квадратным километрам.
Нейронный купол неба
Старые методики нейронного рендеринга на основе вокселей не могли моделировать бесконечно удалённое от сцены небо. Однако небо является неотъемлемым ингредиентом фотореалистичности. Для добавления неба мы используем в GANcraft дополнительный MLP. MLP преобразует направление луча камеры в вектор характеристик, имеющий тот же размер, что и точечные объекты из поля излучения. Этот вектор характеристик используется в качестве полностью непрозрачного окончательного сэмпла луча, смешивающего характеристики пикселя в соответствии с оставшейся пропускаемостью луча.
Генерация изображений с разнообразным внешним видом
Процесс генерации GANcraft является условным и зависит от задающего стиль изображения. Во время обучения мы используем в качестве задающего стиль изображения псевдоистинные данные, что позволяет объяснить несоответствие между сгенерированным изображением и псевдоистинными данными потерями при реконструкции. Во время вычислений мы можем управлять стилем выходных данных, передавая GANcraft различные изображения, задающие стиль. В примере ниже мы линейно интерполируем стиль между шестью различными изображениями стиля.
Minecraft Wiki
Из-за новой политики Microsoft в отношении сторонних ресурсов, Minecraft Wiki больше не является официальной. В связи с этим были внесены некоторые изменения, в том числе и обновлён логотип вики-проекта. Подробности на нашем Discord-сервере.
Получение [ ]
Крафт [ ]
Стол картографа [ ]
Карту также можно создать из одного листа бумаги, используя стол картографа. Для создания карты с локатором, помимо листа бумаги, требуется наличие компаса.
Появление в инвентаре [ ]
В Legacy Console Edition, при первом посещении мира игроком, пустая карта появляется в инвентаре игрока автоматически. Аналогичный функционал можно активировать для миров в Bedrock Edition при создании мира.
Карта
Разные: нет
Пустые, одинаковые: да (64)
Преобразуем миры Minecraft в трёхмерные фотореалистичные сцены с помощью нейросетей
Мы представляем GANcraft — работающий без участия человека фреймворк нейронного рендеринга для генерации фотореалистичных изображений больших миров из 3D-блоков, например, таких, которые созданы в Minecraft. Наша система получает на входе мир из семантических блоков, в котором каждому блоку назначена метка, например, «земля», «дерево», «трава», «песок» или «вода».
Мы задаём мир как непрерывную объёмную функцию и обучаем нашу модель рендерингу фотореалистичных изображений с сохранением внешнего вида с произвольных точек обзора без наличия реальных изображений блочного мира.
Кроме позиции камеры, GANcraft позволяет пользователю задавать семантику и стиль сцены.
Выходные данные нашей модели. В левом нижнем углу показаны блочные миры, подаваемые на вход.
Видео с кратким описанием
Использование [ ]
Каждая карта обладает тремя основными параметрами:
- Измерение, в котором была создана эта карта. Если карту одного измерения смотреть в другом, она не будет обновляться или отображать игрока.
- Центр, определяется местом создания карты, но часто случаются ошибки.
- Масштаб, определяется количеством уменьшений, которые были выполнены над этой картой.
При первом использовании карта не центрируется по игроку, мир разбит на большие невидимые квадраты и карта отображает тот, где первый раз используется. Это сделано для того, чтобы у разных карт одного масштаба не было перекрытий, и при вставке карт в соседние рамки можно было получить ещё большую карту. Соответственно, чтобы начать рисовать другой квадрат карты, нужно её первый раз использовать за пределами уже изученного квадрата.
Карта, помещённая в рамку, занимает целую сторону блока.
Мир и центр являются постоянными, масштаб в определённых пределах можно изменить крафтом. Это значит, что изображение карты не будет «передвигаться» во время перемещения игрока, и масштаб не будет при этом меняться, что отличает карты в Minecraft от типичных карт в других играх. По этим причинам, как только игрок окажется за границей карты, она перестанет обновляться, и чтобы продолжить нанесение местности на карту ему придется создать новую, уже с другим центром, либо увеличить масштаб карты, если это возможно.
Карта будет обновляться только в том случае, если игрок держит её в руках. Обновления карты также привязаны к времени. Это значит, что любые изменения в ландшафте карты, которые произошли за радиусом разведки карты, не будут на ней отображаться до тех пор, пока игрок снова не посетит эту местность. Когда карта находится в руках игрока, она не заслоняет собой область пространства впереди, поскольку находится ниже; чтобы увидеть карту, игроку нужно посмотреть вниз.
Карта создается чистой. Пустые карты складываются до 64. Для того, чтобы начать исследовать пустую карту, нужно нажать ПКМ, держа её в руке. Масштаб самой первой карты таков, что она может быть с самого начала изучена полностью.
Карты привязываются к сетке. Центр карты не будет местом её создания, вместо этого она будет отображать участок с кратными границами, в котором находится игрок.
Совет: размещайте карту на столбах или обзорных плоскостях. Желательно в разных масштабах.
Отображение карт в игре [ ]
Цвета карты соответствуют цветам элементов в мире, но с некоторыми исключениями. Например, песчаник и золотой блок обращаются в серый, трава в болотном биоме выглядит зелёной, а гравий имеет на картах жёлтый цвет.
Индикатор позиции [ ]
В Java Edition и Legacy Console Edition метка на карте, указывающая позицию игрока, является частью непустой карты. В Bedrock Edition также можно создать карту без компаса, такая карта не имеет данного индикатора позиции, но он может быть добавлен путём объединения карты с компасом.
Bedrock Edition [ ]
Если игрок находится за пределами карты, на её границе будет круглая метка, показывающая, в какой он стороне.
Если карта находится в рамке, на ней и на всех её дубликатах рамка будет отмечена меткой, похожей на метку игрока, но зелёного цвета.
Масштабирование [ ]
Карту можно расширить: крафт карты, окруженной бумагой, даст уменьшенную карту. Она будет иметь тот же центр, но втрое меньший масштаб. Уменьшенная карта создается неисследованной, даже если на исходной карте что-то было изучено. Уменьшение масштаба одной карты не приведёт к уменьшению масштаба всех её дубликатов.
Для расширения карты также может использоваться стол картографа, в этом случае для уменьшения масштаба достаточно 1 листа бумаги.
Как ускорить загрузку карт и другие изобретения велосипедов
По идее всё сделано, тайлы отрендерены, лежат в папке, бери модуль карт и запускай. Но всегда что то пойдёт не так, после запуска карты и скролла туда обратно можно заметить, что чем больше тайлов отрендерено, тем дольше грузится зум, и при числе картинок 256х256 в полтора миллиарда, поиск в папке нужной занимает неприлично большое время и ресурсы.
Решение этой проблемы пришло не сразу, но пришло, я создал бинарный файл в который поместил константы, константы представляют собой структуру для каждого зума в которой содержится:
общее количество тайлов
стартовые номера тайлов по x и по y на сетке меркатора
количество тайлов по x и по y, для чего это нужно покажу позже.
Класс информации о тайлах с операторами сериализацииПосле констант я положил в файл структуры с информацией о тайлах, на каждый тайл своя структура, она содержит в себе:
количество долготы широты в пикселе(для отрисовки маршрутов, об этом в следующей статье, если эту прочтёт более 4х человек)
размер картинки тайла в байтах
стартовая позиция картинки в этом же бинарном файле
Ну и последнее это загрузка картинки тайла из папки в файл, картинка ложится в конец файла и указтель возвращается к структуре с инфой об этом тайле и записывается его стартовая позиция в файле и размер для считывания в будущем.
Получение нужного тайла в модуле картографии
Для понимания дальнейших действий покажу как тайлы располагаются на сетке меркатора.
Размещение тайлов на сетке меркатора
Покажу нахождение тайла на примере, без голых формул.
Тоесть в нашем случае 1 - 0, таким образом по X у нас лежит 1 тайл перед требуемым, так же рассчитываем по y получается 2. StartPosX взято из структуры с константами.
XtileCount - количество тайлов X в одном столбце Y
CountY - предыдущие вычисления
Получаем 4*2+1 = 9, как видно на картинке, всё верно.
Далее находим количество тайлов на предыдущем зуме для того, чтобы через seek перескочить на нужный. Просто берём константы предыдущих зумов и забираем количество тайлов прибавляя к TileCount. В итоге получается 14 тайлов лежит перед необходимым.
И одно из последних действий это перенести указатель на структуру нужного тайла и считать её.
После этого из структуры берём начальную позицию картинки и размер её и забираем искомый тайл.
Что же в итоге? В итоге реализовав поддержку файла в модуле картографии с помощью пары формул, получаем поиск нужного тайла за несколько seek по файлу, ну и на загрузку любого зума теперь уходит не более секунды.
Благодарности
Хотелось бы поблагодарить Сахарука Андрея за кураторство в проекте и друзей из Чехии(Framstag и Karry) за отзывчивость и помощь с API :)
Содержание
Как вывести рендеринг карт на сверхзвук и не…
В данной статье я расскажу как я делал тайлер на основе openstreetmaps на С++/Qt. Задача была написать картографический модуль приложению для поисково-спасательных отрядов, которые работают в условиях недоступного интернет соединения и возможно целые сутки, поэтому требования к картографическому модулю стояли следующие:
работа в оффлайн режиме
насколько это возможно быстрый рендеринг определённой области на карте
высокая энергоэффективность загрузки и отображения тайлов на карте
OpenStreetMaps был выбран банально из-за open source, да и модулей к нему в свободном доступе было много. Основу тайлера я взял у libosmscout, но для меня он имел множество проблем, о которых расскажу далее.
Читайте также: