2026-04-01 21:37:15 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "ViewportHostRenderTargets.h"
|
|
|
|
|
|
|
|
|
|
#include <XCEngine/Core/Math/Color.h>
|
|
|
|
|
#include <XCEngine/Rendering/CameraRenderRequest.h>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace Editor {
|
|
|
|
|
|
|
|
|
|
struct ViewportRenderFallbackPolicy {
|
|
|
|
|
const char* statusText = nullptr;
|
|
|
|
|
Math::Color clearColor = Math::Color::Black();
|
|
|
|
|
bool shouldClear = false;
|
|
|
|
|
bool setStatusIfEmpty = false;
|
|
|
|
|
bool invalidateObjectIdFrame = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class SceneViewportRenderFailure {
|
|
|
|
|
MissingSceneViewCamera,
|
|
|
|
|
NoActiveScene,
|
|
|
|
|
SceneRendererFailed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class GameViewportRenderFailure {
|
|
|
|
|
NoActiveScene,
|
|
|
|
|
NoCameraInScene,
|
|
|
|
|
SceneRendererFailed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline void SetViewportStatusIfEmpty(std::string& statusText, const char* message) {
|
|
|
|
|
if (statusText.empty()) {
|
|
|
|
|
statusText = message;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void ApplyViewportFailureStatus(
|
|
|
|
|
std::string& statusText,
|
|
|
|
|
const ViewportRenderFallbackPolicy& policy) {
|
|
|
|
|
if (policy.statusText == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (policy.setStatusIfEmpty) {
|
|
|
|
|
SetViewportStatusIfEmpty(statusText, policy.statusText);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
statusText = policy.statusText;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void InvalidateViewportObjectIdFrame(ViewportRenderTargets& targets) {
|
|
|
|
|
targets.hasValidObjectIdFrame = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline ViewportRenderFallbackPolicy BuildViewportRenderTargetUnavailablePolicy() {
|
|
|
|
|
ViewportRenderFallbackPolicy policy = {};
|
|
|
|
|
policy.statusText = "Viewport render target is unavailable";
|
|
|
|
|
return policy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline ViewportRenderFallbackPolicy BuildSceneViewportRenderFailurePolicy(
|
|
|
|
|
SceneViewportRenderFailure failure) {
|
|
|
|
|
ViewportRenderFallbackPolicy policy = {};
|
|
|
|
|
policy.shouldClear = true;
|
|
|
|
|
|
|
|
|
|
switch (failure) {
|
|
|
|
|
case SceneViewportRenderFailure::MissingSceneViewCamera:
|
|
|
|
|
policy.statusText = "Scene view camera is unavailable";
|
|
|
|
|
policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f);
|
|
|
|
|
break;
|
|
|
|
|
case SceneViewportRenderFailure::NoActiveScene:
|
|
|
|
|
policy.statusText = "No active scene";
|
|
|
|
|
policy.clearColor = Math::Color(0.07f, 0.08f, 0.10f, 1.0f);
|
|
|
|
|
break;
|
|
|
|
|
case SceneViewportRenderFailure::SceneRendererFailed:
|
|
|
|
|
policy.statusText = "Scene renderer failed";
|
|
|
|
|
policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f);
|
|
|
|
|
policy.setStatusIfEmpty = true;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return policy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline ViewportRenderFallbackPolicy BuildGameViewportRenderFailurePolicy(
|
|
|
|
|
GameViewportRenderFailure failure) {
|
|
|
|
|
ViewportRenderFallbackPolicy policy = {};
|
|
|
|
|
policy.shouldClear = true;
|
|
|
|
|
|
|
|
|
|
switch (failure) {
|
|
|
|
|
case GameViewportRenderFailure::NoActiveScene:
|
|
|
|
|
policy.statusText = "No active scene";
|
|
|
|
|
policy.clearColor = Math::Color(0.07f, 0.08f, 0.10f, 1.0f);
|
|
|
|
|
break;
|
|
|
|
|
case GameViewportRenderFailure::NoCameraInScene:
|
|
|
|
|
policy.statusText = "No camera in scene";
|
|
|
|
|
policy.clearColor = Math::Color(0.10f, 0.09f, 0.08f, 1.0f);
|
|
|
|
|
break;
|
|
|
|
|
case GameViewportRenderFailure::SceneRendererFailed:
|
|
|
|
|
policy.statusText = "Scene renderer failed";
|
|
|
|
|
policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return policy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void ApplySceneViewportRenderRequestSetup(
|
|
|
|
|
const ViewportRenderTargets& targets,
|
2026-04-02 14:49:00 +08:00
|
|
|
const Rendering::BuiltinPostProcessRequest* builtinPostProcess,
|
2026-04-01 21:37:15 +08:00
|
|
|
Rendering::RenderPassSequence* postPasses,
|
|
|
|
|
Rendering::CameraRenderRequest& request) {
|
|
|
|
|
request.postScenePasses = nullptr;
|
|
|
|
|
request.objectId = {};
|
2026-04-02 14:49:00 +08:00
|
|
|
request.builtinPostProcess = {};
|
2026-04-01 21:37:15 +08:00
|
|
|
|
|
|
|
|
if (postPasses != nullptr && postPasses->GetPassCount() > 0) {
|
|
|
|
|
request.postScenePasses = postPasses;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 14:49:00 +08:00
|
|
|
if (builtinPostProcess != nullptr &&
|
|
|
|
|
builtinPostProcess->IsRequested()) {
|
|
|
|
|
request.builtinPostProcess = *builtinPostProcess;
|
|
|
|
|
request.builtinPostProcess.objectIdTextureView = targets.objectIdShaderView;
|
2026-04-02 12:47:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 21:37:15 +08:00
|
|
|
if (targets.objectIdView == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request.objectId.surface = BuildViewportObjectIdSurface(targets);
|
|
|
|
|
request.objectId.surface.SetRenderArea(request.surface.GetRenderArea());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void MarkSceneViewportRenderSuccess(
|
|
|
|
|
ViewportRenderTargets& targets,
|
|
|
|
|
const Rendering::CameraRenderRequest& request) {
|
|
|
|
|
targets.colorState = RHI::ResourceStates::PixelShaderResource;
|
|
|
|
|
targets.objectIdState = RHI::ResourceStates::PixelShaderResource;
|
|
|
|
|
targets.hasValidObjectIdFrame = request.objectId.IsRequested();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void MarkGameViewportRenderSuccess(ViewportRenderTargets& targets) {
|
|
|
|
|
targets.colorState = RHI::ResourceStates::PixelShaderResource;
|
|
|
|
|
targets.hasValidObjectIdFrame = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Editor
|
|
|
|
|
} // namespace XCEngine
|