Lower final color into final output stage
This commit is contained in:
@@ -211,6 +211,53 @@ TEST(BuiltinForwardPipeline_Test, BuiltinSkyboxShaderDeclaresExplicitEnvironment
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderDeclaresExplicitFullscreenResourceContract) {
|
||||
ShaderLoader loader;
|
||||
LoadResult result = loader.Load(GetBuiltinFinalColorShaderPath());
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_NE(result.resource, nullptr);
|
||||
|
||||
Shader* shader = static_cast<Shader*>(result.resource);
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
const ShaderPass* pass = shader->FindPass("FinalColor");
|
||||
ASSERT_NE(pass, nullptr);
|
||||
ASSERT_EQ(pass->resources.Size(), 3u);
|
||||
|
||||
const ShaderPropertyDesc* colorScale = shader->FindProperty("_ColorScale");
|
||||
ASSERT_NE(colorScale, nullptr);
|
||||
EXPECT_EQ(colorScale->type, ShaderPropertyType::Color);
|
||||
|
||||
const ShaderPropertyDesc* exposure = shader->FindProperty("_Exposure");
|
||||
ASSERT_NE(exposure, nullptr);
|
||||
EXPECT_EQ(exposure->type, ShaderPropertyType::Float);
|
||||
|
||||
const ShaderPropertyDesc* outputTransferMode = shader->FindProperty("_OutputTransferMode");
|
||||
ASSERT_NE(outputTransferMode, nullptr);
|
||||
EXPECT_EQ(outputTransferMode->type, ShaderPropertyType::Float);
|
||||
|
||||
const ShaderPropertyDesc* toneMappingMode = shader->FindProperty("_ToneMappingMode");
|
||||
ASSERT_NE(toneMappingMode, nullptr);
|
||||
EXPECT_EQ(toneMappingMode->type, ShaderPropertyType::Float);
|
||||
|
||||
EXPECT_STREQ(pass->resources[0].name.CStr(), "FinalColorConstants");
|
||||
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
|
||||
EXPECT_EQ(pass->resources[0].set, 0u);
|
||||
EXPECT_EQ(pass->resources[0].binding, 0u);
|
||||
|
||||
EXPECT_STREQ(pass->resources[1].name.CStr(), "SourceColorTexture");
|
||||
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::Texture2D);
|
||||
EXPECT_EQ(pass->resources[1].set, 1u);
|
||||
EXPECT_EQ(pass->resources[1].binding, 0u);
|
||||
|
||||
EXPECT_STREQ(pass->resources[2].name.CStr(), "LinearClampSampler");
|
||||
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Sampler);
|
||||
EXPECT_EQ(pass->resources[2].set, 2u);
|
||||
EXPECT_EQ(pass->resources[2].binding, 0u);
|
||||
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplicitForwardResources) {
|
||||
ShaderLoader loader;
|
||||
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
|
||||
|
||||
@@ -1887,6 +1887,169 @@ TEST(SceneRenderer_Test, ResolvesFinalColorPolicyFromPipelineDefaultsAndCameraOv
|
||||
EXPECT_FALSE(request.finalOutput.IsRequested());
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, BuildsFinalOutputRequestFromResolvedFinalColorPolicy) {
|
||||
Scene scene("SceneRendererFinalOutputScene");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(2.0f);
|
||||
|
||||
FinalColorOverrideSettings cameraOverrides = {};
|
||||
cameraOverrides.overrideExposureMode = true;
|
||||
cameraOverrides.exposureMode = FinalColorExposureMode::Fixed;
|
||||
cameraOverrides.overrideExposureValue = true;
|
||||
cameraOverrides.exposureValue = 1.6f;
|
||||
cameraOverrides.overrideFinalColorScale = true;
|
||||
cameraOverrides.finalColorScale = XCEngine::Math::Vector4(0.95f, 0.9f, 0.85f, 1.0f);
|
||||
camera->SetFinalColorOverrides(cameraOverrides);
|
||||
|
||||
auto allocationState = std::make_shared<MockShadowAllocationState>();
|
||||
MockShadowDevice device(allocationState);
|
||||
|
||||
auto* backBufferColorView = new MockShadowView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::RenderTarget,
|
||||
XCEngine::RHI::Format::R8G8B8A8_UNorm,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
auto* depthView = new MockShadowView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::DepthStencil,
|
||||
XCEngine::RHI::Format::D24_UNorm_S8_UInt,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
|
||||
auto assetState = std::make_shared<MockPipelineAssetState>();
|
||||
assetState->defaultFinalColorSettings.outputTransferMode =
|
||||
FinalColorOutputTransferMode::LinearToSRGB;
|
||||
|
||||
RenderContext context = CreateValidContext();
|
||||
context.device = &device;
|
||||
|
||||
RenderSurface surface(800, 600);
|
||||
surface.SetColorAttachment(backBufferColorView);
|
||||
surface.SetDepthAttachment(depthView);
|
||||
|
||||
SceneRenderer renderer(std::make_shared<MockPipelineAsset>(assetState));
|
||||
const std::vector<CameraRenderRequest> requests =
|
||||
renderer.BuildRenderRequests(scene, nullptr, context, surface);
|
||||
|
||||
ASSERT_EQ(requests.size(), 1u);
|
||||
const CameraRenderRequest& request = requests[0];
|
||||
EXPECT_FALSE(request.postProcess.IsRequested());
|
||||
EXPECT_TRUE(request.finalOutput.IsRequested());
|
||||
EXPECT_TRUE(request.finalOutput.IsValid());
|
||||
ASSERT_NE(request.finalOutput.passes, nullptr);
|
||||
EXPECT_EQ(request.finalOutput.passes->GetPassCount(), 1u);
|
||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), depthView);
|
||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetWidth(), 800u);
|
||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetHeight(), 600u);
|
||||
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
||||
EXPECT_NE(request.finalOutput.sourceColorView, backBufferColorView);
|
||||
ASSERT_FALSE(request.finalOutput.sourceSurface.GetColorAttachments().empty());
|
||||
EXPECT_NE(request.finalOutput.sourceSurface.GetColorAttachments()[0], backBufferColorView);
|
||||
EXPECT_EQ(allocationState->createTextureCalls, 1);
|
||||
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 1);
|
||||
EXPECT_EQ(allocationState->createShaderViewCalls, 1);
|
||||
|
||||
delete depthView;
|
||||
delete backBufferColorView;
|
||||
}
|
||||
|
||||
TEST(SceneRenderer_Test, RoutesPostProcessIntoIntermediateSurfaceBeforeFinalOutput) {
|
||||
Scene scene("SceneRendererPostProcessFinalOutputScene");
|
||||
|
||||
GameObject* cameraObject = scene.CreateGameObject("Camera");
|
||||
auto* camera = cameraObject->AddComponent<CameraComponent>();
|
||||
camera->SetPrimary(true);
|
||||
camera->SetDepth(2.0f);
|
||||
camera->SetViewportRect(XCEngine::Math::Rect(0.25f, 0.125f, 0.5f, 0.625f));
|
||||
camera->SetPostProcessPasses({
|
||||
XCEngine::Rendering::CameraPostProcessPassDesc::MakeColorScale(
|
||||
XCEngine::Math::Vector4(1.0f, 0.75f, 0.75f, 1.0f))
|
||||
});
|
||||
|
||||
FinalColorOverrideSettings cameraOverrides = {};
|
||||
cameraOverrides.overrideOutputTransferMode = true;
|
||||
cameraOverrides.outputTransferMode = FinalColorOutputTransferMode::LinearToSRGB;
|
||||
cameraOverrides.overrideFinalColorScale = true;
|
||||
cameraOverrides.finalColorScale = XCEngine::Math::Vector4(0.95f, 0.9f, 0.85f, 1.0f);
|
||||
camera->SetFinalColorOverrides(cameraOverrides);
|
||||
|
||||
auto allocationState = std::make_shared<MockShadowAllocationState>();
|
||||
MockShadowDevice device(allocationState);
|
||||
|
||||
auto* backBufferColorView = new MockShadowView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::RenderTarget,
|
||||
XCEngine::RHI::Format::R8G8B8A8_UNorm,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
auto* depthView = new MockShadowView(
|
||||
allocationState,
|
||||
XCEngine::RHI::ResourceViewType::DepthStencil,
|
||||
XCEngine::RHI::Format::D24_UNorm_S8_UInt,
|
||||
XCEngine::RHI::ResourceViewDimension::Texture2D);
|
||||
|
||||
RenderContext context = CreateValidContext();
|
||||
context.device = &device;
|
||||
|
||||
RenderSurface surface(800, 600);
|
||||
surface.SetColorAttachment(backBufferColorView);
|
||||
surface.SetDepthAttachment(depthView);
|
||||
|
||||
SceneRenderer renderer;
|
||||
const std::vector<CameraRenderRequest> requests =
|
||||
renderer.BuildRenderRequests(scene, nullptr, context, surface);
|
||||
|
||||
ASSERT_EQ(requests.size(), 1u);
|
||||
const CameraRenderRequest& request = requests[0];
|
||||
EXPECT_TRUE(request.postProcess.IsRequested());
|
||||
EXPECT_TRUE(request.finalOutput.IsRequested());
|
||||
ASSERT_NE(request.postProcess.passes, nullptr);
|
||||
ASSERT_NE(request.finalOutput.passes, nullptr);
|
||||
EXPECT_EQ(request.postProcess.passes->GetPassCount(), 1u);
|
||||
EXPECT_EQ(request.finalOutput.passes->GetPassCount(), 1u);
|
||||
|
||||
ASSERT_FALSE(request.postProcess.sourceSurface.GetColorAttachments().empty());
|
||||
ASSERT_FALSE(request.postProcess.destinationSurface.GetColorAttachments().empty());
|
||||
ASSERT_FALSE(request.finalOutput.sourceSurface.GetColorAttachments().empty());
|
||||
|
||||
EXPECT_NE(
|
||||
request.postProcess.sourceSurface.GetColorAttachments()[0],
|
||||
request.postProcess.destinationSurface.GetColorAttachments()[0]);
|
||||
EXPECT_EQ(
|
||||
request.finalOutput.sourceSurface.GetColorAttachments()[0],
|
||||
request.postProcess.destinationSurface.GetColorAttachments()[0]);
|
||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetColorAttachments()[0], backBufferColorView);
|
||||
|
||||
EXPECT_EQ(request.postProcess.sourceSurface.GetDepthAttachment(), depthView);
|
||||
EXPECT_EQ(request.postProcess.destinationSurface.GetDepthAttachment(), nullptr);
|
||||
EXPECT_EQ(request.finalOutput.sourceSurface.GetDepthAttachment(), nullptr);
|
||||
EXPECT_EQ(request.finalOutput.destinationSurface.GetDepthAttachment(), depthView);
|
||||
|
||||
const XCEngine::Math::RectInt postProcessSourceArea = request.postProcess.sourceSurface.GetRenderArea();
|
||||
EXPECT_EQ(postProcessSourceArea.x, 200);
|
||||
EXPECT_EQ(postProcessSourceArea.y, 75);
|
||||
EXPECT_EQ(postProcessSourceArea.width, 400);
|
||||
EXPECT_EQ(postProcessSourceArea.height, 375);
|
||||
const XCEngine::Math::RectInt finalOutputSourceArea = request.finalOutput.sourceSurface.GetRenderArea();
|
||||
EXPECT_EQ(finalOutputSourceArea.x, 200);
|
||||
EXPECT_EQ(finalOutputSourceArea.y, 75);
|
||||
EXPECT_EQ(finalOutputSourceArea.width, 400);
|
||||
EXPECT_EQ(finalOutputSourceArea.height, 375);
|
||||
|
||||
EXPECT_NE(request.postProcess.sourceColorView, nullptr);
|
||||
EXPECT_NE(request.finalOutput.sourceColorView, nullptr);
|
||||
EXPECT_NE(request.postProcess.sourceColorView, request.finalOutput.sourceColorView);
|
||||
EXPECT_EQ(allocationState->createTextureCalls, 2);
|
||||
EXPECT_EQ(allocationState->createRenderTargetViewCalls, 2);
|
||||
EXPECT_EQ(allocationState->createShaderViewCalls, 2);
|
||||
|
||||
delete depthView;
|
||||
delete backBufferColorView;
|
||||
}
|
||||
|
||||
TEST(CameraRenderer_Test, UsesResolvedRenderAreaForCameraViewportDimensions) {
|
||||
Scene scene("CameraRendererViewportRectScene");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user