
TheHellBox
Как я поднял количество кадров в своей игре в 2 раза
Каждый раз когда я делал пост о своей аркадной гонке, beaterCore, в коментариях находились люди с жалобой, что игра не работает в программном рендере на пентиуме 2 с 256 мб ОЗУ - ведь текстуры пиксельные, и полигонов мало, значит все должно быть как в 98м году!
Мне эти коментарии откровенно не нравились, так как игра и так работала на железе 15ти летней давности, и я действительно занимался оптимизацией - отрисовка графики где можно идет большими группами(Batch Rendering), количество вызовов отрисовки я старался минимизировать настолько, насколько возможно. Но комментарии все-таки меня тронули, и заставили задуматься, ведь действительно - у меня есть старый ноутбук 2013го года со встроенной графикой, и там игра работает не очень.
Было замечено, что производительность падает больше всего на больших картах. Из этого сделал вывод, что виновником плохой производительности скорее всего является отрисовка ландашфта.
Решил посчитать - большие карты в игре имеют размер 1024x1024 метра. На каждый метр 2 треугольника.
Умножаем, 1024 * 1024 * 2 = ...
2 Миллиона треугольников?!
Виновник найден. Теперь осталось вынести ему смертный приговор.
Для уменьшения количества треугольников, которые нужно отрисовать видеокарте, будем использовать динамическую детализацию ландшафта - поделим его на куски 32x32 метра, и будем решать детализацию каждого куска в зависимости от его удаленности от камеры.
Ландшафт отрисовывается на видеокарте вертекс-шейдером. В шейдер я кидаю текстуру ландшафта, и он на основе позиции вертекса смотрит, какая должна быть высота в этой точке.
- где quads - количество вертексов, на краях участка
Все, что нужно для уменьшения детализации - снизить количество вертексов, запрашиваемых для отрисовки в вызове, и небольшую модификацию в шейдере, чтобы он использовал большее расстояние между точками
- где lod_level - уровень детализации
Вблизи от камеры lod_level равен единице, так мы используем каждый пиксель карты высот. А в 200 метрах меняем этот параметр на 8, так детализация будет меньше в 8 раз.
Если рисовать ландшафт в полной детализации на расстоянии примерно 200 метров, а на большем расстоянии снижать детализацию в 8 раз, то на карте 1024x1024 метра количество треугольников упадет до ~100 000. В 20 раз лучше чем прежние 2 миллиона.
Артефакты на границах
На границах между участками ландшафта с разной детализацией неизбежно будут появлятся швы. Решение достаточно простое - рисовать "Юбку" на стыках. Под юбкой имеется в виду дополнительный набор полигонов на границе участка, которые вместо того, чтобы использовать высоту из карты высот, идут строго вниз.
Такая юбка хорошо прячет стыки, но более элегантным решением является деградация полигональной сетки на стыках между границами участков - но так как юбка работала достаточно хорошо, я не стал использовать этот метод
Идем дальше
Так как мы уже делим ландшафт на куски, для дальнейшей оптимизации мы можем пропускать отрисовку кусков ландшафта вне поля видимости камеры - эта техника называется Culling.
Таким образом мы снижаем количество вызовов на отрисовку в 2-3 раза, в зависимости от положения камеры на сцене
Результаты
Количество треугольников на трассе 1x1км снизилось в 40 раз. Это крайне положительно отразилось на производительности на слабых видеокартах - на Intel HD Graphics 2013го года количество кадров в секунду на трассе увеличилось с 25 к/с до 50 к/с. Я сомневаюсь, что есть железо, с поддержкой OpenGL 3, которое было бы значительно слабее - так что теперь можно считать, что игра будет работать фактически на всем. Так же хочу упомянуть, что в игре реализовано изменение маштаба разрешения (Render scaling) - так, что 3д графика рисуется в разрешении более низком чем интерфейс, благодаря чему отрисовку графики можно ускорить еще больше, не теряя четкость текста на экране
На этом все. Попрошу читателя посетить страницу игры в магазине Steam - и если игра понравится, добавить в список желаемого или попробовать демо-версию - мне это сильно поможет
https://store.steampowered.com/app/3711050/BeaterCore/
Добавил сглаживание в свою инди-гонку. Разбираемся как работают эти алгоритмы
Разработка beaterCore ведется уже 15 месяцев, и все это время в игре отсуствовало сглаживание, по причине использования своего собственного игрового движка. Так как игра близка к выходу, начинаю заниматься мелочами, и сглаживание как раз попалось под руку.



