Track

Engines & Graphics

A Bevy-style ECS in C++20 where a system’s parameter list is its dependency declaration, and the scheduler proves at registration time that no two systems in a stage can conflict.

Three years moving up the abstraction ladder: calling the graphics API directly, then abstracting it behind a backend-agnostic interface, then designing the framework that other code plugs into.

2021

GameEngine

Nov 2021 – Apr 2022

Solo · archived

My first engine: an OpenGL renderer with a skeletal animation importer, a templated ECS and an ImGui editor, later ported to Vulkan.

  • Skeletal animation from glTF, written by hand: inverse bind matrices read straight from the accessor, joint parents reconstructed by walking node children, then animation channels and samplers decoded into per-joint translation, rotation and scale tracks keyed by time.
  • A templated ECS where components live in a static ComponentContainer<T> and entities hold indices rather than pointers, with variadic CreateComponent<T>(args...) and a move-constructor specialization so components survive their vector being resized.
  • An ImGui editor with a docked viewport, scene hierarchy, properties panel, console and file browser, about 1,000 lines of it.
  • Single-file GLSL split per stage and compiled with shaderc, with a shader cache and reflection-driven material shaders.
  • Ported from OpenGL to Vulkan on its own branch: instance, device, swapchain, render pass, pipeline, descriptor pool and buffer abstractions, about 2,100 lines.
commits
125
own source
6,091 LOC
Vulkan layer
2,113 LOC

The link points at branch Vulkan, which is the final state. master stops in February 2022, before the port.

The animation system was lost, not finished: the February 2022 importer rewrite carried over everything except skinning, and only the Joint and Animation structs survive at the tip. It works in the December 2021 history.

C++OpenGLVulkanImGuiglTFshadercGLFW

2022

Alloy Engine & Editor

May 2022 – May 2023

With a collaborator · archived

A C++20 game engine with a dockable editor.

Personal project. My father joined for part of it and wrote the original Vulkan boilerplate; I re-architected the renderer in 2023.

  • SPIR-V reflection drives the material system: single-file GLSL is split per stage, compiled with shaderc, reflected with SPIRV-Cross into a recursive type tree and descriptor set layouts, vertex input and per-material uniform buffers are all generated from it.
  • Native scripting uses a C++20 requires-expression to detect at compile time which event handlers a script defines, subscribing only to those; subscriptions are RAII handles that unsubscribe on destruction.
  • The Bullet physics library gives you persistent manifolds, not callbacks. The collision layer walks the manifolds, maps user pointers back to entities, and produces Enter/Stay/Exit events from a per-body tracker.
  • Entering play mode deep-copies the scene in two passes with an equivalence map, so cross-entity references such as physics constraints are fixed up correctly and edits revert on stop.
  • The engine has no ImGui dependency at all; the editor is a separate consumer of it.
commits
155
own LOC
~11.2k
surviving renderer lines mine
91%

The link points at branch experimental, which holds the final state of the code described here. It is mid-refactor and does not build the editor; main, at January 2023, is the last state that runs.

C++20VulkanOpenGLBulletenttDear ImGuiPremake

2023

AlloyEngine (Vulkan)

May 2023 – Dec 2023

Solo · archived

A ground-up Vulkan engine that turned into an experiment in what an ECS framework should look like in C++.

  • A system is a free function whose parameter list declares its dependencies; the scheduler deduces at compile time whether each parameter is a query, resource or event and whether it is read or written.
  • Registration fails if two systems in the same stage would conflict, and the error text tells you to move one to a different stage.
  • Queries specialize over entt: one component picks a view, several pick a group, and the read/write id sets are constexpr.
  • The renderer stores the scene as a RenderPass → Shader → Material → Mesh tree, so state changes are minimized structurally rather than by sorting each frame.
  • Per-frame descriptor pool chains that grow on exhaustion, VMA-backed allocation, and a light manager with O(1) swap-remove and a dirty list so only moved lights re-upload.
commits
100
branches / merged PRs
17 / 12
own LOC
~5.8k

The conflict checker establishes the invariants that make parallel execution safe; the scheduler itself is single-threaded.

Abandoned mid-refactor while extracting the renderer into a plugin.

C++20VulkanVMAenttSPIRV-CrossPremake