Add request-level clear control for camera rendering
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/RenderCameraData.h>
|
||||
#include <XCEngine/Rendering/RenderContext.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
|
||||
@@ -17,6 +18,7 @@ struct CameraRenderRequest {
|
||||
RenderContext context;
|
||||
RenderSurface surface;
|
||||
float cameraDepth = 0.0f;
|
||||
RenderClearFlags clearFlags = RenderClearFlags::All;
|
||||
|
||||
bool IsValid() const {
|
||||
return scene != nullptr &&
|
||||
|
||||
@@ -9,12 +9,34 @@
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
enum class RenderClearFlags : uint8_t {
|
||||
None = 0,
|
||||
Color = 1 << 0,
|
||||
Depth = 1 << 1,
|
||||
All = (1 << 0) | (1 << 1)
|
||||
};
|
||||
|
||||
constexpr RenderClearFlags operator|(RenderClearFlags lhs, RenderClearFlags rhs) {
|
||||
return static_cast<RenderClearFlags>(
|
||||
static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
constexpr RenderClearFlags operator&(RenderClearFlags lhs, RenderClearFlags rhs) {
|
||||
return static_cast<RenderClearFlags>(
|
||||
static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
|
||||
}
|
||||
|
||||
constexpr bool HasRenderClearFlag(RenderClearFlags flags, RenderClearFlags flag) {
|
||||
return static_cast<uint8_t>(flags & flag) != 0;
|
||||
}
|
||||
|
||||
struct RenderCameraData {
|
||||
Math::Matrix4x4 view = Math::Matrix4x4::Identity();
|
||||
Math::Matrix4x4 projection = Math::Matrix4x4::Identity();
|
||||
Math::Matrix4x4 viewProjection = Math::Matrix4x4::Identity();
|
||||
Math::Vector3 worldPosition = Math::Vector3::Zero();
|
||||
Math::Color clearColor = Math::Color::Black();
|
||||
RenderClearFlags clearFlags = RenderClearFlags::All;
|
||||
uint32_t viewportWidth = 0;
|
||||
uint32_t viewportHeight = 0;
|
||||
};
|
||||
|
||||
@@ -50,6 +50,7 @@ bool CameraRenderer::Render(
|
||||
return false;
|
||||
}
|
||||
|
||||
sceneData.cameraData.clearFlags = request.clearFlags;
|
||||
return m_pipeline->Render(request.context, request.surface, sceneData);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,12 +235,15 @@ bool BuiltinForwardPipeline::Render(
|
||||
? surface.GetClearColorOverride()
|
||||
: sceneData.cameraData.clearColor;
|
||||
const float clearValues[4] = { clearColor.r, clearColor.g, clearColor.b, clearColor.a };
|
||||
for (RHI::RHIResourceView* renderTarget : renderTargets) {
|
||||
if (renderTarget != nullptr) {
|
||||
commandList->ClearRenderTarget(renderTarget, clearValues);
|
||||
if (HasRenderClearFlag(sceneData.cameraData.clearFlags, RenderClearFlags::Color)) {
|
||||
for (RHI::RHIResourceView* renderTarget : renderTargets) {
|
||||
if (renderTarget != nullptr) {
|
||||
commandList->ClearRenderTarget(renderTarget, clearValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surface.GetDepthAttachment() != nullptr) {
|
||||
if (surface.GetDepthAttachment() != nullptr &&
|
||||
HasRenderClearFlag(sceneData.cameraData.clearFlags, RenderClearFlags::Depth)) {
|
||||
commandList->ClearDepthStencil(surface.GetDepthAttachment(), 1.0f, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ std::vector<CameraRenderRequest> SceneRenderer::BuildRenderRequests(
|
||||
request.context = context;
|
||||
request.surface = surface;
|
||||
request.cameraDepth = camera->GetDepth();
|
||||
request.clearFlags = RenderClearFlags::All;
|
||||
requests.push_back(request);
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ struct MockPipelineState {
|
||||
uint32_t lastSurfaceHeight = 0;
|
||||
CameraComponent* lastCamera = nullptr;
|
||||
size_t lastVisibleItemCount = 0;
|
||||
RenderClearFlags lastClearFlags = RenderClearFlags::All;
|
||||
std::vector<CameraComponent*> renderedCameras;
|
||||
std::vector<RenderClearFlags> renderedClearFlags;
|
||||
};
|
||||
|
||||
class MockPipeline final : public RenderPipeline {
|
||||
@@ -49,7 +51,9 @@ public:
|
||||
m_state->lastSurfaceHeight = surface.GetHeight();
|
||||
m_state->lastCamera = sceneData.camera;
|
||||
m_state->lastVisibleItemCount = sceneData.visibleItems.size();
|
||||
m_state->lastClearFlags = sceneData.cameraData.clearFlags;
|
||||
m_state->renderedCameras.push_back(sceneData.camera);
|
||||
m_state->renderedClearFlags.push_back(sceneData.cameraData.clearFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -89,6 +93,7 @@ TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
|
||||
request.context = CreateValidContext();
|
||||
request.surface = RenderSurface(640, 480);
|
||||
request.cameraDepth = overrideCamera->GetDepth();
|
||||
request.clearFlags = RenderClearFlags::None;
|
||||
|
||||
ASSERT_TRUE(renderer.Render(request));
|
||||
EXPECT_EQ(state->renderCalls, 1);
|
||||
@@ -97,6 +102,7 @@ TEST(CameraRenderer_Test, UsesOverrideCameraAndSurfaceSizeWhenSubmittingScene) {
|
||||
EXPECT_EQ(state->lastCamera, overrideCamera);
|
||||
EXPECT_NE(state->lastCamera, primaryCamera);
|
||||
EXPECT_EQ(state->lastVisibleItemCount, 0u);
|
||||
EXPECT_EQ(state->lastClearFlags, RenderClearFlags::None);
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, BuildsSingleExplicitRequestFromSelectedCamera) {
|
||||
@@ -121,6 +127,7 @@ TEST(SceneRenderer_Test, BuildsSingleExplicitRequestFromSelectedCamera) {
|
||||
ASSERT_EQ(defaultRequests.size(), 1u);
|
||||
EXPECT_EQ(defaultRequests[0].camera, highCamera);
|
||||
EXPECT_EQ(defaultRequests[0].cameraDepth, 5.0f);
|
||||
EXPECT_EQ(defaultRequests[0].clearFlags, RenderClearFlags::All);
|
||||
EXPECT_EQ(defaultRequests[0].surface.GetWidth(), 320u);
|
||||
EXPECT_EQ(defaultRequests[0].surface.GetHeight(), 180u);
|
||||
|
||||
@@ -188,14 +195,19 @@ TEST(SceneRenderer_Test, SortsManualCameraRequestsByDepthBeforeRendering) {
|
||||
farRequest.context = CreateValidContext();
|
||||
farRequest.surface = RenderSurface(800, 600);
|
||||
farRequest.cameraDepth = farCamera->GetDepth();
|
||||
farRequest.clearFlags = RenderClearFlags::None;
|
||||
|
||||
CameraRenderRequest nearRequest = farRequest;
|
||||
nearRequest.camera = nearCamera;
|
||||
nearRequest.cameraDepth = nearCamera->GetDepth();
|
||||
nearRequest.clearFlags = RenderClearFlags::Depth;
|
||||
|
||||
const std::vector<CameraRenderRequest> requests = { farRequest, nearRequest };
|
||||
ASSERT_TRUE(renderer.Render(requests));
|
||||
ASSERT_EQ(state->renderedCameras.size(), 2u);
|
||||
ASSERT_EQ(state->renderedClearFlags.size(), 2u);
|
||||
EXPECT_EQ(state->renderedCameras[0], nearCamera);
|
||||
EXPECT_EQ(state->renderedClearFlags[0], RenderClearFlags::Depth);
|
||||
EXPECT_EQ(state->renderedCameras[1], farCamera);
|
||||
EXPECT_EQ(state->renderedClearFlags[1], RenderClearFlags::None);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user