Cosmic
C++20 OpenGL 2D Game & Simulation Engine

Cosmic is proven by what runs on top of it — from the canonical template that every project starts from, to a live telemetry dashboard for a real combat robot. Expand a project to read how it works.

TemplateProject is a root manager Layerthat owns a set of child “mode” layers and switches between them:
- TemplateRenderLayer — material + shader + camera demo (animated, time-driven).
- TemplateSpriteLayer — sprite-sheet + ECS demo.
- TemplateRenderBenchmarkLayer — instanced-rendering stress test.
- BallPhysicsSystem — a ParallelSystem example running ball physics across worker threads (the canonical parallel-pipeline demo).
- TemplateTelemetryLayer — wires all five telemetry subsystems together for ~20 simulated agents (record → export → replay → live charts → click-to-inspect).
It is the reference for time management, the composite-layer architecture, ECS integration, parallel physics, and telemetry — and it documents the “double-tick trap” pitfall.
View on GitHub ↗
A single Cosmic plugin layer that:
- Connects to an ESP32 microcontroller over a Bluetooth-SPP COM port using Cosmic::SerialPort.
- Parses framed, checksummed raw KISS telemetry packets tagged Right / Left (one ESP32 reads two drive ESCs on separate UARTs) and decodes them to engineering units on the PC (voltage, current, eRPM, motor RPM, wheel speed in mph, power) — so the conversion constants (motor pole pairs, gear ratio, wheel diameter, slip factor) can be tuned live in the UI without reflashing.
- Feeds both sides into the engine telemetry stack: DataRecorder → CSV + .bin export → DataPlayer replay.
- Overlays Right (red) vs Left (blue) for every channel in a live/replay dashboard, plus a single-side drill-down panel.
- Drives a differential-drive robot visual on a top-down Cartesian map (auto-scaling grid, origin marker, trail) by integrating pose from the two wheel speeds, so you can watch the robot translate and turn.
Fault tolerance:the two sides are fully independent — if one ESC’s telemetry wire dies, that side is flagged (error note + red wheel) and the app keeps running on the surviving side.
Extras: ships ESP32 firmware plus a simulator sketch that synthesizes realistic dual-ESC telemetry over Bluetooth so the whole pipeline can be demoed with no ESC or robot required.
View on GitHub ↗Cosmic is a C++20, OpenGL-backed 2D game and simulation engine for Windows, built around a hot-reloadable plugin model: the engine compiles once into an executable, and each project you build compiles into its own .dll that the engine loads at runtime — so you iterate on your project without ever recompiling the engine.
But it isn’t just a toy renderer. Cosmic blends two worlds: a 2D engine (batch renderer, entity-component-system, materials and shaders, cameras, a multithreaded job system) and a real-time instrumentation platform (a telemetry stack that records, exports and replays data; serial-port hardware I/O; and live ImPlot charts).
That telemetry-and-serial combination lets it talk to real hardware and visualize it live — an uncommon capability for a personal engine, and the reason it has a genuine real-world application: instrumenting a real combat robot.
Cosmic splits into two binaries. The engine host is a single .exe, compiled once. Each project is a separate client workspace — a .dll the host loads at runtime and can hot-reload without ever restarting.
Every project’s entry point is a single Layer subclass. You override only the hooks you care about — OnAttach, OnUpdate, OnFixedUpdate, OnImGuiRender, OnEvent— and export the layer from your DLL. The engine’s Launcherhas a New Project button that copies the canonical template, renames every file and class to your project, and generates a wired CMakeLists.txt and build.bat.

