diff --git a/demos/viewer/src/viewer.cpp b/demos/viewer/src/viewer.cpp
index 8a56e775a46169762abd795adc649d41b1a78472..358ba7fa1a55321e6520258f4e8db36726fa35ee 100644
--- a/demos/viewer/src/viewer.cpp
+++ b/demos/viewer/src/viewer.cpp
@@ -115,15 +115,17 @@ int main(int, char**) {
 
   virtual_platform_transform->SetLocalTranslation(glm::vec3(0.f, -1.f, -2.f));
 
-  phx::Entity* camera = scene->CreateEntity();
-  auto camera_transform = camera->AddComponent<phx::Transform>();
-  auto camera_projection = camera->AddComponent<phx::Projection>();
-  camera->AddComponent<NavigationBehavior>(
-      engine->GetSystem<phx::DisplaySystemOpenVR>());
-  camera_projection->SetPerspective(glm::radians(68.0f), 4.0f / 3.0f, 0.01f,
-                                    1000.0f);
-  camera_transform->SetLocalTranslation(glm::vec3(0, 0, 0));
-  camera_transform->SetParent(virtual_platform_transform, false);
+  phx::Entity* camera =
+      scene->GetEntitiesWithComponents<phx::RenderTarget>()[0];
+  if (camera->GetFirstComponent<phx::RuntimeComponent<phx::LEFT_EYE>>() ==
+          nullptr &&
+      camera->GetFirstComponent<phx::RuntimeComponent<phx::RIGHT_EYE>>() ==
+          nullptr) {
+    auto camera_projection = camera->GetFirstComponent<phx::Projection>();
+    camera_projection->SetPerspective(glm::radians(68.0f), 4.0f / 3.0f, 0.01f,
+                                      1000.0f);
+  }
+
   auto virtual_platform = scene->GetEntitiesWithComponents<
       phx::RuntimeComponent<phx::USER_PLATFORM>>()[0];
   virtual_platform->AddComponent<NavigationBehavior>(
diff --git a/library/phx/display_system.hpp b/library/phx/display_system.hpp
index 98b84f3ceb0a433000582e059730885a7e00bb47..08e2d36364fc6747c9cb8d2605b45e990ebeaa9d 100644
--- a/library/phx/display_system.hpp
+++ b/library/phx/display_system.hpp
@@ -44,8 +44,6 @@ class PHOENIX_EXPORT DisplaySystem : public System {
 
   void Update(const FrameTimer::TimeInfo&) override = 0;
 
-  virtual std::vector<std::unique_ptr<RenderTarget>> CreateRenderTargets() = 0;
-
  protected:
   explicit DisplaySystem(Engine* engine);
   friend DisplaySystem* Engine::CreateSystem<DisplaySystem>();
diff --git a/library/phx/display_system_openvr.cpp b/library/phx/display_system_openvr.cpp
index a51efa182b4c6e1eb9b26e863397b55578a454fe..7938a3fce7112a3c5791d209b315c3d5fc4b616e 100644
--- a/library/phx/display_system_openvr.cpp
+++ b/library/phx/display_system_openvr.cpp
@@ -29,14 +29,25 @@
 #include <utility>
 #include <vector>
 
+#include "engine.hpp"
 #include "logger.hpp"
 #include "rendering_system.hpp"
+#include "runtime_component.hpp"
+#include "scene.hpp"
 
 #undef CreateWindow
 
 namespace phx {
 DisplaySystemOpenVR::DisplaySystemOpenVR(Engine* engine)
-    : DisplaySystem(engine) {}
+    : DisplaySystem(engine),
+      left_render_target_(nullptr),
+      right_render_target_(nullptr) {
+  scene_changed_connection_ = engine->AddSceneChangedCallback(
+      [this](std::shared_ptr<Scene>, std::shared_ptr<Scene> new_scene) {
+        RemoveRenderTargets();
+        CreateRenderTargets(new_scene.get());
+      });
+}
 DisplaySystemOpenVR::~DisplaySystemOpenVR() {}
 
 phx::HMD* DisplaySystemOpenVR::CreateHMD() {
@@ -56,32 +67,59 @@ phx::HMD* DisplaySystemOpenVR::GetHMD() { return hmd_.get(); }
 
 void DisplaySystemOpenVR::Update(const FrameTimer::TimeInfo&) {
   if (hmd_ != nullptr) {
-    auto rendering_system = engine_->GetSystem<RenderingSystem>();
-    if (rendering_system != nullptr) {
-      auto render_targets = rendering_system->GetRenderTargets();
-      if (render_targets.size() >= 2) {
-        auto right_texture = render_targets[0]->GetColorTexture();
-        hmd_->Submit(HMD::RIGHT_EYE, right_texture);
-        auto left_texture = render_targets[1]->GetColorTexture();
-        hmd_->Submit(HMD::LEFT_EYE, left_texture);
-      }
+    if (left_render_target_ != nullptr && right_render_target_ != nullptr) {
+      auto right_texture = right_render_target_->GetColorTexture();
+      hmd_->Submit(HMD::RIGHT_EYE, right_texture);
+      auto left_texture = left_render_target_->GetColorTexture();
+      hmd_->Submit(HMD::LEFT_EYE, left_texture);
     }
   }
 }
 
-std::vector<std::unique_ptr<RenderTarget>>
-DisplaySystemOpenVR::CreateRenderTargets() {
-  std::vector<std::unique_ptr<RenderTarget>> render_targets;
+void DisplaySystemOpenVR::CreateRenderTargets(Scene* scene) {
   if (GetHMD() == nullptr) {
     error("Cannot create render targets: no HMD.");
-    return render_targets;
+    return;
+  }
+  auto left_eye_components =
+      scene->GetEntitiesWithComponents<RuntimeComponent<LEFT_EYE>>();
+  if (!left_eye_components.empty()) {
+    left_render_target_ = left_eye_components[0]->AddComponent<RenderTarget>(
+        GetHMD()->GetViewportSize());
+  }
+  auto right_eye_components =
+      scene->GetEntitiesWithComponents<RuntimeComponent<RIGHT_EYE>>();
+  if (!right_eye_components.empty()) {
+    right_render_target_ = right_eye_components[0]->AddComponent<RenderTarget>(
+        GetHMD()->GetViewportSize());
   }
+  SetEyeProjections(scene);
+}
+
+void DisplaySystemOpenVR::RemoveRenderTargets() {
+  if (left_render_target_)
+    left_render_target_->GetEntity()->RemoveComponent(left_render_target_);
+  if (right_render_target_)
+    right_render_target_->GetEntity()->RemoveComponent(right_render_target_);
+}
 
-  render_targets.push_back(
-      std::make_unique<RenderTarget>(GetHMD()->GetViewportSize()));
-  render_targets.push_back(
-      std::make_unique<RenderTarget>(GetHMD()->GetViewportSize()));
-  return render_targets;
+void DisplaySystemOpenVR::SetEyeProjections(Scene* scene) {
+  if (GetHMD() == nullptr) {
+    error("Cannot set eye projections: no HMD.");
+    return;
+  }
+  auto left_eye_components =
+      scene->GetEntitiesWithComponents<RuntimeComponent<LEFT_EYE>>();
+  if (!left_eye_components.empty()) {
+    left_eye_components[0]->GetFirstComponent<Projection>()->SetMatrix(
+        GetHMD()->GetProjectionMatrix(HMD::LEFT_EYE));
+  }
+  auto right_eye_components =
+      scene->GetEntitiesWithComponents<RuntimeComponent<RIGHT_EYE>>();
+  if (!right_eye_components.empty()) {
+    right_eye_components[0]->GetFirstComponent<Projection>()->SetMatrix(
+        GetHMD()->GetProjectionMatrix(HMD::RIGHT_EYE));
+  }
 }
 
 }  // namespace phx
diff --git a/library/phx/display_system_openvr.hpp b/library/phx/display_system_openvr.hpp
index 8e0962cc327aa78984354bc48b5630f078723cbb..389c6e41dff4208bacd729bc1d63941f0180faaa 100644
--- a/library/phx/display_system_openvr.hpp
+++ b/library/phx/display_system_openvr.hpp
@@ -29,6 +29,8 @@
 #include "phx/display_system.hpp"
 #include "phx/export.hpp"
 #include "phx/hmd.hpp"
+#include "phx/render_target.hpp"
+#include "phx/scene.hpp"
 #include "phx/window.hpp"
 
 namespace phx {
@@ -49,10 +51,19 @@ class PHOENIX_EXPORT DisplaySystemOpenVR : public DisplaySystem {
 
   void Update(const FrameTimer::TimeInfo&) override;
 
-  std::vector<std::unique_ptr<RenderTarget>> CreateRenderTargets() override;
+  void CreateRenderTargets(Scene* scene);
 
  protected:
   std::unique_ptr<HMD> hmd_;
+
+ private:
+  void RemoveRenderTargets();
+  void SetEyeProjections(Scene* scene);
+
+  boost::signals2::connection scene_changed_connection_;
+
+  RenderTarget* left_render_target_;
+  RenderTarget* right_render_target_;
 };
 
 }  // namespace phx
diff --git a/library/phx/display_system_window.cpp b/library/phx/display_system_window.cpp
index d68c4d7f453c12a1b13afb1a3520e691ee03c472..095f56d72197328a03dbd26bfd21ba74abf3350a 100644
--- a/library/phx/display_system_window.cpp
+++ b/library/phx/display_system_window.cpp
@@ -48,18 +48,9 @@ DisplaySystemWindow::~DisplaySystemWindow() { SDL_VideoQuit(); }
 
 void DisplaySystemWindow::DestroyWindow() {
   window_.reset();
-  /*windows_.erase(
-      std::remove_if(windows_.begin(), windows_.end(),
-                     [window](const std::unique_ptr<Window>& iteratee) {
-                       return window == iteratee.get();
-                     }));*/
 }
 
 Window* DisplaySystemWindow::GetWindow() {
-  /*std::vector<Window*> windows(windows_.size());
-  std::transform(
-      windows_.begin(), windows_.end(), windows.begin(),
-      [](const std::unique_ptr<Window>& iteratee) { return iteratee.get(); });*/
   return window_.get();
 }
 
@@ -69,17 +60,4 @@ void DisplaySystemWindow::Update(const FrameTimer::TimeInfo&) {
   }
 }
 
-std::vector<std::unique_ptr<RenderTarget>>
-DisplaySystemWindow::CreateRenderTargets() {
-  std::vector<std::unique_ptr<RenderTarget>> render_targets;
-  if (GetWindow() == nullptr) {
-    error("Cannot create render target: no window.");
-    return render_targets;
-  }
-
-  render_targets.push_back(
-      std::make_unique<RenderTarget>(GetWindow()->GetSize()));
-  return render_targets;
-}
-
 }  // namespace phx
diff --git a/library/phx/display_system_window.hpp b/library/phx/display_system_window.hpp
index 8abfcee03022c9af1d00355b788690bfbf9ffd55..024c34de643bb5ef6fccc1e82688b435541585f9 100644
--- a/library/phx/display_system_window.hpp
+++ b/library/phx/display_system_window.hpp
@@ -52,8 +52,6 @@ class PHOENIX_EXPORT DisplaySystemWindow : public DisplaySystem {
 
   void Update(const FrameTimer::TimeInfo&) override;
 
-  std::vector<std::unique_ptr<RenderTarget>> CreateRenderTargets() override;
-
  protected:
   std::unique_ptr<Window> window_;
 };
diff --git a/library/phx/entity.hpp b/library/phx/entity.hpp
index d590575e7e1cf6a67d5d0228f8619df9b42a903b..7d9b7939bac276a32122c4fa11ca2ac6fb2141fb 100644
--- a/library/phx/entity.hpp
+++ b/library/phx/entity.hpp
@@ -52,8 +52,8 @@ class PHOENIX_EXPORT Entity : public Nameable, public Loggable {
   Entity& operator=(const Entity&) = delete;
   Entity& operator=(Entity&&) = default;
 
-  template <class ComponentType, class... ArgumentTypes>
-  ComponentType* AddComponent(ArgumentTypes&&... arguments) {
+  template <class ComponentType, typename... ComponentArguments>
+  ComponentType* AddComponent(ComponentArguments&&... arguments) {
     static_assert(std::is_base_of<phx::Component, ComponentType>::value,
                   "ComponentType is not derived from phx::Component.");
     auto component_ptr = new ComponentType(arguments...);
diff --git a/library/phx/projection.cpp b/library/phx/projection.cpp
index 9ec2b2bb1c76a2d3a9fd304dee52405428c37db8..81713abd912bc564b7a0615a738cfcc05e7a052c 100644
--- a/library/phx/projection.cpp
+++ b/library/phx/projection.cpp
@@ -46,6 +46,8 @@ void Projection::SetOrthogonal(float left, float right, float bottom, float top,
   matrix_ = glm::ortho(left, right, bottom, top, near, far);
 }
 
+void Projection::SetMatrix(const glm::mat4& matrix) { matrix_ = matrix; }
+
 std::string Projection::ToString() const { return "ProjectionComponent"; }
 
 }  // namespace phx
diff --git a/library/phx/projection.hpp b/library/phx/projection.hpp
index c24e22ba8ccba2e843b922621ba99f6f93c13724..17671b52416f0bdda621d5f711670fd7f955a2b9 100644
--- a/library/phx/projection.hpp
+++ b/library/phx/projection.hpp
@@ -44,6 +44,7 @@ class PHOENIX_EXPORT Projection final : public Component {
 
   void SetOrthogonal(float left, float right, float bottom, float top,
                      float near, float far);
+  void SetMatrix(const glm::mat4& matrix);
 
   std::string ToString() const override;
 
diff --git a/library/phx/render_target.cpp b/library/phx/render_target.cpp
index 1bfe7ade23e5f7174496529de1cc7c2862ce83a3..02008a7d97e3072cb6c1a7a42ebb34edc9393210 100644
--- a/library/phx/render_target.cpp
+++ b/library/phx/render_target.cpp
@@ -27,7 +27,10 @@
 #include "gl/command_execution.hpp"
 #include "gl/viewport.hpp"
 
+#include "phx/entity.hpp"
 #include "phx/logger.hpp"
+#include "phx/projection.hpp"
+#include "phx/transform.hpp"
 
 namespace phx {
 phx::RenderTarget::RenderTarget(const glm::uvec2 dimensions)
@@ -65,18 +68,32 @@ phx::RenderTarget::RenderTarget(const glm::uvec2 dimensions)
 
 const glm::uvec2& RenderTarget::GetDimensions() const { return dimensions_; }
 
-const glm::mat4& RenderTarget::GetProjection() const { return projection_; }
-
-void RenderTarget::SetProjection(const glm::mat4& matrix) {
-  projection_ = matrix;
+gl::texture_2d* RenderTarget::GetColorTexture() const {
+  return color_texture_.get();
 }
 
-const glm::mat4& RenderTarget::GetView() const { return view_; }
-
-void RenderTarget::SetView(const glm::mat4& matrix) { view_ = matrix; }
+const glm::mat4 RenderTarget::GetProjection() const {
+  auto projection = GetEntity()->GetFirstComponent<Projection>();
+  if (projection) {
+    return projection->GetMatrix();
+  } else {
+    error(
+        "RenderTarget component may not be added to an Entity without a "
+        "Projection component!");
+    return glm::mat4();
+  }
+}
 
-gl::texture_2d* RenderTarget::GetColorTexture() const {
-  return color_texture_.get();
+const glm::mat4 RenderTarget::GetView() const {
+  auto transform = GetEntity()->GetFirstComponent<Transform>();
+  if (transform) {
+    return inverse(transform->GetGlobalMatrix());
+  } else {
+    error(
+        "RenderTarget component may not be added to an Entity without a "
+        "Transform component!");
+    return glm::mat4();
+  }
 }
 
 void RenderTarget::SetViewport() const {
diff --git a/library/phx/render_target.hpp b/library/phx/render_target.hpp
index a8ca89bb3e1c15ca7e3b03eabfb2d81bf768b344..f441a947c7a32e831d353f1078bfd6b986bf2d28 100644
--- a/library/phx/render_target.hpp
+++ b/library/phx/render_target.hpp
@@ -38,13 +38,15 @@ SUPPRESS_WARNINGS_END
 #include "gl/renderbuffer.hpp"
 #include "gl/texture.hpp"
 
+#include "phx/component.hpp"
 #include "phx/export.hpp"
 
 namespace phx {
 
 SUPPRESS_WARNINGS_BEGIN_PADDED
-class PHOENIX_EXPORT RenderTarget : public gl::framebuffer {
+class PHOENIX_EXPORT RenderTarget : public Component, public gl::framebuffer {
  public:
+  RenderTarget() = delete;
   explicit RenderTarget(const glm::uvec2 dimensions);
   RenderTarget(RenderTarget&) = delete;
   RenderTarget(RenderTarget&&) = default;
@@ -54,15 +56,11 @@ class PHOENIX_EXPORT RenderTarget : public gl::framebuffer {
   RenderTarget& operator=(RenderTarget&&) = default;
 
   const glm::uvec2& GetDimensions() const;
-
-  const glm::mat4& GetProjection() const;
-  void SetProjection(const glm::mat4& matrix);
-
-  const glm::mat4& GetView() const;
-  void SetView(const glm::mat4& matrix);
-
   gl::texture_2d* GetColorTexture() const;
 
+  const glm::mat4 GetProjection() const;
+  const glm::mat4 GetView() const;
+
   void SetViewport() const;
 
  private:
@@ -70,8 +68,6 @@ class PHOENIX_EXPORT RenderTarget : public gl::framebuffer {
   std::unique_ptr<gl::texture_2d> depth_texture_;
 
   glm::uvec2 dimensions_;
-  glm::mat4 projection_;
-  glm::mat4 view_;
 };
 SUPPRESS_WARNINGS_END
 
diff --git a/library/phx/rendering_system.cpp b/library/phx/rendering_system.cpp
index 45d55f276d7a08076cb91a6274c69c4fb5819544..b403cbecc009abe26a32c6b1efd303ffcf73489c 100644
--- a/library/phx/rendering_system.cpp
+++ b/library/phx/rendering_system.cpp
@@ -29,10 +29,6 @@
 #include <utility>
 #include <vector>
 
-#include "blit_pass.hpp"
-#include "clear_pass.hpp"
-#include "display_system_openvr.hpp"
-#include "display_system_window.hpp"
 #include "engine.hpp"
 #include "light.hpp"
 #include "logger.hpp"
@@ -73,42 +69,14 @@ void RenderingSystem::SetupFramegraph() {
 void RenderingSystem::Update(const FrameTimer::TimeInfo&) {
   std::vector<GeometryPass::RenderingInstance> rendering_instances;
   std::vector<std::pair<Light*, Transform*>> light_transform_pairs;
-  std::vector<std::pair<Projection*, Transform*>> projection_transform_pairs;
 
   if (GetEngine()->GetScene() == nullptr) {
     return;
   }
-  if (render_targets_.empty()) {
-    return;
-  }
-
-  const auto display_system_window = engine_->GetSystem<DisplaySystemWindow>();
-  const auto display_system_hmd = engine_->GetSystem<DisplaySystemOpenVR>();
-
-  // @TODO(anyone): these render parameters should be extracted from the scene
-  // somehow, the RenderingSystem shouldn't have to know about this.
-  if (display_system_hmd != nullptr && render_targets_.size() >= 2) {
-    auto right_eye_entities =
-        GetEngine()->GetEntitiesWithComponents<RuntimeComponent<RIGHT_EYE>>();
-    if (!right_eye_entities.empty()) {
-      render_targets_[0]->SetView(inverse(right_eye_entities[0]
-                                              ->GetFirstComponent<Transform>()
-                                              ->GetGlobalMatrix()));
-    }
-
-    auto left_eye_entities =
-        GetEngine()->GetEntitiesWithComponents<RuntimeComponent<LEFT_EYE>>();
-    if (!left_eye_entities.empty()) {
-      render_targets_[1]->SetView(inverse(left_eye_entities[0]
-                                              ->GetFirstComponent<Transform>()
-                                              ->GetGlobalMatrix()));
-    }
-  }
 
   for (auto& entity : GetEngine()->GetEntities()) {
     auto mesh_handle = entity->GetFirstComponent<MeshHandle>();
     auto light = entity->GetFirstComponent<Light>();
-    auto projection = entity->GetFirstComponent<Projection>();
     auto transform = entity->GetFirstComponent<Transform>();
     auto material_handle = entity->GetFirstComponent<MaterialHandle>();
     if (transform != nullptr) {
@@ -121,34 +89,15 @@ void RenderingSystem::Update(const FrameTimer::TimeInfo&) {
       } else if (light != nullptr) {
         light_transform_pairs.push_back(
             std::pair<Light*, Transform*>(light, transform));
-      } else if (projection != nullptr) {
-        projection_transform_pairs.push_back(
-            std::pair<Projection*, Transform*>(projection, transform));
       }
     }
   }
+
   auto geometry_passes = frame_graph_->GetRenderPasses<GeometryPass>();
   for (auto geometry_pass : geometry_passes) {
     geometry_pass->SetData(rendering_instances, light_transform_pairs);
   }
 
-  // @TODO(anyone) see above, should also not be in the RenderingSystem, but
-  // the scene (Camera?) should store the connection between render target
-  // and Camera
-  if (display_system_hmd != nullptr && render_targets_.size() >= 2) {
-    HMD* hmd = display_system_hmd->GetHMD();
-    render_targets_[0]->SetProjection(hmd->GetProjectionMatrix(HMD::RIGHT_EYE));
-    render_targets_[1]->SetProjection(hmd->GetProjectionMatrix(HMD::LEFT_EYE));
-  }
-
-  if (display_system_hmd == nullptr && display_system_window != nullptr &&
-      !render_targets_.empty() && !projection_transform_pairs.empty()) {
-    render_targets_[0]->SetProjection(
-        projection_transform_pairs[0].first->GetMatrix());
-    render_targets_[0]->SetView(
-        glm::inverse(projection_transform_pairs[0].second->GetGlobalMatrix()));
-  }
-
   frame_graph_->Execute();
 }
 
@@ -165,18 +114,4 @@ std::string RenderingSystem::ToString() const {
          std::to_string(frame_graph_->GetNumberOfPasses());
 }
 
-void RenderingSystem::SetRenderTargets(
-    std::vector<std::unique_ptr<RenderTarget>>* render_targets) {
-  render_targets_ = std::move(*render_targets);
-}
-
-std::vector<RenderTarget*> RenderingSystem::GetRenderTargets() const {
-  std::vector<RenderTarget*> render_targets;
-  std::transform(
-      render_targets_.begin(), render_targets_.end(),
-      std::back_inserter(render_targets),
-      [](const std::unique_ptr<RenderTarget>& ptr) { return ptr.get(); });
-  return render_targets;
-}
-
 }  // namespace phx
diff --git a/library/phx/rendering_system.hpp b/library/phx/rendering_system.hpp
index 886f321b624c15f9b0859086ff2e96c7898fea23..40da48362089f540ebadc82d309a3f3e9874041c 100644
--- a/library/phx/rendering_system.hpp
+++ b/library/phx/rendering_system.hpp
@@ -56,10 +56,6 @@ class PHOENIX_EXPORT RenderingSystem : public System {
   RenderingSystem& operator=(const RenderingSystem&) = delete;
   RenderingSystem& operator=(RenderingSystem&&) = default;
 
-  void SetRenderTargets(
-      std::vector<std::unique_ptr<RenderTarget>>* render_targets);
-  std::vector<RenderTarget*> GetRenderTargets() const;
-
  protected:
   template <typename SystemType, typename... SystemArguments>
   friend SystemType* Engine::CreateSystem(SystemArguments&&... arguments);
@@ -70,8 +66,6 @@ class PHOENIX_EXPORT RenderingSystem : public System {
   void SetupFramegraph();
 
   std::unique_ptr<FrameGraph> frame_graph_;
-
-  std::vector<std::unique_ptr<RenderTarget>> render_targets_;
 };
 
 }  // namespace phx
diff --git a/library/phx/setup.cpp b/library/phx/setup.cpp
index c20a35426e13877be9e19531e378d0d92e81f3a2..0d5ff27d4693e93541dc5380ecff61f6da41fe47 100644
--- a/library/phx/setup.cpp
+++ b/library/phx/setup.cpp
@@ -30,6 +30,7 @@
 #include "behavior_system.hpp"
 #include "blit_pass.hpp"
 #include "clear_pass.hpp"
+#include "component.hpp"
 #include "display_system_openvr.hpp"
 #include "display_system_window.hpp"
 #include "engine.hpp"
@@ -39,6 +40,8 @@
 #include "openvr_controller_system.hpp"
 #include "render_target.hpp"
 #include "rendering_system.hpp"
+#include "runtime_component.hpp"
+#include "scene.hpp"
 #include "tracking_system_openvr.hpp"
 
 #undef CreateWindow
@@ -80,61 +83,79 @@ std::unique_ptr<Engine> Setup::CreateDefaultEngine() {
 
   // setup rendering and frame graph
   if (using_hmd) {
-    // we need the render targets of the DisplaySystemOpenVR, but the
-    // DisplaySystemWindow only exists for blitting the result of the left eye
-    // into the window and does not create a render target themselves
-    auto render_targets = displaysys_hmd->CreateRenderTargets();
-    rendering_system->SetRenderTargets(&render_targets);
-    SetupDefaultFrameGraphOpenVR(rendering_system);
     auto tracking_system =
         engine->CreateSystem<TrackingSystemOpenVR>(displaysys_hmd);
     auto controller_system = engine->CreateSystem<OpenVRControllerSystem>(
         engine->GetSystem<DisplaySystem>());
+
+    displaysys_hmd->CreateRenderTargets(engine->GetScene().get());
+    SetupDefaultFrameGraphOpenVR(rendering_system, engine.get());
+
     engine->MoveSystemBefore(tracking_system, rendering_system);
     engine->MoveSystemAfter(behavior_system, tracking_system);
     engine->MoveSystemAfter(controller_system, tracking_system);
   } else {
-    auto render_targets = displaysys_window->CreateRenderTargets();
-    rendering_system->SetRenderTargets(&render_targets);
-    SetupDefaultFrameGraphWindow(rendering_system);
+    // TODO(@ALL): This should not be done here.
+    Entity* platform =
+        engine->GetScene()
+            ->GetEntitiesWithComponents<RuntimeComponent<USER_PLATFORM>>()[0];
+    Entity* camera = engine->GetScene()->CreateEntity();
+    camera->AddComponent<Transform>()->SetParent(
+        platform->GetFirstComponent<Transform>());
+    camera->AddComponent<Projection>();
+    camera->AddComponent<RenderTarget>(window_size);
+    SetupDefaultFrameGraphWindow(rendering_system, engine.get());
   }
 
   return engine;
 }
 
-void Setup::SetupDefaultFrameGraphWindow(RenderingSystem* rendering_system) {
+void Setup::SetupDefaultFrameGraphWindow(RenderingSystem* rendering_system,
+                                         Engine* engine) {
   auto frame_graph = std::make_unique<FrameGraph>();
-  auto render_targets = rendering_system->GetRenderTargets();
-  if (render_targets.empty()) {
+  auto render_target = engine->GetScene()
+                           ->GetEntitiesWithComponents<RenderTarget>()[0]
+                           ->GetFirstComponent<RenderTarget>();
+  if (!render_target) {
     error("Cannot setup default frame graph (window): no render targets.");
     return;
   }
 
-  frame_graph->AddRenderPass(std::make_unique<ClearPass>(render_targets[0]));
-  frame_graph->AddRenderPass(std::make_unique<GeometryPass>(render_targets[0]));
-  frame_graph->AddRenderPass(std::make_unique<BlitPass>(render_targets[0]));
+  frame_graph->AddRenderPass(std::make_unique<ClearPass>(render_target));
+  frame_graph->AddRenderPass(std::make_unique<GeometryPass>(render_target));
+  frame_graph->AddRenderPass(std::make_unique<BlitPass>(render_target));
 
   frame_graph->Initialize();
 
   rendering_system->SetFrameGraph(std::move(frame_graph));
 }
 
-void Setup::SetupDefaultFrameGraphOpenVR(RenderingSystem* rendering_system) {
+void Setup::SetupDefaultFrameGraphOpenVR(RenderingSystem* rendering_system,
+                                         Engine* engine) {
   auto frame_graph = std::make_unique<FrameGraph>();
-  auto render_targets = rendering_system->GetRenderTargets();
-  if (render_targets.size() < 2) {
+  auto left_render_target =
+      engine->GetScene()
+          ->GetEntitiesWithComponents<RuntimeComponent<LEFT_EYE>>()[0]
+          ->GetFirstComponent<RenderTarget>();
+  auto right_render_target =
+      engine->GetScene()
+          ->GetEntitiesWithComponents<RuntimeComponent<RIGHT_EYE>>()[0]
+          ->GetFirstComponent<RenderTarget>();
+  if (!left_render_target || !right_render_target) {
     error(
         "Cannot setup default frame graph (OpenVR): not enough render "
         "targets.");
     return;
   }
 
-  frame_graph->AddRenderPass(std::make_unique<ClearPass>(render_targets[0]));
-  frame_graph->AddRenderPass(std::make_unique<ClearPass>(render_targets[1]));
-  frame_graph->AddRenderPass(std::make_unique<GeometryPass>(render_targets[0]));
-  frame_graph->AddRenderPass(std::make_unique<GeometryPass>(render_targets[1]));
+  frame_graph->AddRenderPass(std::make_unique<ClearPass>(right_render_target));
+  frame_graph->AddRenderPass(std::make_unique<ClearPass>(left_render_target));
+  frame_graph->AddRenderPass(
+      std::make_unique<GeometryPass>(right_render_target));
+  frame_graph->AddRenderPass(
+      std::make_unique<GeometryPass>(left_render_target));
 
-  frame_graph->AddRenderPass(std::make_unique<BlitPass>(render_targets[0]));
+  frame_graph->AddRenderPass(std::make_unique<BlitPass>(right_render_target));
 
   frame_graph->Initialize();
 
diff --git a/library/phx/setup.hpp b/library/phx/setup.hpp
index c5fb4a7496c2990dc871484eb020e0c22c0b437b..ee37cf4cf9b4712479652c1d5aa2716bf5b29343 100644
--- a/library/phx/setup.hpp
+++ b/library/phx/setup.hpp
@@ -43,8 +43,10 @@ class PHOENIX_EXPORT Setup {
   // also creates an empty scene for the engine
   static std::unique_ptr<Engine> CreateDefaultEngine();
 
-  static void SetupDefaultFrameGraphWindow(RenderingSystem* rendering_system);
-  static void SetupDefaultFrameGraphOpenVR(RenderingSystem* rendering_system);
+  static void SetupDefaultFrameGraphWindow(RenderingSystem* rendering_system,
+                                           Engine* engine);
+  static void SetupDefaultFrameGraphOpenVR(RenderingSystem* rendering_system,
+                                           Engine* engine);
 };
 
 }  // namespace phx
diff --git a/tests/src/integration_test_model_rendering.cpp b/tests/src/integration_test_model_rendering.cpp
index 1dc9ffc83ffbb1e255a8259dca92cce2e1fea930..4b9416dad1fbd4ac028b01a2c67ece54298a56c7 100644
--- a/tests/src/integration_test_model_rendering.cpp
+++ b/tests/src/integration_test_model_rendering.cpp
@@ -90,9 +90,10 @@ void SetupLightAndCamera(phx::Scene* scene) {
   light->SetColor(glm::vec3(1.0f, 1.0f, 1.0f));
   light->SetIntensity(1.0f);
 
-  phx::Entity* camera = scene->CreateEntity();
-  auto camera_transform = camera->AddComponent<phx::Transform>();
-  auto camera_projection = camera->AddComponent<phx::Projection>();
+  phx::Entity* camera =
+      scene->GetEntitiesWithComponents<phx::RenderTarget>()[0];
+  auto camera_transform = camera->GetFirstComponent<phx::Transform>();
+  auto camera_projection = camera->GetFirstComponent<phx::Projection>();
   camera_projection->SetPerspective(glm::radians(68.0f), 4.0f / 3.0f, 0.01f,
                                     1000.0f);
   camera_transform->SetLocalTranslation(glm::vec3(0, 0, -0.3));
diff --git a/tests/src/integration_test_rendering.cpp b/tests/src/integration_test_rendering.cpp
index eeabd149ba5ab97deb604d1ca8c77e9d277b4e5d..fae6373d2b335894e644afe32725def618896dbb 100644
--- a/tests/src/integration_test_rendering.cpp
+++ b/tests/src/integration_test_rendering.cpp
@@ -65,9 +65,10 @@ void SetupLightAndCamera(phx::Scene* scene) {
   light->SetColor(glm::vec3(1.0f, 1.0f, 1.0f));
   light->SetIntensity(1.0f);
 
-  phx::Entity* camera = scene->CreateEntity();
-  auto camera_transform = camera->AddComponent<phx::Transform>();
-  auto camera_projection = camera->AddComponent<phx::Projection>();
+  phx::Entity* camera =
+      scene->GetEntitiesWithComponents<phx::RenderTarget>()[0];
+  auto camera_transform = camera->GetFirstComponent<phx::Transform>();
+  auto camera_projection = camera->GetFirstComponent<phx::Projection>();
   camera_projection->SetPerspective(glm::radians(68.0f), 4.0f / 3.0f, 0.01f,
                                     1000.0f);
   camera_transform->SetLocalTranslation(glm::vec3(0, 0, 2.0));
diff --git a/tests/src/test_geometry_pass.cpp b/tests/src/test_geometry_pass.cpp
index 2edd3f931eda628a101e8da96c77b147b8e5bdf0..d8cdc27c771136f87a763a8cb840352afbd17ceb 100644
--- a/tests/src/test_geometry_pass.cpp
+++ b/tests/src/test_geometry_pass.cpp
@@ -39,7 +39,9 @@ SUPPRESS_WARNINGS_END
 
 #include "phx/entity.hpp"
 #include "phx/geometry_pass.hpp"
+#include "phx/projection.hpp"
 #include "phx/render_target.hpp"
+#include "phx/transform.hpp"
 
 #include "mocks/opengl_mock.hpp"
 
@@ -57,8 +59,12 @@ SCENARIO(
   const GLuint index_buffer_id = 4u;
 
   GIVEN("A geometry pass") {
-    phx::RenderTarget renderTarget(glm::uvec2(1024, 768));
-    phx::GeometryPass geometry_pass(&renderTarget);
+    phx::Entity camera;
+    camera.AddComponent<phx::Transform>();
+    camera.AddComponent<phx::Projection>();
+    auto render_target =
+        camera.AddComponent<phx::RenderTarget>(glm::uvec2(1024, 768));
+    phx::GeometryPass geometry_pass(render_target);
 
     WHEN("We initialize it.") {
       trompeloeil::sequence seq;
@@ -223,8 +229,12 @@ SCENARIO(
   const GLuint index_buffer_id = 3u;
 
   GIVEN("An initialized geometry pass") {
-    phx::RenderTarget renderTarget(glm::uvec2(1024, 768));
-    phx::GeometryPass geometry_pass(&renderTarget);
+    phx::Entity camera;
+    camera.AddComponent<phx::Transform>();
+    camera.AddComponent<phx::Projection>();
+    auto render_target =
+      camera.AddComponent<phx::RenderTarget>(glm::uvec2(1024, 768));
+    phx::GeometryPass geometry_pass(render_target);
     geometry_pass.Initialize();
 
     WHEN("We add a meshes with two different transformations") {