refactor: extract scene render request policy utils

This commit is contained in:
2026-04-02 00:31:35 +08:00
parent fd39808c91
commit 410b1e59c3
4 changed files with 360 additions and 96 deletions

View File

@@ -1,78 +1,14 @@
#include "Rendering/SceneRenderer.h"
#include "Rendering/SceneRenderRequestUtils.h"
#include "Components/CameraComponent.h"
#include "Components/GameObject.h"
#include "Scene/Scene.h"
#include <algorithm>
#include <cmath>
namespace XCEngine {
namespace Rendering {
namespace {
bool CompareCameraRenderRequest(const CameraRenderRequest& lhs, const CameraRenderRequest& rhs) {
if (lhs.cameraStackOrder != rhs.cameraStackOrder) {
return lhs.cameraStackOrder < rhs.cameraStackOrder;
}
if (lhs.cameraDepth != rhs.cameraDepth) {
return lhs.cameraDepth < rhs.cameraDepth;
}
return false;
}
bool IsUsableCamera(const Components::CameraComponent* camera) {
return camera != nullptr &&
camera->IsEnabled() &&
camera->GetGameObject() != nullptr &&
camera->GetGameObject()->IsActiveInHierarchy();
}
RenderClearFlags ResolveClearFlags(
const Components::CameraComponent& camera,
size_t renderedBaseCameraCount,
size_t renderedRequestCount) {
switch (camera.GetClearMode()) {
case Components::CameraClearMode::ColorAndDepth:
return RenderClearFlags::All;
case Components::CameraClearMode::DepthOnly:
return RenderClearFlags::Depth;
case Components::CameraClearMode::None:
return RenderClearFlags::None;
case Components::CameraClearMode::Auto:
default:
if (camera.GetStackType() == Components::CameraStackType::Overlay) {
return renderedRequestCount == 0 ? RenderClearFlags::All : RenderClearFlags::Depth;
}
return renderedBaseCameraCount == 0 ? RenderClearFlags::All : RenderClearFlags::Depth;
}
}
Math::RectInt ResolveCameraRenderArea(
const Components::CameraComponent& camera,
const RenderSurface& surface) {
const Math::Rect viewportRect = camera.GetViewportRect();
const Math::RectInt parentRenderArea = surface.GetRenderArea();
const float parentWidth = static_cast<float>(std::max(parentRenderArea.width, 0));
const float parentHeight = static_cast<float>(std::max(parentRenderArea.height, 0));
const int32_t left = parentRenderArea.x +
static_cast<int32_t>(std::floor(viewportRect.x * parentWidth));
const int32_t top = parentRenderArea.y +
static_cast<int32_t>(std::floor(viewportRect.y * parentHeight));
const int32_t right = parentRenderArea.x +
static_cast<int32_t>(std::ceil((viewportRect.x + viewportRect.width) * parentWidth));
const int32_t bottom = parentRenderArea.y +
static_cast<int32_t>(std::ceil((viewportRect.y + viewportRect.height) * parentHeight));
return Math::RectInt(left, top, right - left, bottom - top);
}
} // namespace
SceneRenderer::SceneRenderer() = default;
SceneRenderer::SceneRenderer(std::unique_ptr<RenderPipeline> pipeline)
@@ -99,7 +35,7 @@ std::vector<CameraRenderRequest> SceneRenderer::BuildRenderRequests(
std::vector<CameraRenderRequest> requests;
std::vector<Components::CameraComponent*> cameras;
if (IsUsableCamera(overrideCamera)) {
if (SceneRenderRequestUtils::IsUsableCamera(overrideCamera)) {
cameras.push_back(overrideCamera);
} else {
cameras = scene.FindObjectsOfType<Components::CameraComponent>();
@@ -108,40 +44,24 @@ std::vector<CameraRenderRequest> SceneRenderer::BuildRenderRequests(
cameras.begin(),
cameras.end(),
[](const Components::CameraComponent* camera) {
return !IsUsableCamera(camera);
return !SceneRenderRequestUtils::IsUsableCamera(camera);
}),
cameras.end());
}
std::stable_sort(
cameras.begin(),
cameras.end(),
[](const Components::CameraComponent* lhs, const Components::CameraComponent* rhs) {
if (lhs->GetStackType() != rhs->GetStackType()) {
return static_cast<int>(lhs->GetStackType()) < static_cast<int>(rhs->GetStackType());
}
if (lhs->GetDepth() != rhs->GetDepth()) {
return lhs->GetDepth() < rhs->GetDepth();
}
return false;
});
SceneRenderRequestUtils::SortSceneCamerasForRendering(cameras);
size_t renderedBaseCameraCount = 0;
for (Components::CameraComponent* camera : cameras) {
CameraRenderRequest request;
request.scene = &scene;
request.camera = camera;
request.context = context;
request.surface = surface;
request.surface.SetRenderArea(ResolveCameraRenderArea(*camera, surface));
request.cameraDepth = camera->GetDepth();
request.cameraStackOrder = static_cast<uint8_t>(camera->GetStackType());
request.clearFlags = ResolveClearFlags(*camera, renderedBaseCameraCount, requests.size());
if (request.surface.GetRenderAreaWidth() > 0 &&
request.surface.GetRenderAreaHeight() > 0) {
if (SceneRenderRequestUtils::BuildCameraRenderRequest(
scene,
*camera,
context,
surface,
renderedBaseCameraCount,
requests.size(),
request)) {
requests.push_back(request);
if (camera->GetStackType() == Components::CameraStackType::Base) {
++renderedBaseCameraCount;
@@ -168,10 +88,7 @@ bool SceneRenderer::Render(const std::vector<CameraRenderRequest>& requests) {
}
std::vector<CameraRenderRequest> sortedRequests = requests;
std::stable_sort(
sortedRequests.begin(),
sortedRequests.end(),
CompareCameraRenderRequest);
SceneRenderRequestUtils::SortCameraRenderRequests(sortedRequests);
bool rendered = false;
for (const CameraRenderRequest& request : sortedRequests) {