Обновления

Выпустил первое крупное обновление Dagon после стабильного релиза — 1.1.0. В этой версии исправлены некоторые баги, добавлен модуль проверки столкновений в 2D и в целом несколько упрощена работа с 2D-играми. Во всех встроенных шейдерах сабрутины GLSL заменены на ветвления для лучшей совместимости со старыми видеокартами. Стартовала работа над редактором сцен для движка.

К этому релизу я приурочил выпуск переиздания моей старой игры 2048×2 — версии популярной головоломки 2048 для двух игроков. Игра портирована на Dagon, что обеспечило поддержку x86_64 и улучшило качество рендеринга шрифтов. Также я добавил переводы игры на немецкий, французский, испанский, португальский и другие языки. Графический стиль и механика не изменились.

Сборку для Windows можно скачать тут, исходники и linux-версия будут на днях.

Подробности об инциденте 3 июня

Итак, что же произошло? 3 июня 2026 года нидерландский дата-центр nLighten без предупреждения обесточил серверы в Дронтене, которые арендовала компания MIRhosting. Этот инцидент стал продолжением массовой волны отключений: ранее с этим столкнулся еще один крупный российский хостинг VDSina.

Началась эта история с преследования двух лиц, которые, по версии следствия, причастны к кибератакам и операциям по вмешательству в выборы в Дании в конце 2025 года — в частности, обеспечивая инфраструктуру для атак хакерской группы NoName057(16). Тогда в Дании перестали работать сайты политических партий, датского парламента и издания The Copenhagen Post, а также была нарушена работа системы MitID, через которую граждане получают доступ к государственным сервисам.

По информации европейских информагентств, серверы компаний MIRhosting и WorkTitans наиболее активно использовались для осуществления незаконных действий на территории ЕС. Руководство MIRhosting, впрочем, все обвинения отрицает. MIRhosting — крупный оптовый провайдер, ориентированный преимущественно на B2B. Среди его клиентов множество мелких хостингов, в том числе и тот, услугами которого я пользовался (по соображениям безопасности, не буду его пока раскрывать).

Я пока не понимаю, какие юридические основания были для отключения со стороны дата-центра. Исходя из отписки техподдержки хостинга, есть вероятность, что это не более чем перестраховка, и все вернут (то есть, серверы не конфискованы полицией, а просто на всякий случай отключены). Но чисто интуитивно оснований для оптимизма я не вижу. В таком вот непредсказуемом мире мы сейчас живем.

Блог частично восстановлен

Хорошие новости: мне удалось восстановить большую часть постов 2026 года (правда, без картинок) из локального архива и сохранившихся копий Wayback Machine. В архивах сохранилось многое, но, к сожалению, все это практически невозможно импортировать в WordPress без ручной правки. В ближайшее время я восстановлю материалы за 2025 год, а остальным буду заниматься по мере сил.

Вскоре напишу подробный пост о том, что произошло с сервером.

