Майские праздники не прошли даром: на пару дней я основательно засел за Python и написал собственный лаунчер. Зачем? Он нужен для того, чтобы не привязывать игру к конкретной игровой платформе. В моем случае, я использую GameJolt, но такой подход работает для любого сервиса. Лаунчер служит посредником между игрой и API площадки. Все, что нужно делать игре — это сообщать лаунчеру о событиях наподобие «игрок получил такую-то ачивку». Лаунчер, в свою очередь, передает эти данные игровому сервису. Если надо переехать на другой сервис, достаточно просто обновить лаунчер, а игру патчить не придется — это удобно и экономит массу времени.
(далее…)Dagon 0.22.0
Вышла новая версия движка! Как уже было упомянуто, добавил поддержку скелетной анимации glTF — спасибо denizzzka за реализацию модуля dagon.resource.gltf.animation
с необходимыми классами GLTFAnimationSampler
, GLTFAnimationChannel
и GLTFAnimation
. Скелетная анимация постепенно будет интегрирована в ядро движка: уже добавил абстрактный класс Pose
для хранения матриц костей и необходимую функциональность для их передачи в вершинные шейдеры во всех стандартных пайплайнах Dagon. Вычисление этих матриц зависит от конкретного анимационного воркфлоу, для glTF предусмотрены GLTFPose
и GLTFBlendedPose
.
Также появилась поддержка мешей glTF без текстурных координат, нормалей и индексов. Загрузчик выводит предупреждение, если важные атрибуты отсутствуют, но такие модели теперь можно использовать без проблем.

В движок добавлен встроенный логгер — dagon.core.logger
, который позволяет делать записи функциями logInfo, logDebug, logError и logFatalError. Лог по умолчанию выводится в консоль, можно также включить вывод в файл. Функции логирования работают аналогично writeln
— то есть, поддерживают вариативные параметры любых типов. Можно отключить записи ниже минимального уровня, изменив глобальную переменную logLevel
(по умолчанию — LogLevel.All
).
Улучшения в dagon.core.event
: горячее подключение игрового контроллера и поддержка вибрации (EventManager.gameControllerRumble
).
Добавлен новый примитив — конус (ShapeCone
).
glTF: скелетная анимация
В следующей версии Dagon наконец-то дебютирует поддержка анимации в сценах glTF. Поддерживается GPU-скиннинг, причем универсальный — для любого объекта можно передать в рендер-пайплайн набор матриц костей (за это отвечает объект Pose
) и необходимые вершинные атрибуты (индексы матриц костей и веса).