The engine is written from scratch in modern C++. These are its building blocks — the renderer, the ECS, the job system, and the telemetry stack that makes it a real-time data lab.
Telemetry System
Five subsystems working as one. DataRecorder captures per-entity float channels (thread-safe, multi-entity); DataPlayer replays the binary log with seek + interpolation; the TelemetryPanel owns the replay lifecycle with a scrubbable transport bar and live ImPlot charts; and EntitySelection + EntityPicker add click-to-inspect via a world-space hit test. It records to CSV and a binary .bin.
Serial Communication
A Windows COM-port reader (SerialPort) running on its own thread — used to ingest live telemetry from microcontrollers such as an ESP32 over Bluetooth-SPP. This is what connects the engine to real hardware.
Hot-Reloadable Plugin DLLs
The engine .exe loads project .dlls at runtime — rebuild and reload a project without ever restarting the engine.
Layer System
Clean lifecycle hooks — OnAttach, OnUpdate, OnFixedUpdate, OnImGuiRender, OnEvent — plus composite, multi-mode layer support.
2D Batch Renderer
Renderer2D batches quads, lines and SDF circles into minimal draw calls and tracks render stats such as draw-call counts.
Instanced Rendering
A stress-tested path for drawing huge numbers of objects efficiently; the template ships an instanced-rendering benchmark layer.
SDF Circles
Crisp, resolution-independent circles via signed-distance-field shading rather than triangulated geometry.
Materials & Shaders
A Material is a typed uniform bag; a custom GLSL preprocessing system and a documented “shader contract” govern standard uniforms like u_ViewProjection, u_Time and u_ViewportSize.
Sprite Sheets
SubTexture2D addresses atlas sub-regions, making sprite-sheet rendering straightforward.
Entity-Component-System
Scene owns an EnTT registry with built-in TransformComponent, SpriteRendererComponent and TagComponent. Systems come in serial (System) and parallel (ParallelSystem) flavors; rendering groups by material bucket and sorts by depth.
Job System & Parallel Pipeline
A persistent thread pool (worker count = logical cores − 1) with ParallelFor helpers, plus a four-pass pipeline and automatic snapshot/commit via SystemQuery<T> so per-entity simulation runs safely across all cores.
Time & Timeline System
A global time-scale plus per-layer time-scales cascade through the update hooks — supporting pause, rewind (negative time scale) and a fixed-timestep pass for deterministic physics.
Camera System
An orthographic camera paired with a WASD + scroll-zoom controller.
Virtual File System
Path resolution with engine:// and project:// prefixes so assets and logs resolve correctly per project.
Framebuffer (FBO)
Render the scene to an offscreen texture so it can be composited inside an ImGui viewport panel.
Logging
CS_INFO / CS_WARN / CS_ERROR macros (spdlog); the log directory can be redirected into a project’s own asset folder.
#include <Cosmic.h>
class MyProject : public Cosmic::Layer
{
public:
MyProject() : Cosmic::Layer("MyProject") {}
void OnAttach() override { /* create GPU resources, scene, systems */ }
void OnUpdate(float ts) override { /* per-frame logic + rendering */ }
void OnFixedUpdate(float dt) override { /* fixed-step physics */ }
void OnImGuiRender() override { /* draw ImGui/ImPlot panels */ }
void OnEvent(Cosmic::Event& e) override { /* handle input/window events */ }
void OnDetach() override { /* release resources */ }
};A minimal Cosmic project is a single Layer.
Parallel ECS systems run through a structured four-pass pipeline. Components are snapshotted up front, per-entity work fans out across the worker pool, and results are committed back on a single thread — so simulation scales across cores without data races.
| Script | Use |
|---|---|
| setup.bat | Run once per machine. Registers the COSMIC_SDK_DIR env var that every project’s CMake relies on. |
| build_all.bat | Full CMake reconfigure + compile of the engine and all projects. Use after cloning or adding a project. |
| build.bat | Incremental build — skips CMake reconfigure. Day-to-day iteration. |
| build_engine.bat | Builds only the engine host. |
| build_all_release.bat | Clean Release build for distribution. |
/O2 with no asserts (for distribution and benchmarking). The rule: never benchmark in Debug — it can be 5–10× slower. Outputs land in build/Runtime/Debug/ or build/Runtime/Release/.Note: the README in this GitHub repository goes significantly deeper than this page.