Add MrGameEng.Atlases: texture atlas builder, runtime loader and CLI tool
CI / build-test (push) Failing after 1m13s

AtlasBuilder packs a directory tree of loose images into atlas pages plus
JSON metadata (deterministic shelf packing, incremental rebuilds, orphan
cleanup); TextureAtlas loads them back handing out Texture2DRegions, so
sprites from one page batch into a single draw call. The asset handle
generator maps .atlas files to TextureAtlas and skips page images.
Demonstrated in the sample (Assets/Atlases + 'atlas' console command),
wrapped as tools/MrGameEng.AtlasTool for build scripts.

Documented dependency exception: Atlases depends on Graphics and Assets.
This commit is contained in:
Leonid Pershin
2026-06-11 08:18:30 +03:00
parent d6f19b9119
commit b318d1e795
21 changed files with 1209 additions and 1 deletions
+40
View File
@@ -33,6 +33,7 @@
| `MrGameEng.Audio` | Звуковые эффекты и музыка |
| `MrGameEng.Assets` | Runtime-загрузка ресурсов без Content Pipeline, кэш, `AssetRef<T>` |
| `MrGameEng.Assets.Generator` | Roslyn incremental source generator: классы с типизированными хендлами ресурсов |
| `MrGameEng.Atlases` | Текстурные атласы: офлайн-сборка из дерева картинок (`AtlasBuilder`) и рантайм-загрузка (`TextureAtlas`); CLI — `tools/MrGameEng.AtlasTool` |
| `MrGameEng.UI` | Игровой UI на [Myra](https://github.com/rds1983/Myra): `Desktop` на сцену, виджеты, скининг |
| `MrGameEng.DevConsole` | Ингейм-консоль разработчика: логи `Log`, команды, история, автодополнение |
@@ -50,6 +51,10 @@ MrGameEng.Assets ─┘ └──► Friflo.Engine.ECS
Модули зависят **только от `Core`** и никогда друг от друга. `Core` зависит только
от MonoGame и Friflo. Если двум модулям нужен общий тип — он переезжает в `Core`.
Документированное исключение: `MrGameEng.Atlases` зависит от `Graphics`
(выдаёт `Texture2DRegion`) и от `Assets` (регистрирует загрузчик в `AssetManager`) —
атлас по своей природе склейка этих двух областей.
`MrGameEng.Assets.Generator` — особый случай: это анализатор (netstandard2.0),
он подключается к проекту игры как `Analyzer`, в рантайме не участвует и не зависит
от других модулей движка.
@@ -125,6 +130,39 @@ public static partial class GameAssets
Обращение к ресурсу по строковому пути в коде игры — запрещено соглашением;
строки существуют только внутри сгенерированного кода.
## Текстурные атласы
`MrGameEng.Atlases` превращает дерево отдельных картинок в атласы и грузит их в рантайме.
Спрайты с регионами одной страницы атласа батчер сливает в один draw call.
### Сборка (билд-тайм, без GPU)
`AtlasBuilder.Build(AtlasBuildOptions)` — чистый CPU (StbImageSharp/StbImageWriteSharp):
- Источник сканируется рекурсивно (png/jpg/jpeg/bmp); картинки группируются в атласы
по первым `GroupDepth` папкам относительного пути (0 — один атлас на всё).
- Упаковка — детерминированный shelf-packer (`ShelfPacker`): сортировка по высоте,
полки, страницы до `MaxPageSize`² (по умолчанию 2048), зазор `Padding` (2 px),
размер страницы подрезается до степени двойки; негабаритные картинки получают
отдельную страницу под себя.
- Выход: страницы `<Имя>.atlas.<N>.png` + метаданные `<Имя>.atlas` (JSON: страницы,
регионы с ключами и прямоугольниками). Ключ региона — путь от корня источника без
расширения (`Things/Pawn/Animal/Fox`).
- Инкрементальность: группа пересобирается только если изменились исходники, состав
файлов или параметры сборки; атласы исчезнувших групп удаляются из выходной папки.
CLI-обёртка: `dotnet run --project tools/MrGameEng.AtlasTool -- <источник> <выход>
[--group-depth N] [--page-size N] [--padding N] [--root-name Имя] [--force]`.
### Загрузка (рантайм)
- `context.UseTextureAtlases()` регистрирует загрузчик `TextureAtlas` в `AssetManager`;
кодогенератор выдаёт хендлы `AssetRef<TextureAtlas>` для файлов `.atlas`
(страницы `*.atlas.N.png` собственных Texture2D-хендлов не получают).
- `TextureAtlas` владеет страницами (premultiplied alpha, как все текстуры движка)
и отдаёт регионы: `atlas.GetRegion("Things/Pawn/Animal/Fox")` → `Texture2DRegion`,
готовый для `Sprite`.
## Рендеринг
`SpriteBatch` в движке **не используется** — в `MrGameEng.Graphics` свой батчер,
@@ -243,4 +281,6 @@ docs/ документация (русский)
| FontStashSharp.MonoGame | 1.5.6 | Шрифты (ttf) в рантайме |
| NVorbis | 0.10.5 | Декодирование ogg |
| Myra | 1.6.1 | Игровой UI |
| StbImageSharp | 2.30.15 | Декодирование картинок при сборке атласов |
| StbImageWriteSharp | 1.16.7 | Запись PNG-страниц атласов |
| dotnet-mgfxc (dotnet tool) | 3.8.4.1 | Компиляция шейдеров при сборке |