Поскольку система низкоуровневая, скиннинг требует подготовительной работы — в частности, под каждый уникальный анимированный меш нужен объект позы (Pose
), который анимирует кости и заполняет массив матриц. Позу нужно применить к сущности (Entity
), и тогда в вершинном шейдере меш этой сущности будет трансформирован матрицами, хранящимися в позе. Преимущество в том, что можно расширять систему скиннинга практически без ограничений. Если вы понимаете, как устроен формат glTF, вы можете написать кастомную альтернативу стандартному классу GLTFPose
с любыми фичами: процедурная анимация, обратная кинематика — все, что угодно.
auto characterNode = characterModel.node("character");
characterPose = New!GLTFPose(characterNode.skin, assetManager);
characterPose.animation = characterModel.animation("walk");
Entity character = characterNode.entity;
character.pose = characterPose;
characterPose.play();
Можно прикреплять объекты к костям при помощи родительской связи:
Entity weapon = addEntity(characterModel.node("arm_right").entity);
weapon.drawable = someWeaponMesh;
Const-корректность в D
Русский перевод моей статьи «Const-correctness in D». Оригинал опубликован на Medium.
Ключевое слово const
знакомо каждому программисту — оно присутствует во многих современных C-подобных языках и используется в самых разных контекстах. В общем смысле оно означает, что переменная неизменяема и может быть инициализирована только один раз. Чаще всего такой упрощенный смысл const встречается в динамических языках, однако в мире статической типизации, в том числе и в D, существует несколько видов неизменяемости, и понимание этих различий крайне важно для написания надежного ПО.
Dagon 0.21.0
Выпустил новую версию движка. В этом релизе очень много изменений, в особенности касающихся системы загрузки текстур.
- Переход на SDL 2.32. Под Linux движок теперь предоставляет готовую библиотеку libSDL2-2.0.so, которая копируется в папку с приложением — чтобы ее использовать вместо системной, нужно собирать с флагом линкера
"lflags-linux": ["-rpath=$$ORIGIN"]
(либо перед запуском задавать рабочую папку вLD_LIBRARY_PATH
, что, на мой взгляд, намного менее удобно) - Текстуры теперь загружаются через библиотеку SDL2_Image, если она присутствует. Благодаря этому появилась поддержка прогрессивных JPEG, WebP, AVIF, SVG и множества других форматов. Необходимые библиотеки также копируются в проект при сборке (для 64-битных Windows и Linux). Также можно реализовать и подключить к
AssetManager
кастомный загрузчик изображений - Поддержка текстур формата KTX. Полноценная поддержка KTX1 и KTX2. Текстуры, сжатые в Basis Universal, транскодируются в S3TC/RGTC/BPTC или распаковываются в RGBA8, в зависимости от заданной пользователем настройки. Поскольку для этого требуется дополнительная библиотека, за загрузку KTX отвечает расширение
dagon:ktx
- Расширение
dagon:physfs
, которое позволяет примонтировать вAssetManager
виртуальную файловую систему PhysFS и загружать ассеты из архивов - Упрощенные тени в SimpleRenderer: дефолтный шейдер затемняет пиксели в зависимости от удаленности от указанной точки в плоскости XZ, создавая кружочек тени под объектом. Радиус затемнения можно контролировать, чтобы сделать либо мягкий кружок, либо резкий. Центр тени можно привязать, например, к позиции персонажа
- 4-байтное выравнивание в текстурах, которые загружаются из файла вместе с mip-уровнями
- Функция
isExtensionSupported
для проверки поддержки расширений OpenGL. ТакжеmaxTextureUnits
иmaxTextureSize
— для опрашивания максимального количества текстурных блоков и максимального размера текстуры.
Полный список изменений читайте на странице релиза.
Обновления
bindbc-wgpu 0.24.0
Обновил биндинг к WebGPU, обеспечив поддержку wgpu-native 24.0. Очень рад внедрению WGPUStringView
вместо null-terminated строк — теперь строки в API передаются в виде пары указатель + длина. Это дает прямую совместимость со строками D — не нужно вызывать toStringz
, что всегда меня дико раздражало. В моем биндинге WGPUStringView
в большинстве случаев неявно создается из string
благодаря конвертирующему конструктору this(string)
.
https://github.com/DLangGamedev/bindbc-wgpu
bindbc-physfs
Написал биндинг к PhysFS, популярной библиотеке для абстрактного доступа к файловой системе и содержимому архивов.
Сжатие текстур, часть V. ASTC и Basis Universal
Продолжение серии постов о сжатых текстурных форматах. Предыдущие части: часть I, часть II, часть III, часть IV.
Вот мы и подошли к state of the art текстурного сжатия по состоянию на 2025 год.
ASTC
Adaptive Scalable Texture Compression
Современный формат, созданный с учетом особенностей мобильных платформ. На сегодняшний день крайне мало распространен. Программно поддерживается в Vulkan и новейших версиях OpenGL ES, но аппаратно — далеко не всеми видеокартами. В десктопном OpenGL поддержки нет и, судя по всему, не предвидится (но это не проблема — см. ниже).
В отличие от S3TC, BPTC и RGTC, формат работает с блоками от 4×4 до 12×12. Размер блока ASTC всегда составляет 16 байт, поэтому чем больше блок, тем выше степень сжатия, но ниже качество. Можно выбирать формат блока (например, 5×5, 6×6, 8×8 и т.д.) в зависимости от баланса между качеством и размером. ASTC поддерживает от 1 до 4 каналов.
ASTC поддерживает HDR и является на сегодняшний день единственным универсальным решением для сжатия HDR-текстур на мобильных GPU.
Basis Universal
Использовать ASTC напрямую непрактично, если вы хотите охватить широкий спектр платформ и конфигураций. Для этого была придумана особая система хранения сжатых текстур, которая позволяет приложениям на лету транскодировать их в формат, подходящий для каждой конкретной платформы — ASTC, BPTC, S3TC, RGTC, PVRTC и в несжатые форматы. Basis Universal охватывает как LDR, так и HDR-текстуры в рамках пяти режимов сжатия: ETC1S, UASTC LDR 4×4, UASTC HDR 4×4, UASTC HDR 6×6, UASTC HDR 6×6 intermediate.
ETC1S. Режим низкого и среднего качества, основанный на подмножестве ETC1. Поддерживает переменный баланс веса/качества (наподобие JPEG). Поддерживает альфа-канал. Этот вид текстур можно быстро транскодировать практически в любые другие сжатые форматы.
UASTC (Universal ASTC) LDR 4×4. Подмножество ASTC для стандартных LDR-текстур с 8 битами на канал. Транскодируется также очень эффективно, особенно в ASTC и BC7.
UASTC HDR 4×4. Режим для HDR-текстур, подмножество ASTC HDR 4×4 8bpp. Разработан для обеспечения высокого качества, эффективно транскодируется (с небольшими потерями) в BC6H. В ASTC HDR превращается вообще без какого-либо оверхеда и без потерь. Этот режим также можно транскодировать в различные несжатые HDR-форматы 32-64 bpp.
UASTC HDR 6×6. Режим HDR-текстур 3.56 bpp. Также на 100% эквивалентен ASTC.
UASTC HDR 6×6 Intermediate («GPU Photo»). Быстро транскодирутся в ASTC HDR 6×6, BC6H и различные несжатые HDR-форматы.
ETC1S и UASTC LDR 4×4 могут быть транскодированы в:
- ASTC LDR 4×4 L/LA/RGB/RGBA 8bpp
- BC1-5 RGB/RGBA/X/XY
- BC7 RGB/RGBA
- ETC1 RGB, ETC2 RGBA, ETC2 EAC R11/RG11
- PVRTC1 4bpp RGB/RGBA, PVRTC2 RGB/RGBA
- ATC RGB/RGBA, FXT1 RGB
- Несжатые LDR-форматы.
UASTC HDR 4×4 и UASTC HDR 6×6 могут быть транскодированы в:
- ASTC HDR 4×4 (8bpp, только UASTC HDR 4×4)
- ASTC HDR 6×6 RGB (3.56bpp, ASTC HDR 6×6 или UASTC HDR 6×6 intermediate)
- BC6H RGB (8bpp, UASTC HDR 4×4 или UASTC HDR 6×6)
- Несжатые HDR-форматы.
KTX2 и суперкомпрессия
Basis Universal — это отлично, но как с ним работать и с удобством хранить? Для упрощения этой задачи Khronos Group предложили формат контейнера KTX2, развитие KTX. Если Basis Universal — это механизм сжатия, то KTX2 — чемодан, в который можно упаковать вообще все. Он поддерживает все существующие форматы сжатия, включая ASTC, UASTC, ETC1S, BC1-7, ETC, PVRTC, и сверх того позволяет сжимать текстуры при помощи lossless-алгоритмов (Zstandard, Zlib, BasisLZ). Несжатые форматы, определенные спецификацией Vulkan, также поддерживаются в полной мере. В KTX можно хранить не только 1D-, 2D- и 3D-текстуры, но и кубические карты, mip-уровни и массивы текстур.
Khronos предоставляет набор утилит KTX Software для конвертации изображений в KTX/KTX2, а также для валидации и анализа файлов. Плюс, разумеется, библиотека libktx для декодирования файлов в приложениях — она полностью берет на себя задачу по транскодированию, и на выходе вы получаете текстуру в нужном вам формате, которую остается лишь отправить в графический API.
SDL_Image и загрузчики текстур
Вслед за KTX я решил улучшить в движке ситуацию с поддержкой стандартных форматов изображений. Отныне Dagon загружает текстуры с помощью SDL_Image, если библиотека присутствует, системно или локально. В противном случае используется старый загрузчик на основе dlib.image
. Преимуществом такого подхода является гарантированная под Windows поддержка огромного числа форматов, включая современные WebP и AVIF; также автоматически решается застарелая проблема с декодированием прогрессивных JPEG.
А еще одно важное нововведение — механизм расширения этой системы. Теперь, если нужно добавить новый формат текстур, вместо кастомного ассета достаточно написать и зарегистрировать в AssetManager
‘е кастомный загрузчик текстур — реализацию абстрактного класса TextureLoader
. Он работает почти аналогично ассету, но предназначен для прямого декодирования данных в TextureBuffer
.
Chillwave Drive
Значительно обновлена демка физики автомобиля на Dagon, которая отныне называется Chillwave Drive. Трение колес теперь моделируется на чистых силах вместо встроенных джоинтов Newton, что сделало симуляцию более точной и стабильной. При движении используется динамическое трение (продольное и поперечное) на основе формул Pacejka ’98, при остановке — статическое, препятствующее боковому скольжению машины на склоне. Улучшено управление с контроллера, также добавлена новая модель машины и шейдер неба с облаками и сменой дня и ночи.

Скачать готовую сборку демки под Windows можно тут.
Dagon 0.20.0
Вышло небольшое, но важное обновление Dagon. Добавлена поддержка кастомных шейдеров для текстурирующих слоев материала ландшафта — это делает систему невероятно гибкой, так как вы можете рисовать на ландшафте все, что захотите. В качестве примера в движок добавлен шейдер луж (dagon.extra.puddle
) с эффектом кругов от дождевых капель. Также появилась поддержка Matcap для фейковых отражений (особенно полезная фича в в SimpleRenderer
, где нет честных отражений), поддержка glTF-расширения KHR_materials_emissive_strength, доступ к материалам glTF по именам. Обновлена библиотека Newton под Linux.


В репозитории проекта открыты обсуждения: https://github.com/gecko0307/dagon/discussions