Select Git revision
rendering_system.cpp
rendering_system.cpp 7.12 KiB
//------------------------------------------------------------------------------
// Project Phoenix
//
// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
// Virtual Reality & Immersive Visualization Group.
//------------------------------------------------------------------------------
// License
//
// Licensed under the 3-Clause BSD License (the "License");
// you may not use this file except in compliance with the License.
// See the file LICENSE for the full text.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//------------------------------------------------------------------------------
#include "rendering_system.hpp"
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "blit_pass.hpp"
#include "clear_pass.hpp"
#include "display_system.hpp"
#include "engine.hpp"
#include "light.hpp"
#include "logger.hpp"
#include "material_handle.hpp"
#include "mesh.hpp"
#include "mesh_handle.hpp"
#include "projection.hpp"
#include "scene.hpp"
#include "system.hpp"
#include "transform.hpp"
#include "gl/opengl.hpp"
namespace phx {
RenderingSystem::RenderingSystem(Engine* engine, DisplaySystem* display_system)
: System(engine) {
if (!display_system) error("RenderingSystem needs a valid DisplaySystem.");
InitializeOpenGL();
InitializeRenderTargets();
SetupFramegraph();
}
void RenderingSystem::InitializeOpenGL() {
if (!gl::initialize()) {
error("Initializing gl failed");
}
std::string prefix = "[RenderingSystem] OpenGl Error: ";
gl::print_error(prefix.c_str());
}
void RenderingSystem::InitializeRenderTargets() {
const auto displaySystem = engine_->GetSystem<DisplaySystem>();
if (displaySystem == nullptr) {
error(
"The Rendering System cannot be initialized without a display system");
return;
}
// TODO(all) Support multiple windows and HMD?
if (displaySystem->GetHMD() != nullptr) {
HMD* hmd = displaySystem->GetHMD();
right_render_target_ =
std::make_unique<RenderTarget>(hmd->GetViewportSize());
left_render_target_ =
std::make_unique<RenderTarget>(hmd->GetViewportSize());
} else if (displaySystem->GetWindow() != nullptr) {
auto window = displaySystem->GetWindow();
window_render_target_ = std::make_unique<RenderTarget>(window->GetSize());
}
}
void RenderingSystem::SetupFramegraph() {
frame_graph_ = std::make_unique<FrameGraph>();
if (right_render_target_ != nullptr && left_render_target_ != nullptr) {
frame_graph_->AddRenderPass(
std::make_unique<ClearPass>(right_render_target_.get()));
frame_graph_->AddRenderPass(
std::make_unique<ClearPass>(left_render_target_.get()));
auto geometry_pass = static_cast<GeometryPass*>(frame_graph_->AddRenderPass(
std::make_unique<GeometryPass>(right_render_target_.get())));
geometry_passes_.push_back(geometry_pass);
geometry_pass = static_cast<GeometryPass*>(frame_graph_->AddRenderPass(
std::make_unique<GeometryPass>(left_render_target_.get())));
geometry_passes_.push_back(geometry_pass);
frame_graph_->AddRenderPass(
std::make_unique<BlitPass>(right_render_target_.get()));
} else if (window_render_target_ != nullptr) {
frame_graph_->AddRenderPass(
std::make_unique<ClearPass>(window_render_target_.get()));
auto geometry_pass = static_cast<GeometryPass*>(frame_graph_->AddRenderPass(
std::make_unique<GeometryPass>(window_render_target_.get())));
geometry_passes_.push_back(geometry_pass);
frame_graph_->AddRenderPass(
std::make_unique<BlitPass>(window_render_target_.get()));
} else {
error(
"[RenderingSystem] No Render Targets are defined, so no framegraph "
"will be created.");
return;
}
frame_graph_->Initialize();
}
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;
}
// TODO(@all) refactor this part, once there is a way to get entities by name
for (auto& entity : GetEngine()->GetEntities()) {
if (entity->GetName() == "RuntimeEntityEyeLeft") {
left_render_target_->SetView(
inverse(entity->GetFirstComponent<Transform>()->GetGlobalMatrix()));
}
if (entity->GetName() == "RuntimeEntityEyeRight") {
right_render_target_->SetView(
inverse(entity->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) {
if (mesh_handle != nullptr) {
Material* material = nullptr;
if (material_handle != nullptr)
material = material_handle->GetMaterial();
rendering_instances.push_back(
{mesh_handle->GetMesh(), material, transform});
} 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));
}
}
}
for (auto geometry_pass : geometry_passes_) {
geometry_pass->SetData(rendering_instances, light_transform_pairs);
}
HMD* hmd = engine_->GetSystem<DisplaySystem>()->GetHMD();
if (left_render_target_ != nullptr) {
left_render_target_->SetProjection(hmd->GetProjectionMatrix(HMD::LEFT_EYE));
}
if (right_render_target_ != nullptr) {
right_render_target_->SetProjection(
hmd->GetProjectionMatrix(HMD::RIGHT_EYE));
}
if (window_render_target_ != nullptr && !projection_transform_pairs.empty()) {
window_render_target_->SetProjection(
projection_transform_pairs[0].first->GetMatrix());
window_render_target_->SetView(
glm::inverse(projection_transform_pairs[0].second->GetGlobalMatrix()));
}
frame_graph_->Execute();
}
FrameGraph* RenderingSystem::GetFrameGraph() const {
return frame_graph_.get();
}
std::string RenderingSystem::ToString() const {
return "RenderingSystem with #FrameGraph-Passes: " +
std::to_string(frame_graph_->GetNumberOfPasses());
}
phx::RenderTarget* RenderingSystem::GetRightRenderTarget() const {
return right_render_target_.get();
}
phx::RenderTarget* RenderingSystem::GetLeftRenderTarget() const {
return left_render_target_.get();
}
} // namespace phx