Сравнение разных видов сглаживания на сцене. 1: Без сглаживания. 2: 8X MSAA. 3: SSAA (2X)
Читатель, редко играющий в игры, может не знать отличие между MSAA и SSAA, и зачем оно вообще нужно.
Обьясняю: Сглаживание необходимо из-за ограничений разрешения экрана. Когда графика отрисовывается на экране - на каждом пикселе экрана производится набор математических операций, которые определяют, прежде всего, нужно ли его рисовать, или нет.
Так как у таких вычислений только 2 исхода - рисовать или не рисовать - линии на границах модели выглядят "Грубо"
Цель сглаживания - убрать грубые края, так, чтобы линии выглядяли плавнее
Благодаря визуально плавным линиям, создается ощущение, что картинка была отрисована в большем разрешении, чем на самом деле.
Так же один из эффектов использования сглаживания - снижение визуального "шума" при движении камеры. Когда игрок меняет положение, с которого он смотрит на сцену, видеокарта выбирает совершенно другие пиксели для отрисовки. Так при движении создается шум, вызванный резкой сменой цветов на экране. Алгоритмы сглаживания помогают уменьшить эту проблему.
Читатель может задать вопрос, чем сглаживание отличается от простого размытия изображения? Ответ простой - алгоритмы сглаживания добавляют недостающую на картинке информацию, пока размытие теряет уже существующую.
SSAA
Самый качественный алгоритм сглаживания - SSAA. Или же супер-семплинг.
Принцип его работы крайне простой - изображение рисуется в разрешении большем, чем разрешение экрана, а затем сжимается назад.
Пример - разрешение вашего экрана 1920x1080. SSAA сначала отрисует сцену в разрешении 3840x2160, а затем используя линейную или кубическую фильтрацию уменьшит назад в к исходному разрешению экрана.
Так края не просто сглаживаются - на изображении появляется дополнительная информация, которую рендер не смог бы захватить в исходном разрешении
На примере выше можно заметить, что при применении SSAA у буквы i появилась точка сверху, которую не смогла захватить отрисовка в исходном разрешении экрана
Но не смотря на высокое качество результатов работы алгоритма, у него есть большая проблема - он требует очень много вычислительных ресурсов для исполнения. По этому его применение ограничено играми с очень простой графикой, или при наличии крайне производительного компьютера и желании максимального качества изображения.
MSAA
Из-за слабой производительности SSAA возникла необходимость в более быстрых алгоритмах сглаживания. MSAA - один из таких алгоритмов.
Его принцип работы не сильно отличается от SSAA, но MSAA работает только на краях полигонов. Внутри отрисованного полигона MSAA ничего не делает.
Такой подход значительно снижает количество дополнительных пикселей, которые нужно отрисовать видеокарте.
Другие алгоритмы
В современном мире существует множество других алгоритмов сглаживания. Их общая цель - иметь качество, схожее с SSAA, при этом работая быстрее.
Примеры таких алгоритмов:
FXAA - Работает за счет "размытия" резких границ на изображении. Один из самых быстрых алгоритмов сглаживания, основным недостатком которого является низкая четкость изображения
TAA - Похож на MSAA, но дополнительно использует информацию из предыдущих отрисованных кадров. Позволяет снизить визуальный шум, о котором я говорил ранее, при этом используя меньше дополнительных пикселей
DLAA - Алгоритмы на основе нейронных сетей. Плюсом такого подходя является высокое качество итогового изображения, при относительно низком использовании ресурсов видеокарты. Главный минус: такие алгоритмы требуют дополнительные специализированные ядра на видеокарте, повышая ее стоимость.
Новое меню выбора мероприятий в моей гонке
Раньше в beaterCore был простой список мероприятий. Теперь - красивая карта с плавными анимациями и большим количеством информации о предстоящих гонках
Добавил динамический звук в свою игру. Громкость звука зависит от ландшафта и обьектов вокруг игрока
Не так круто, как рейтрейсинг аудио, но из-за открытых локаций от полноценной реализации было бы мало проку.
С объектами всё просто, луч между камерой и источником звука - если есть препятствие, снижается громкость.
Ландшафт немного сложнее. Луч проверяет высоту ландшафта на своем пути, а также сколько метров он провел "под землей", громкость звука определяется и на основе максимальной высоты и толщины ландшафта через которую пришлось пройти лучу.
Разработка аркадной гонки на Rust с нуля. Ошибки и успехи. История разработки beaterCore
14 месяцев назад я начал разрабатывать гонку. Идея была простой - с дедлайном 4 месяца сделать простую игру без пафоса. Ну, любой разработчик знает, что произошло дальше - без пафоса не вышло.
Истоки
У меня есть глупый принцип делать как можно больше задач самостоятельно. Этот принцип применяется и к игровым движкам - я их не использую. Давным давно попробовал делать игры с нуля на языке Rust и с тех пор упорно продолжаю. Каждый год что-то новое, первым проектом был чат для VR шлемов, потом космосим... 3 космосима. И вот сейчас гонка.
Идея гонки у меня была давно, я просто люблю этот жанр и всегда знал, что в нем есть незанятая ниша. Нишей этой является некий единорог - аркадная гонка которая ощущалась бы как симулятор. Такие игры как-бы есть но они не совсем попадали в мои критерии. Мне очень хотелось, чтобы любой мог начать играть в игру без опыта, но не хотел типичный картинг или аркаду без веса автомобиля.
Было решено сделать комбат-рейсер с элементами ремонта автомобилей. Чтобы сделать моего единорога - двигатель и трансмиссия должны были симулироватся относительно реалистично(Присуствовало бы сцепление, переключение передач, кривая момента у двигателя), а покрышки относительно аркадно.
В основе "ядра" гонки встал как раз таки заброшенный космосим, от него перешел простой рендер на API Vulkan и редактор уровней, а так же система ввода, звука, и общая организация проекта.
Через пару дней удаления всего связанного с космосом у меня получилось чистое "ядро" из которого можно было начинать лепить гонку
А через неделю, когда я только-только вник в основы симуляции покрышек, у меня уже ездила машинка по сцене
Отдельно про шины
Кто бы мог подумать, что симуляция шин будет сложной? Ведь цель-то - сделать просто!
Было решено использовать модель динамики шин Ханса Б. Пасейки. Эту модель использует большая часть гонок, кроме совсем серьезных симуляторов.
Итог - первые месяцы разработки игры ушли в тонкую настройку шин. Оказалось, что внедрять эту модель в игру задача не простая. Есть множество различных способов интерпретации параметров этой модели, и каждый будет работать по разному.
Особой сложностью обладает задача совмещения сил по двум осям - в оригинале модель работает только в одном направлении, а в игре шины подвергаются различным силам с разных сторон. Разные игры решают эту задачу по разному, я могу похвастатся, что метод который я использую относительно уникален - правда получен он скорее методом проб и ошибок а не наукой.
Пример ранней симуляции шин. Заметно что машина тяжело поворачивается. Финальная версия значительно отличается
Графика. Формирование внешнего вида игры



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



