diff --git a/library/phx/display_system.hpp b/library/phx/display_system.hpp
index bca638e4be07da5252da1b1f7b9a1ce95f8743e3..ffcc68492dda98db366bf20f8bf9cd684590e1e8 100644
--- a/library/phx/display_system.hpp
+++ b/library/phx/display_system.hpp
@@ -26,6 +26,7 @@
 #include <memory>
 #include <vector>
 
+#include "phx/engine.hpp"
 #include "phx/export.hpp"
 #include "phx/hmd.hpp"
 #include "phx/system.hpp"
@@ -37,7 +38,6 @@ namespace phx {
 
 class PHOENIX_EXPORT DisplaySystem : public System {
  public:
-  explicit DisplaySystem(Engine* engine);
   DisplaySystem(const DisplaySystem&) = delete;
   DisplaySystem(DisplaySystem&&) = default;
   ~DisplaySystem();
@@ -57,6 +57,9 @@ class PHOENIX_EXPORT DisplaySystem : public System {
   void Update(const FrameTimer::TimeInfo&) override;
 
  protected:
+  explicit DisplaySystem(Engine* engine);
+  friend DisplaySystem* Engine::CreateSystem<DisplaySystem>();
+
   std::unique_ptr<Window> window_;
   std::unique_ptr<HMD> hmd_;
 };
diff --git a/library/phx/engine.cpp b/library/phx/engine.cpp
index 0b5b2e55608a7800e61577af524e105965f9381f..315ac6ae015c0562bb1c78c3a0461c275943469b 100644
--- a/library/phx/engine.cpp
+++ b/library/phx/engine.cpp
@@ -57,27 +57,19 @@ void Engine::Run() {
 
   frame_timer_.Start();
 
-  InitializeSystems();
   is_running_ = true;
   while (is_running_) UpdateSystems();
-  TerminateSystems();
 }
 
 void Engine::Stop() { is_running_ = false; }
 
 bool Engine::IsRunning() const { return is_running_; }
 
-void Engine::InitializeSystems() {
-  for (auto& system : systems_) system->Initialize();
-}
 void Engine::UpdateSystems() {
   // before updating all systems, update the frame timer
   frame_timer_.Tick();
   for (auto& system : systems_) system->Update(frame_timer_.GetTimeInfo());
 }
-void Engine::TerminateSystems() {
-  for (auto& system : systems_) system->Terminate();
-}
 
 std::string Engine::ToString() const {
   return "(Engine, #Systems: " + std::to_string(systems_.size()) +
diff --git a/library/phx/engine.hpp b/library/phx/engine.hpp
index 81a29919975cb8cfc5ddd2fb18fc7be2d28565fa..481afbe06eac5f947da28688362e5256427d1ad5 100644
--- a/library/phx/engine.hpp
+++ b/library/phx/engine.hpp
@@ -108,9 +108,7 @@ class PHOENIX_EXPORT Engine final : public Loggable {
     return typeid(SystemType) == typeid(system);
   }
 
-  void InitializeSystems();
   void UpdateSystems();
-  void TerminateSystems();
 
   std::vector<std::unique_ptr<System>> systems_;
   bool is_running_ = false;
diff --git a/library/phx/rendering_system.cpp b/library/phx/rendering_system.cpp
index 893b5e53071617ce4975dc3d62fedb904fc81b57..15a17eb3ef60a938bec74ec15002c0bc98ff0310 100644
--- a/library/phx/rendering_system.cpp
+++ b/library/phx/rendering_system.cpp
@@ -47,18 +47,20 @@
 
 namespace phx {
 
-RenderingSystem::RenderingSystem(Engine* engine) : System(engine) {}
+RenderingSystem::RenderingSystem(Engine* engine, DisplaySystem* display_system)
+    : System(engine) {
+  if (!display_system) error("RenderingSystem needs a valid DisplaySystem.");
+  InitializeOpenGL();
+  InitializeRenderTargets();
+  SetupFramegraph();
+}
 
-void RenderingSystem::Initialize() {
+void RenderingSystem::InitializeOpenGL() {
   if (!gl::initialize()) {
     error("Initializing gl failed");
   }
   std::string prefix = "[RenderingSystem] OpenGl Error: ";
   gl::print_error(prefix.c_str());
-
-  InitializeRenderTargets();
-
-  SetupFramegraph();
 }
 
 void RenderingSystem::InitializeRenderTargets() {
diff --git a/library/phx/rendering_system.hpp b/library/phx/rendering_system.hpp
index 460176d84454308362035cc99cfa87e1202bd284..43ca9b6df6fd09ce363ab4c7e2ee76a73fec3ff7 100644
--- a/library/phx/rendering_system.hpp
+++ b/library/phx/rendering_system.hpp
@@ -28,6 +28,7 @@
 #include <string>
 #include <vector>
 
+#include "phx/display_system.hpp"
 #include "phx/engine.hpp"
 #include "phx/export.hpp"
 #include "phx/frame_graph.hpp"
@@ -45,7 +46,6 @@ class PHOENIX_EXPORT RenderingSystem : public System {
   RenderingSystem(RenderingSystem&&) = default;
   virtual ~RenderingSystem() = default;
 
-  void Initialize() override;
   void Update(const FrameTimer::TimeInfo& time_info) override;
 
   FrameGraph* GetFrameGraph() const;
@@ -58,11 +58,16 @@ class PHOENIX_EXPORT RenderingSystem : public System {
   RenderTarget* GetRightRenderTarget() const;
   RenderTarget* GetLeftRenderTarget() const;
 
+ protected:
+  RenderingSystem(Engine* engine, DisplaySystem* display_system);
+
  private:
+  void InitializeOpenGL();
   void InitializeRenderTargets();
   void SetupFramegraph();
 
-  friend RenderingSystem* Engine::CreateSystem<RenderingSystem>();
+  template <typename SystemType, typename... SystemArguments>
+  friend SystemType* Engine::CreateSystem(SystemArguments&&... arguments);
   explicit RenderingSystem(Engine* engine);
 
   std::unique_ptr<FrameGraph> frame_graph_;
diff --git a/library/phx/setup.cpp b/library/phx/setup.cpp
index 8e0ef78ea41233dca131eb5818ffa6877fe9c379..28773ff4351a4bf94d37bc9ff23b667c470d208c 100644
--- a/library/phx/setup.cpp
+++ b/library/phx/setup.cpp
@@ -45,8 +45,6 @@ std::unique_ptr<Engine> Setup::CreateDefaultEngine() {
   engine->CreateSystem<BehaviorSystem>();
   engine->CreateSystem<InputSystem>()->AddQuitCallback(
       [engine_ptr]() { engine_ptr->Stop(); });
-  engine->CreateSystem<TrackingSystem>();
-  engine->CreateSystem<RenderingSystem>();
 
   auto displaysys = engine->CreateSystem<DisplaySystem>();
   if (HMD::IsHMDPresent()) {
@@ -55,6 +53,8 @@ std::unique_ptr<Engine> Setup::CreateDefaultEngine() {
   } else {
     displaysys->CreateWindow("Phoenix", glm::uvec2(100, 100));
   }
+  engine->CreateSystem<RenderingSystem>(engine->GetSystem<DisplaySystem>());
+  engine->CreateSystem<TrackingSystem>(engine->GetSystem<DisplaySystem>());
 
   return engine;
 }
diff --git a/library/phx/system.hpp b/library/phx/system.hpp
index 6a9ff52d872043c01737ae529794da254225775d..ffdf3b01cba3197b9f29417977be323980aa587b 100644
--- a/library/phx/system.hpp
+++ b/library/phx/system.hpp
@@ -37,9 +37,7 @@ class PHOENIX_EXPORT System : public Loggable {
   System() = delete;
   virtual ~System() = default;
 
-  virtual void Initialize() {}
   virtual void Update(const FrameTimer::TimeInfo&) {}
-  virtual void Terminate() {}
 
   Engine* GetEngine() const;
 
diff --git a/library/phx/tracking_system.cpp b/library/phx/tracking_system.cpp
index 25562e38ff5eb2481cc63844ecb2d1dfc37cd1d2..ae836ae207255f3163e21681f2e0b1f9b5963a07 100644
--- a/library/phx/tracking_system.cpp
+++ b/library/phx/tracking_system.cpp
@@ -26,14 +26,41 @@
 
 #include "display_system.hpp"
 #include "hmd.hpp"
+#include "logger.hpp"
 #include "projection.hpp"
 #include "runtime_component.hpp"
 #include "transform.hpp"
 
 namespace phx {
-TrackingSystem::TrackingSystem(Engine* engine) : System(engine) {}
 
-void TrackingSystem::Initialize() {
+TrackingSystem::TrackingSystem(Engine* engine, DisplaySystem* display_system)
+    : System(engine) {
+  if (!display_system) error("TrackingSystem needs a valid DisplaySystem.");
+  CreateRuntimeEntities();
+}
+
+void TrackingSystem::Update(const FrameTimer::TimeInfo&) {
+  const auto hmd = engine_->GetSystem<DisplaySystem>()->GetHMD();
+  if (hmd == nullptr) return;
+  hmd->UpdateTrackedDevices();
+  const auto head_transformation = hmd->GetHeadTransformation();
+  hmd_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
+      head_transformation);
+  const auto left_eye_transformation = hmd->GetEyeToHeadMatrix(HMD::LEFT_EYE);
+  left_eye_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
+      left_eye_transformation);
+  const auto right_eye_transformation = hmd->GetEyeToHeadMatrix(HMD::RIGHT_EYE);
+  right_eye_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
+      right_eye_transformation);
+
+  left_controller_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
+      hmd->GetLeftControllerTransformation());
+
+  right_controller_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
+      hmd->GetRightControllerTransformation());
+}
+
+void TrackingSystem::CreateRuntimeEntities() {
   const auto hmd = engine_->GetSystem<DisplaySystem>()->GetHMD();
   if (hmd == nullptr) {
     return;
@@ -48,16 +75,19 @@ void TrackingSystem::Initialize() {
     const auto virtual_platform = virtual_platforms[0];
     const auto virtual_platform_transform =
         virtual_platform->GetFirstComponent<Transform>();
+
     hmd_entity_ = scene->CreateEntity();
     hmd_entity_->AddComponent<RuntimeComponent<HEAD>>();
     auto hmd_transform = hmd_entity_->AddComponent<Transform>();
     hmd_transform->SetParent(virtual_platform_transform);
     left_eye_entity_ = scene->CreateEntity();
+
     left_eye_entity_->AddComponent<RuntimeComponent<LEFT_EYE>>();
     auto left_eye_transform = left_eye_entity_->AddComponent<Transform>();
     left_eye_transform->SetParent(hmd_transform);
     left_eye_entity_->AddComponent<Projection>();
     right_eye_entity_ = scene->CreateEntity();
+
     right_eye_entity_->AddComponent<RuntimeComponent<RIGHT_EYE>>();
     auto right_eye_transform = right_eye_entity_->AddComponent<Transform>();
     right_eye_entity_->AddComponent<Projection>();
@@ -78,32 +108,6 @@ void TrackingSystem::Initialize() {
   }
 }
 
-void TrackingSystem::Update(const FrameTimer::TimeInfo&) {
-  const auto hmd = engine_->GetSystem<DisplaySystem>()->GetHMD();
-  if (hmd == nullptr) {
-    return;
-  }
-  hmd->UpdateTrackedDevices();
-  const auto head_transformation = hmd->GetHeadTransformation();
-  if (hmd_entity_ != nullptr) {
-    hmd_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
-        head_transformation);
-    const auto left_eye_transformation = hmd->GetEyeToHeadMatrix(HMD::LEFT_EYE);
-    left_eye_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
-        left_eye_transformation);
-    const auto right_eye_transformation =
-        hmd->GetEyeToHeadMatrix(HMD::RIGHT_EYE);
-    right_eye_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
-        right_eye_transformation);
-
-    left_controller_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
-        hmd->GetLeftControllerTransformation());
-
-    right_controller_entity_->GetFirstComponent<Transform>()->SetLocalMatrix(
-        hmd->GetRightControllerTransformation());
-  }
-}
-
 std::string TrackingSystem::ToString() const { return "Tracking System"; }
 
 }  // namespace phx
diff --git a/library/phx/tracking_system.hpp b/library/phx/tracking_system.hpp
index f2bdb4a13c8ab0277c1b38868e614358a9966931..4022d7e7f2c28358e62a4d665862f84ea1228751 100644
--- a/library/phx/tracking_system.hpp
+++ b/library/phx/tracking_system.hpp
@@ -25,6 +25,7 @@
 
 #include <string>
 
+#include "phx/display_system.hpp"
 #include "phx/engine.hpp"
 #include "phx/export.hpp"
 #include "phx/system.hpp"
@@ -41,13 +42,18 @@ class PHOENIX_EXPORT TrackingSystem : public System {
   TrackingSystem& operator=(const TrackingSystem&) = delete;
   TrackingSystem& operator=(TrackingSystem&&) = default;
 
-  void Initialize() override;
   void Update(const FrameTimer::TimeInfo&) override;
 
   std::string ToString() const override;
 
+ protected:
+  TrackingSystem(Engine* engine, DisplaySystem* display_system);
+
  private:
-  friend TrackingSystem* Engine::CreateSystem<TrackingSystem>();
+  void CreateRuntimeEntities();
+
+  template <typename SystemType, typename... SystemArguments>
+  friend SystemType* Engine::CreateSystem(SystemArguments&&... arguments);
   explicit TrackingSystem(Engine* engine);
 
   Entity* hmd_entity_ = nullptr;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f8059bb98542556b0de86c5c1c07cb19d7587dac..0c516001fb8a2bb48d0353a54fac5d8469af3628 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -224,7 +224,7 @@ add_mocked_test(test_geometry_pass MOCK_GLEW MOCK_SDL)
 add_mocked_test(test_rendering_system MOCK_GLEW MOCK_SDL)
 add_mocked_test(test_shader MOCK_GLEW)
 add_mocked_test(test_display_system MOCK_SDL)
-add_mocked_test(test_engine MOCK_SDL MOCK_OPENVR)
+add_mocked_test(test_engine MOCK_SDL MOCK_OPENVR MOCK_GLEW)
 add_mocked_test(test_tracking_system MOCK_SDL MOCK_OPENVR)
 
 add_mocked_test(integration_test_model_rendering MOCK_OPENVR)
diff --git a/tests/src/integration_test_model_rendering.cpp b/tests/src/integration_test_model_rendering.cpp
index dd782b0085de13d2e5c8cb1078f5b2259c3899a7..f4d4a601534826ecb357afdc8f5619d314b65221 100644
--- a/tests/src/integration_test_model_rendering.cpp
+++ b/tests/src/integration_test_model_rendering.cpp
@@ -114,7 +114,6 @@ SCENARIO(
     auto display_system = engine->GetSystem<phx::DisplaySystem>();
 
     WHEN("We render the scene") {
-      rendering_system->Initialize();
       rendering_system->Update(phx::FrameTimer::TimeInfo());
       display_system->Update(phx::FrameTimer::TimeInfo());
       THEN("the rendering matches our reference image") {
@@ -144,7 +143,6 @@ SCENARIO(
     auto display_system = engine->GetSystem<phx::DisplaySystem>();
 
     WHEN("We render the scene") {
-      rendering_system->Initialize();
       rendering_system->Update(phx::FrameTimer::TimeInfo{});
       display_system->Update(phx::FrameTimer::TimeInfo());
       THEN("the rendering matches our reference image") {
diff --git a/tests/src/integration_test_rendering.cpp b/tests/src/integration_test_rendering.cpp
index a6a3ad0ede817e24eb6e533cb0807a63dc378dc4..a4f6257c7c158ce19978f7480c0aa13d0062f89d 100644
--- a/tests/src/integration_test_rendering.cpp
+++ b/tests/src/integration_test_rendering.cpp
@@ -117,7 +117,6 @@ SCENARIO("We can render a simple triangle", "[phx][phx::Rendering]") {
     material_handle->SetMaterialProxy(material_proxy);
 
     WHEN("We render the scene") {
-      rendering_system->Initialize();
       rendering_system->Update(phx::FrameTimer::TimeInfo{});
       display_system->Update(phx::FrameTimer::TimeInfo{});
       THEN("the rendering matches our reference image") {
@@ -148,7 +147,6 @@ SCENARIO("If no material given a default red one is taken.",
     phx::Transform* transform = triangle->AddComponent<phx::Transform>();
 
     WHEN("We render the scene") {
-      rendering_system->Initialize();
       rendering_system->Update(phx::FrameTimer::TimeInfo{});
       display_system->Update(phx::FrameTimer::TimeInfo{});
       THEN("the rendering matches our reference image") {
diff --git a/tests/src/test_display_system.cpp b/tests/src/test_display_system.cpp
index a896603b84d89f0c8b089b757cf11d0107f79f98..5c7e6b07219fc8858c4c319cd2e456f06c833d2a 100644
--- a/tests/src/test_display_system.cpp
+++ b/tests/src/test_display_system.cpp
@@ -52,8 +52,9 @@ SCENARIO(
         "scope.") {
       REQUIRE_CALL(sdl_mock.Get(), SDL_VideoInit(nullptr)).RETURN(0);
       REQUIRE_CALL(sdl_mock.Get(), SDL_VideoQuit());
-      phx::DisplaySystem displaySystem(nullptr);
-      displaySystem.Initialize();
+      phx::Engine engine;
+      phx::DisplaySystem* displaySystem =
+          engine.CreateSystem<phx::DisplaySystem>();
 
       WHEN("We create a window.") {
         THEN("The window is created.") {
@@ -71,13 +72,13 @@ SCENARIO(
               .RETURN(0);
           REQUIRE_CALL(sdl_mock.Get(), SDL_GL_CreateContext(_))
               .RETURN(reinterpret_cast<SDL_GLContext>(1u));
-          displaySystem.CreateWindow("TestWindow", glm::uvec2(0, 0),
-                                     glm::uvec2(640, 480));
+          displaySystem->CreateWindow("TestWindow", glm::uvec2(0, 0),
+                                      glm::uvec2(640, 480));
 
           WHEN("DisplaySystem Update is called") {
             THEN("SDL_GL_SwapWindow is called") {
               REQUIRE_CALL(sdl_mock.Get(), SDL_GL_SwapWindow(_));
-              displaySystem.Update(phx::FrameTimer::TimeInfo());
+              displaySystem->Update(phx::FrameTimer::TimeInfo());
             }
           }
         }
diff --git a/tests/src/test_engine.cpp b/tests/src/test_engine.cpp
index 6281651a5b4cd384b5b131d2363ce46dc83847be..3256e671385c5be1d8f79da1df7c43b876786ea3 100644
--- a/tests/src/test_engine.cpp
+++ b/tests/src/test_engine.cpp
@@ -43,6 +43,7 @@ SUPPRESS_WARNINGS_BEGIN
 #include "mocks/openvr_mock.hpp"
 SUPPRESS_WARNINGS_END
 #include "mocks/sdl_mock.hpp"
+#include "mocks/opengl_mock.hpp"
 
 using trompeloeil::_;
 using trompeloeil::ne;
@@ -278,6 +279,7 @@ SCENARIO("An engine provides access to the behaviors", "[phx][phx::Engine]") {
 
 SCENARIO("An engine can be setup by the default setup", "[phx][phx::Engine]") {
   SDL_MOCK_ALLOW_ANY_CALL
+  OPENGL_MOCK_ALLOW_ANY_CALL
   ALLOW_CALL(openvr_mock.Get(), VR_IsHmdPresent()).RETURN(false);
   GIVEN("Nothing") {
     WHEN("An engine is setup with the default setup") {
diff --git a/tests/src/test_rendering_system.cpp b/tests/src/test_rendering_system.cpp
index d86db1bf4ba9b7b1857e25d29340f7bb068c4667..4c83660c7f36a14b96d0264636bdf7294d8c2cbd 100644
--- a/tests/src/test_rendering_system.cpp
+++ b/tests/src/test_rendering_system.cpp
@@ -48,11 +48,11 @@ SCENARIO(
   phx::Engine engine;
 
   GIVEN("A rendering system.") {
+    auto diplay_system = engine.CreateSystem<phx::DisplaySystem>();
     phx::RenderingSystem* rendering_system =
-        engine.CreateSystem<phx::RenderingSystem>();
+        engine.CreateSystem<phx::RenderingSystem>(diplay_system);
 
     WHEN("We initialize the system") {
-      rendering_system->Initialize();
       THEN(
           "a default frame graph is created, that has 0 render passes, "
           "since there is currently to much inter-relation between the "
diff --git a/tests/src/test_tracking_system.cpp b/tests/src/test_tracking_system.cpp
index b1e688d45c10a67016824729ff1d5bd6e9e49fa1..ea6f58a16e8e944ec443a99d475d82d88192aeff 100644
--- a/tests/src/test_tracking_system.cpp
+++ b/tests/src/test_tracking_system.cpp
@@ -81,8 +81,8 @@ SCENARIO(
         ->GetFirstComponent<phx::Transform>()
         ->SetLocalMatrix(platform_trans_mat);
     WHEN("A tracking system is created and initialized.") {
-      auto tracking_system = engine.CreateSystem<phx::TrackingSystem>();
-      tracking_system->Initialize();
+      auto tracking_system =
+          engine.CreateSystem<phx::TrackingSystem>(display_system);
       THEN("The HMD and the user's eyes are represented in the scene.") {
         auto entities = scene->GetEntitiesWithComponents<phx::Transform>();
         bool platform_present = false;