Files
XCEngine/new_editor/app/Rendering/Viewport/SceneViewportRenderPlan.h

168 lines
6.2 KiB
C++

#pragma once
#include "Rendering/Viewport/SceneViewportPassSpecs.h"
#include "Rendering/Viewport/ViewportRenderTargets.h"
#include "Scene/EditorSceneRuntime.h"
#include <XCEngine/Components/CameraComponent.h>
#include <XCEngine/Components/GameObject.h>
#include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
#include <XCEngine/Rendering/RenderPass.h>
#include <functional>
#include <memory>
namespace XCEngine::UI::Editor::App {
struct SceneViewportRenderPlan {
::XCEngine::Rendering::RenderPassSequence postScenePasses = {};
bool usesGridPass = false;
bool usesSelectionOutline = false;
bool hasClearColorOverride = true;
::XCEngine::Math::Color clearColorOverride =
::XCEngine::Math::Color(0.27f, 0.27f, 0.27f, 1.0f);
bool HasPostScenePasses() const {
return postScenePasses.GetPassCount() > 0u;
}
};
using SceneViewportGridPassFactory = std::function<
std::unique_ptr<::XCEngine::Rendering::RenderPass>(
const SceneViewportGridPassData&)>;
using SceneViewportSelectionOutlinePassFactory = std::function<
std::unique_ptr<::XCEngine::Rendering::RenderPass>(
ViewportRenderTargets*,
const std::vector<std::uint64_t>&,
const SceneViewportSelectionOutlineStyle&)>;
struct SceneViewportRenderPlanBuildResult {
SceneViewportRenderPlan plan = {};
const char* warningStatusText = nullptr;
};
inline SceneViewportSelectionOutlineStyle BuildSceneViewportSelectionOutlineStyle(
bool debugSelectionMask = false) {
SceneViewportSelectionOutlineStyle style = {};
style.debugSelectionMask = debugSelectionMask;
return style;
}
inline bool CanRenderSceneViewportSelectionOutline(
const ViewportRenderTargets& targets) {
return targets.selectionMaskView != nullptr &&
targets.selectionMaskShaderView != nullptr &&
targets.depthView != nullptr &&
targets.depthShaderView != nullptr;
}
inline SceneViewportGridPassData BuildSceneViewportGridPassData(
const SceneViewportRenderRequest& request) {
SceneViewportGridPassData data = {};
if (request.camera == nullptr ||
request.camera->GetGameObject() == nullptr ||
request.camera->GetGameObject()->GetTransform() == nullptr) {
return data;
}
const auto* transform = request.camera->GetGameObject()->GetTransform();
data.valid = true;
data.cameraPosition = transform->GetPosition();
data.cameraForward = transform->GetForward();
data.cameraRight = transform->GetRight();
data.cameraUp = transform->GetUp();
data.verticalFovDegrees = request.camera->GetFieldOfView();
data.nearClipPlane = request.camera->GetNearClipPlane();
data.farClipPlane = request.camera->GetFarClipPlane();
data.orbitDistance = request.orbitDistance;
return data;
}
inline SceneViewportRenderPlanBuildResult BuildSceneViewportRenderPlan(
ViewportRenderTargets& targets,
const SceneViewportRenderRequest& request,
const SceneViewportGridPassFactory& gridPassFactory,
const SceneViewportSelectionOutlinePassFactory& selectionOutlinePassFactory) {
SceneViewportRenderPlanBuildResult result = {};
const SceneViewportGridPassData gridPassData =
BuildSceneViewportGridPassData(request);
if (gridPassData.valid && gridPassFactory != nullptr) {
std::unique_ptr<::XCEngine::Rendering::RenderPass> gridPass =
gridPassFactory(gridPassData);
if (gridPass != nullptr) {
result.plan.postScenePasses.AddPass(std::move(gridPass));
result.plan.usesGridPass = true;
}
}
if (request.selectedObjectIds.empty()) {
return result;
}
if (!CanRenderSceneViewportSelectionOutline(targets) ||
selectionOutlinePassFactory == nullptr) {
result.warningStatusText = "Scene selection outline resources are unavailable";
return result;
}
std::unique_ptr<::XCEngine::Rendering::RenderPass> selectionOutlinePass =
selectionOutlinePassFactory(
&targets,
request.selectedObjectIds,
BuildSceneViewportSelectionOutlineStyle(request.debugSelectionMask));
if (selectionOutlinePass != nullptr) {
result.plan.postScenePasses.AddPass(std::move(selectionOutlinePass));
result.plan.usesSelectionOutline = true;
return result;
}
result.warningStatusText = "Scene selection outline pass creation failed";
return result;
}
inline void ApplySceneViewportRenderPlan(
const ViewportRenderTargets& targets,
SceneViewportRenderPlan& plan,
::XCEngine::Rendering::CameraFramePlan& framePlan) {
framePlan.preScenePasses = nullptr;
framePlan.postScenePasses = nullptr;
framePlan.overlayPasses = nullptr;
framePlan.request.objectId = {};
if (plan.HasPostScenePasses()) {
framePlan.postScenePasses = &plan.postScenePasses;
}
if (targets.objectIdView == nullptr || targets.objectIdDepthView == nullptr) {
framePlan.request.hasClearColorOverride = plan.hasClearColorOverride;
framePlan.request.clearColorOverride = plan.clearColorOverride;
return;
}
framePlan.request.objectId.surface = BuildViewportObjectIdSurface(targets);
framePlan.request.objectId.surface.SetRenderArea(
framePlan.request.surface.GetRenderArea());
framePlan.request.hasClearColorOverride = plan.hasClearColorOverride;
framePlan.request.clearColorOverride = plan.clearColorOverride;
}
inline void MarkSceneViewportRenderSuccess(
ViewportRenderTargets& targets,
const SceneViewportRenderPlan& plan,
const ::XCEngine::Rendering::CameraFramePlan& framePlan) {
targets.colorState = ::XCEngine::RHI::ResourceStates::PixelShaderResource;
targets.objectIdState =
framePlan.request.objectId.IsRequested()
? ::XCEngine::RHI::ResourceStates::PixelShaderResource
: ::XCEngine::RHI::ResourceStates::Common;
targets.selectionMaskState =
plan.usesSelectionOutline
? ::XCEngine::RHI::ResourceStates::PixelShaderResource
: ::XCEngine::RHI::ResourceStates::Common;
targets.hasValidObjectIdFrame = framePlan.request.objectId.IsRequested();
}
} // namespace XCEngine::UI::Editor::App