Первая машина оставшаяся в финальной версии игры. Узнаёте чем она была вдохновлена?
Развитие игры. Сложность создания игровых механик
Изначально игра планировалась только для сетевой игры с друзьями. Но по мере разработки увеличивался и масштаб, появилось желание добавить одиночную компанию.
Вместе с одиночной компанией родилась и основания тематика игры - ремонт автомобилей. Вместе с ремонтом появилась и экономика, игроку нужно зарабатывать деньги с гонок, чтобы себе его позволить. Элементы комбат-рейсинга были забыты. На бумаге все просто, на практике продумывать как и что будет делать игрок оказалось тяжелой задачей.


Развитие карты города
В момент разработки я играл в Neon White, и мне очень понравилось оформление главного меню игры ввиде карты города с локациями которые можно посетить. Клянусь, я не копировал Gran Turismo! Быстро появилась идея с гаражем, где игрок бы чинил свой автомобиль, магазином автозапчастей, дилером, и свалкой старых автомобилей(Которая сейчас лишь в планах). В первом прототипе можно заметить, что вместо дилера стоит парк, в нем игроку планировалось встречать квестовых персонажей - увы, тоже идея которая не дожила до текущей версии игры.
Раняя версия гаража
Планировалось, что каждая гонка будет случайной. Со случайной картой и соперниками, сложность которых возрастала бы со временем. В итоге было решено отказатся от такой системы, и вместо этого иметь режим карьеры, состоящий из предустановленных мероприятий, которые игроку постепенно предстоит пройти.
Позже в игре появились и первые диалоги с персонажами. В будущем планируется развить взаимодействие с ними, но и сейчас им можно задать вопросы, вызвать на дуэль или одолжить их автомобиль
Сетевая игра
Я уже упоминал, что игра планировалась только для игры с друзьями. Эту идею я не оставил, и как только одиночная игра стала меня устраивать - я начал разработку игры по сети.
Я решил оставить элементы карьеры и в ней. При игре по сети игрок так же зарабатывает деньги как и в одиночной игре, а запчасти автомобиля имеют такой же износ. Теоретически одиночная игра является опциональной.
Первые версии сетевой игры работали уже через неделю после начала её разработки, но мелочи приходится исправлять до сих пор.
При выпуске игры в Steam так же пришлось добавить поддержку Steam Networking Sockets, для простых людей - возможность пригласить друга в игру через клиент Steam без необходимости открывать порты. Хочу отметить мой исключительно позитивный опыт с Steam SDK, разработчикам планирующим добавить сетевую игру в свои игры могу смело сказать, что боятся его не нужно.
API Vulkan - не для слабых. Я понял, что я слаб
Главной ошибкой для меня стало использование API Vulkan. Я уже упомянал ранее что в основу ядра гонки лег мой прошлый проект. Этот проект во многом я начинал ради изучения Vulkan, по этому и в гонке большую часть времени оставался он. Но лично у меня сложился негативный опыт.
Во первых разработка любой фичи связанной с графикой занимала в 10 раз больше времени. Физически больше нужно писать кода, куда больше пространства для ошибок.
Во вторых я постоянно натыкался на проблемы возникающие только на определенном железе. Если все работает хорошо на NVidia - далеко не факт, что код будет функционировать на картах Intel или AMD. И даже если код работает на одной видеокарте AMD - не факт, что он будет работать на другой.
Это встало мне боком на первом выпуске демо версии игры - на некоторых системах игра просто не запускалась, даже не выдавала ошибку, а на других системах игра крашилась через 30 минут. Как это исправлять я не знал, а иметь в запасе 15 видеокарт для тестирования на каждой не практично.
В итоге за 3 дня перевел всю графику на OpenGL и забыл про Vulkan как страшный сон. Хотя в будущем возможно постараюсь вернуть его опционально.
Выпуск демо-версии на itch.io
До выпуска демо-версии в Steam я выложил игру на itch.io. Игра не получила широкой огласки, и на момент написания статьи имеет 370 загрузок. Но польза определенно была - решение перевести игру на OpenGL было принято как раз после выпуска на itch.
График просмотров и загрузок на itch.io Заметно что в первую неделю было больше всего трафика, релиз демо версии в Steam 5го февраля никак не повлиял на количество загрузок
Выпуск демо-версии в Steam
Для выпуска демо-версии в Steam нужна была страница. Для начала нужно заплатить пошлину в 100$, это даст возможность получить доступ к личному кабинету разработчика где можно начать оформление страницы.
Поначалу я очень боялся заниматся оформлением, казалось, что это задача, к которой стоит подходить с наивысшей ответственностью. В реальности же я бы не рекомендовал разработчикам сильно нервничать по поводу оформления на ранних этапах разработки, Valve фактически пропускает все у чего есть скриншоты и внятное описание, а видимость страницы в любом случае будет низкой без дальнейшего маркетинга.
Страницу в магазине я выложил в публику в тот же день как и выпустил демо версию на itch. А вот демо версию в Steam я выпустил уже через 3 месяца, когда был уверен, что игра находится в достойном для этого виде.
Запуск оказался весьма успешным, некоторые проблемы конечно всплыли - например некоторые игроки принимали экран выбора автомобиля за экран загрузки, из за чего пришлось добавить подсказку. За неделю после запуска 400 человек добавили игру в список желаемого
Демо версия была выпущена 5го февраля. На графике можно видеть резкий рост количества человек, добавивших игру в свой список желаемого
Про Rust
Вообще я не вижу огромного смысла говорить о языке програмирования. Честно и в заголовке он больше для того чтобы вызвать интерес. Но раз уж упомянул - скажу пару слов.
Мне он просто нравится. Я пишу игры на Расте уже 10 лет и своими глазами видел развитие экосистемы.
Мне нравится, что мой код работает на всех платформах без модификаций. Мне очень нравятся библиотеки и их авторы. Отдельное спасибо Ralith за библиотеку hecs(ECS система), SamiP за fundsp(Звук, высокий уровень), а так же спасибо всем, кто участвует в разработке библиотек gilrs(Ввод), cpal(Звук, низкий ровень), разработчикам nalgebra и parry(Математика и коллизия), и многим другим(Полный список используемых библиотек можно узнать скачав игру и посмотрев файл THIRDPARTY_LICENSES)
А что за игра то?
Название игры - beaterCore. Сейчас доступна только демо-версия
Страницу в магазине Steam можно найти по ссылке
https://store.steampowered.com/app/3711050/BeaterCore/
Так же игру можно найти на itch.io
https://the-hellbox.itch.io/beatercore
После 14 месяцев разработки выпустил демо-версию своей первой игры. beaterCore - Аркадная гонка про ремонт старых автомобилей
beaterCore это игра, которую я всегда хотел найти сам. Я обожаю игры с механиками ремонта, а гонки всегда занимали отдельное место в моём сердце. Ничего такого найти, увы, не мог - было решено делать самостоятельно.
Отдельно про физику - я люблю определённый реализм в играх, совсем простенькие аркады редко нравились. При этом сам не являюсь фанатом хардкорных симуляторов, слишком сложно. В игре я постарался соблюсти баланс между реализмом и простотой, и мне кажется, у меня это получилось. Машины в игре имеют реальный вес и полноценную симуляцию работы двигателя и коробки передач, но остаются управляемыми (если износ покрышек не слишком высокий!)
В демо-версию включён полностью функциональный мультиплеер, а для любителей посиделок с друзьями присутствует режим игры с раздельным экраном.

























