Umbra Engine
Umbra Engine is a custom C++ game engine designed for 2D games, featuring a lightweight Entity-Component-System (ECS) architecture, a multithreaded job system, modular service layer, and full support for real-time game mechanics.
Features
Core Architecture
- Custom ECS framework inspired by ENTT — bitset-based component matching, typed views, and multi-phase system execution (
FrameStart→Simulation→PreRender→FrameEnd) - Scene graph with parent-child transform hierarchy — local/world matrix propagation via DFS each frame
- Scene management with async transitions and LDtk level editor integration
Multithreading & Parallelism
- M:N job system — fixed thread pool with work-stealing queue
ParallelForfor data-parallel workloads (e.g. texture loading batches)- Dependency chains via
SubmitAfter—JobHandle/JobCompletionprimitives with completion callbacks - Primitives:
Mutex,SpinLock,ConditionVariable,Thread(RAII wrapper)
Rendering
- Decoupled
RenderService— ECS submitsRenderQuaddraw commands each frame; service handles sort, cull, batch, and flush - GLSL shader support via
IShader/SfmlShader+MaterialComponentfor per-entity shaders DebugDrawerfor lines, circles, boxes, and oriented boxes without ECS coupling- Sprite-sheet animation system —
AnimationClip::FromGrid()helper, frame-rate controlled UV writes
Asset System
AssetManager— demand-loaded, path-keyed cache for textures, fonts, and shaders- Async variants (
GetTextureAsync,GetFontAsync,GetShaderAsync) — callbacks fire on job completion ShaderResourcesupporting fragment-only and vertex+fragment pipelines
Physics & Collision
- Dynamic AABB tree for broadphase and Sequential Impulse based collision solver for narrow phase and collision event callbacks
PhysicsService+ `ECS bridge’ — ECS ↔ PhysicsService sync (creates/destroys bodies, syncs transforms)
Audio
AudioServicebacked by miniaudio — fire-and-forget and looping playbackAudioResourceintegrated into the async asset cache
Diagnostics & Utilities
MemoryTracker— hooks globalnew/delete; per-category atomic stats with live ImGui panelPathUtils— header-only path manipulation (normalize, join, stem, extension, relative/absolute)LDtkEntityComponent— arbitrary field map from LDtk entity layer for designer-driven data
Read up on implementation in my devblog series
Watch the Physics System Demo: