Giving fireEngine its first scene
This release turns fireEngine’s hard-coded triangle path into the beginning of a structured rendering architecture. Meshes, materials, render objects, scene hierarchy, and render preparation are now represented independently of
Vulkan, while Renderer compiles those descriptions into the GPU resources and commands required to draw them.
The build has been divided into three targets. fireEngineTutorialEngine is a reusable static library containing the engine implementation, fireEngineTutorial is the small application and event loop in main.cpp, and
fireEngineTutorialTests exercises the library through Catch2. This separation allows most behavior to be tested without creating a Vulkan device or opening a window.
A new RenderAssets collection owns reusable mesh and material descriptions. Strongly typed IDs connect those assets into render objects without allowing mesh, material, and render-object references to be mixed accidentally.
Graphics colors now use a dedicated Color4 type, while new vector and matrix types provide the transformations required by the scene.
The scene graph owns only transformable SceneNode instances. Nodes may form a hierarchy, carry local and resolved world transforms, and optionally instance a render object. A scene may contain several roots and produces a stable,
depth-first SceneDrawList containing the current world transforms and a hash of its transform-independent rendering dependencies.
RenderPreparation provides the first compilation boundary between high-level scene descriptions and renderer-owned resources. It validates asset relationships, identifies the distinct meshes, materials, and render objects required
by the current draw list, and caches the resulting RenderPreparationPlan. Transform-only changes reuse that plan, while asset revisions or changed render-object dependencies trigger recompilation.
The renderer now owns the complete Vulkan implementation behind a Vulkan-free public interface. This is a breaking change from 0.6: the constructor now accepts Glfw, Window, and the application name rather than externally
constructed device, allocator, swapchain, and pipeline objects.
Rendering also has a new explicit two-step contract. prepare() must be called before drawFrame() and performs validation, plan compilation, and required GPU allocation. Calling drawFrame() without successful preparation throws
std::logic_error. Once prepared, drawFrame() consumes current scene transforms and records drawing without performing hidden asset allocation.
Included in this release
- Separate engine-library, tutorial-application, and Catch2 test targets.
- Vulkan-free render assets with strongly typed mesh, material, and render-object IDs.
- A hierarchical, multiple-root scene graph with resolved world transforms.
- Cached render-preparation plans that remain valid across transform-only changes.
- Explicit prepare() and allocation-free drawFrame() phases.
- A pimpl renderer that owns the Vulkan device, allocator, swapchain, pipeline, frame state, and compiled resources.
- Indexed mesh rendering with per-draw transform and material-color push constants.
- Vec3, Vec4, Color4, and column-major Mat4 types using C++23 multidimensional subscripting.
- Testable detail interfaces for asset validation, SPIR-V loading, and swapchain selection.
- 24 device-free unit tests plus the rendered-frame smoke test, for 25 CTest tests in total.
- Separate public API and internal implementation Doxygen sites.
- Linux, macOS, and Windows build coverage.
- A CI terminology gate enforcing consistent US English in first-party code.
- A consistently pinned vcpkg registry and CI toolchain.
- Catch2 3.15.3, GLFW 3.5.1, Slang 2026.7.1, Vulkan Memory Allocator 3.4.0, and Vulkan Headers and Loader 1.4.357.0.
- Explicit XCB and Xlib loader support for GLFW’s Linux X11 presentation paths.
- Project version updated to 0.7.0.
The tutorial still constructs its triangle assets and scene directly in main.cpp; external model loading remains deliberately separate. This release establishes the asset, scene, preparation, and renderer boundaries needed to
introduce glTF loading, visibility selection, richer materials, and more advanced render compilation without pushing those concerns into the Vulkan implementation.