Блог утерян :(

Из-за серьезных проблем с датацентром, на котором в последнее время был размещен блог, мне пришлось мигрировать на новый VPS. К сожалению, восстановить базу постов не удалось. Все, что я пока смог воссоздать — тема и некоторые страницы в меню (их версии по состоянию на май 2025 года).

Я не оставляю надежду, что еще удастся вернуться на старый сервер, где сохранились все данные, но большого оптимизма по этому поводу нет. Вероятнее всего, придется начать все с нуля.

Формат DAF

В предыдущем посте я уже писал о том, почему glTF нельзя использовать в качестве полноценного формата игровых ассетов, и вот альтернатива, которую я специально проектирую для Dagon 2.0 — Dagon Asset Format, сокращенно DAF.

DAF хранит, в первую очередь, вершинные буферы для прямой передачи в VRAM. Формат бинарный, архитектурно соответствующий API Dagon 2.0 и расширяемый: в нем могут быть объявлены любые дополнительные структуры данных и даже динамические свойства, не ломая обратную совместимость.

Основные задачи формата:

  • Хранение данных в форме, подходящей для прямой загрузки в видеопамять без накладных расходов на обработку (zero overhead). В отличие от glTF, в DAF вершинные буферы имеют фиксированный формат, согласованный с пайплайном движка, не требуя конверсии;
  • Максимальная эффективность десериализации. glTF требует парсинга JSON и динамического построения довольно сложных объектов в памяти (списков, словарей), а загрузка DAF – это просто реинтерпретация слайсов байтового буфера в массивы POD-структур. DAF экономит память и сокращает риск утечек, поскольку не требует множества аллокаций;
  • Частичная десериализация. Декодер может читать из DAF только те данные, которые ему нужны, не разбирая остальные.
  • Формат «все в одном». Файл DAF может хранить как отдельный меш, так и целую сцену. Все структуры формата поддерживают пользовательские свойства, что позволяет хранить в DAF метаданные редактора. Фактически, DAF может быть использован как простая NoSQL база данных для различных целей.
  • Поддержка семантики данных. Все объекты имеют список классов, что позволяет движку группировать их для задач игровой логики. Все текстуры помечаются как baseColor, normal, height, roughness-metallic, emission, для того, чтобы движок мог выбрать оптимальный BCn формат сжатия.
  • Поддержка данных для физики и проверки столкновений (в разработке).

Спецификация DAF находится здесь.

Недостатки формата glTF

В Dagon 1.0 я очень много времени потратил на поддержку этого монструозного формата моделей, и спустя пять лет работы с ним у меня не осталось ничего, кроме разочарования. Главный вывод: glTF — не для игровых ассетов (т.е. карт и отдельных переиспользуемых моделей). Это формат, предназначенный исключительно для просмотра, причем в основном в браузере, на WebGL, при помощи вьюверов типа Sketchfab. В этом он свою задачу выполняет, хотя и тоже неидеально. Но то, что его все начали использовать как формат обмена данными между программами моделирования и игровыми движками — это фундаментальная ошибка. Ниже мой личный список недостатков glTF, актуальных, прежде всего, в контексте игрового рендеринга.

  • Трансформация нод в glTF хранится либо в виде комбинации позиции, поворота и масштаба (TRS), либо в виде матрицы 4×4. Такая вариативность сильно усложняет игровую логику, так как без декомпозиции обратно в TRS вы не можете ничего анимировать. Декомпозиция матриц — задача нетривиальная, у нее нет стопроцентно надежных решений, и это делает glTF-сцены в общем случае неподходящими для интерактивности. Для игр намного оптимальнее всегда хранить трансформацию в виде TRS и конвертировать в матрицу в движке, что является простейшей задачей.
  • Нефиксированный лейаут вершин — то есть, физическое расположение атрибутов в общем массиве данных может вариьироваться от отдного меша к другому, равно как и формат чисел в буферах. Это совместимо с OpenGL/WebGL, но очень плохо для низкоуровневых API, где формат вершин фиксирован на уровне PSO и не может меняться в проходе. Движок вынужден конвертировать формат в свое внутреннее представление, что убивает саму идею формата — прямую загрузку данных в видеопамять без препроцессинга.
  • Поддержка моделей без некоторых атрибутов — например, без текстурных координат или нормалей. В игровом движке не может быть такого, что нормали отсутствуют, для PBR-пайплайна их все равно нужно предоставить шейдеру. Поэтому отсутствующие атрибуты приходится генерировать — а как это делать, glTF не регламентирует, приходится изобретать свою логику. Это, опять-таки, противоречит идее «эффективного GPU-формата».
  • Кости для скелетной анимации определены как обычные ноды сцены, хотя они логически принадлежат не сцене, а отдельному виду объектов — собственно скелету. Скелет не вставляется в граф сцены, а используется как источник данных для построения pose-матриц для каждой индивидуально анимированной модели в сцене. То есть, с точки зрения архитектуры движка, glTF-подход к скелетке очень далек от эффективного решения несложной в принципе задачи.
  • Поддержка отрицательного масштаба. Для рендеринга это зло, потому что меняет winding и влияет на отбор видимости. Иногда при рендеринге это используется целенаправленно, но в форматах 3D-моделей практически всегда приводит к проблемам совместимости.
  • Использование web-first форматов текстур — PNG и JPEG. В AAA-движках эти форматы практически не используются из-за того, что они требуют декодирования на стороне CPU. Кроме того, для игр с большими мирами жизненно важно блочное сжатие текстур, это индустриальный стандарт. А с glTF получается, что нужен отдельный этап декодирования и сжатия изображений в GPU-френдли форматы. Это может и не быть большой проблемой, если движок поддерживает такой процесс, но все равно возникает много сложностей. Основной вопрос — в какой формат движку сжимать цветные текстуры? Если это base color, то, конечно, достаточно BC1/BC3 (в зависимости от наличия альфа-канала), но для карт нормалей уже желателен BC7, а для черно-белых изображений эффективнее BC4. glTF никак не регламентирует семантику текстур, она определяется на уровне материалов, что в общем случае не позволяет реализовать полностью автоматический алгоритм выбора формата.

В общем, в Dagon 2.0 я обязательно буду пилить собственный формат ассетов, учитывая весь этот опыт. Поддержка glTF сохранится благодаря библиотеке Assimp, но формат больше не будет позиционироваться как основной.

Новости по Dagon 2

Разработка Dagon 2.0 началась в весьма бодром темпе. Deferred-рендер уже почти готов — остались только тени PSM и DPSM, поддержка локальных зондов освещения и forward-проход. Я добавил систему кэширования ресурсов, сжатие в BC7 (на основе компрессора bc7enc Рича Гелдриха) и проделал еще множество мелких улучшений на разных стадиях формирования кадра. Особое внимание я уделил тому, чтобы картинка соответствовала Eevee в Blender 5.

Что еще нового? Часть функциональности, которая в Dagon 1.0 существует в качестве расширений, теперь войдет в ядро — это физика на базе Jolt и загрузчик текстур в формате KTX/KTX2. Такое решение я принял исходя из полезности этих фич, простоты сборки Jolt и libktx из исходников и их автономности: они не имеют собственных зависимостей и отлично работают на всех платформах (в противовес тому же Newton, который имеет проблемы с работой некоторых функций под Linux). Наличие libktx «из коробки» дает серьезные преимущества и ставит Dagon 2 в авангард движкостроения; в будущем не исключен перевод текстурного кэша с DDS на KTX2.

Еще одним нововведением будет встроенная VM GScript3, которую я разработал в прошлом году. Движок при старте загружает скомпилированный байт-код скрипта и выполняет его, а скрипт, в свою очередь, навешивает обработчики событий, позволяя, таким образом, выполнять внешнюю логику без пересборки игры. Игра может экспонировать скриптовой системе свои данные и методы, что полезно для создания модов. Некоторые встроенные классы Dagon уже реализуют интерфейс GsObject и напрямую совместимы с GScript: это Entity, Scene, World, BaseGame.

Зарегистрирован пакет dagon2 в реестре DUB, так что начать пользоваться можно уже сейчас.

Переезд сайтов на домене ru

В связи с тем, что в России для владельцев доменов в зонах ru/su/рф ввели обязательное подтверждение через Госуслуги, я решил отказаться от timurgafarov.ru и перенести все свои персональные ресурсы на pixperfect.online. Это касается следующих сайтов и страниц:

Dagon 2.0 на SDL3. Долгосрочные планы

Я пишу графику на OpenGL много лет (с 2009 года) и считаю, что этот классический API — до сих пор самый очевидный выбор, если вам нужно кроссплатформенно вывести что-то на экран. В сочетании с SDL это еще и очень просто — код приложения со всеми его ключевыми компонентами (окно, графика, ввод) получается на 99% независимый от операционной системы. Для 2D-проектов этой связки более чем достаточно, но в играх с продвинутой 3D-графикой, которая выжимает максимум из видеокарты, теперь, к сожалению, все сложнее.

Я выделяю три главные архитектурные проблемы OpenGL: однопоточность, частая синхронизация CPU и GPU и сложность управления глобальным состоянием конвейера. Новые низкоуровневые API решают все это, особенно последнее, жертвуя удобством написания приложений и вообще входным порогом в профессию графического разработчика (я не представляю, как можно изучить концепции и идиомы Vulkan с полного нуля — я бы рвал на себе волосы, если бы пришлось объяснять начинающим, что такое дескриптор-сеты, PSO и барьеры памяти). Долгое время между OpenGL и Vulkan была совершенно непреодолимая стена концептуальной несовместимости, мешающая портировать игры. OpenGL, между тем, хоть никуда и не делся, развиваться перестал. Под macOS — старая версия, под Windows — довольно серьезная проблема с вертикальной синхронизацией в оконном режиме, приводящая к статтерингу (это полноценно решается только путем работы поверх свопчейна DXGI, что требует нетривиального бойлерплейта в приложении, либо поддержки со стороны видеодрайвера). Ну и до кучи в OpenGL нет поддержки HDR-режима Windows, что некритично, но не круто.

Все это подводит к мысли, что OpenGL, каким бы он комфортным ни был, уже отжил свое. Но и на Vulkan переходить совершенно не хочется. Познакомившись с SDL GPU, я решил попробовать портировать на него некоторые ключевые части Dagon и быстро понял, что этот API — именно то, чего мне и не хватало в последние годы. WebGPU стал разочарованием из-за громоздкости интерфейсов и спорного синтаксиса WGSL, а здесь с этим проблем нет.

Исходники Dagon 2.0 доступны в отдельном репозитории на GitHub: https://github.com/gecko0307/dagon2. На данный момент перенесен dagon.core, реализованы G-буфер, базовый deferred-рендеринг, тонмаппинг и анти-алиасинг. Движок загружает модели OBJ и текстуры в стандартных форматах, поддерживает кубические карты и DDS. Судя по всему, большая часть возможностей Dagon будет перенесена без серьезных изменений, картинка движка останется прежней, но не исключены архитектурные улучшения и CPU-оптимизации. Также изменится шейдерный API — на днях напишу отдельный пост об этом. Переход на Vulkan-бэкенд должен заметно ускорить рендер, а также позволит использовать HDR-свопчейн, если дисплей позволяет выводить в extended linear.

Я не уверен, что процесс портирования будет быстрым, но впечатления от работы пока весьма положительные, код для SDL GPU компактный и читаемый. Самая нетривиальная часть — воркфлоу компиляции шейдеров, но я уже смирился с тем, что от GLSLang в современных условиях никуда не денешься. Есть вероятность, что Dagon 1.0 я выпущу уже в ближайшее время, чтобы полностью сосредоточиться на порте.

Dagon 1.0

Рад сообщить, что наконец-то выпустил Dagon 1.0.0, первый стабильный релиз моего игрового движка! Это в основном исправляющий релиз, который подытоживает огромную работу над Dagon, которую я проделал за последние два года. Набор основных фич заморожен, дальше будут только багфиксы и развитие расширений (которые все пока экспериментальные и нестабильные). Также у меня в долгосрочных планах написать редактор сцен, концептуально близкий к редактору Unity.