void FRCPassPostProcessScreenSpaceReflections::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, ScreenSpaceReflections, DEC_SCENE_ITEMS); const FSceneView& View = Context.View; const auto FeatureLevel = Context.GetFeatureLevel(); const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, FIntRect()); Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); int SSRQuality = ComputeSSRQuality(View.FinalPostProcessSettings.ScreenSpaceReflectionQuality); SSRQuality = FMath::Clamp(SSRQuality, 1, 4); uint32 iPreFrame = bPrevFrame ? 1 : 0; if (View.Family->EngineShowFlags.VisualizeSSR) { iPreFrame = 0; SSRQuality = 0; } TShaderMapRef< FPostProcessVS > VertexShader(Context.GetShaderMap()); #define CASE(A, B) \ case (A + 2 * (B + 3 * 0 )): \ { \ TShaderMapRef< FPostProcessScreenSpaceReflectionsPS<A, B> > PixelShader(Context.GetShaderMap()); \ static FGlobalBoundShaderState BoundShaderState; \ SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); \ VertexShader->SetParameters(Context); \ PixelShader->SetParameters(Context); \ }; \ break switch (iPreFrame + 2 * (SSRQuality + 3 * 0)) { CASE(0,0); CASE(0,1); CASE(1,1); CASE(0,2); CASE(1,2); CASE(0,3); CASE(1,3); CASE(0,4); CASE(1,4); default: check(!"Missing case in FRCPassPostProcessScreenSpaceReflections"); } #undef CASE // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), GSceneRenderTargets.GetBufferSizeXY(), *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessScreenSpaceReflections::Process(FRenderingCompositePassContext& Context) { auto& RHICmdList = Context.RHICmdList; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const FSceneView& View = Context.View; const auto FeatureLevel = Context.GetFeatureLevel(); int32 SSRQuality = ComputeSSRQuality(View.FinalPostProcessSettings.ScreenSpaceReflectionQuality); uint32 iPreFrame = bPrevFrame ? 1 : 0; SSRQuality = FMath::Clamp(SSRQuality, 1, 4); const bool VisualizeSSR = View.Family->EngineShowFlags.VisualizeSSR; const bool SSRStencilPrePass = CVarSSRStencil.GetValueOnRenderThread() != 0 && !VisualizeSSR; FRenderingCompositeOutputRef* Input2 = GetInput(ePId_Input2); const bool SSRConeTracing = Input2 && Input2->GetOutput(); if (VisualizeSSR) { iPreFrame = 0; SSRQuality = 0; } else if (SSRConeTracing) { SSRQuality = SSRConeQuality; } const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); if (SSRStencilPrePass) { // ScreenSpaceReflectionsStencil draw event SCOPED_DRAW_EVENT(RHICmdList, ScreenSpaceReflectionsStencil); TShaderMapRef< FPostProcessVS > VertexShader(Context.GetShaderMap()); TShaderMapRef< FPostProcessScreenSpaceReflectionsStencilPS > PixelShader(Context.GetShaderMap()); // bind the dest render target and the depth stencil render target SetRenderTarget(RHICmdList, DestRenderTarget.TargetableTexture, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EUninitializedColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); Context.SetViewportAndCallRHI(View.ViewRect); // Clear stencil to 0 RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, View.ViewRect); // bind shader static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetParameters(Context); PixelShader->SetParameters(Context, SSRQuality, true); // Clobers the stencil to pixel that should not compute SSR RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true, CF_Always, SO_Replace, SO_Replace, SO_Replace>::GetRHI(), 0x80); // Set rasterizer state to solid RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); // disable blend mode RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); // Draw a quad mapping scene color to the view's render target to set stencil to set the stencil mask where it needs to be DrawRectangle( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, EDRF_UseTriangleOptimization); } // ScreenSpaceReflectionsStencil draw event { // ScreenSpaceReflections draw event SCOPED_DRAW_EVENT(Context.RHICmdList, ScreenSpaceReflections); if (SSRStencilPrePass) { // set up the stencil test to match 0, meaning FPostProcessScreenSpaceReflectionsStencilPS has been discarded RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true, CF_Equal, SO_Keep, SO_Keep, SO_Keep>::GetRHI(), 0); } else { // bind only the dest render target SetRenderTarget(RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(View.ViewRect); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); } // clear DestRenderTarget only outside of the view's rectangle RHICmdList.Clear(true, FLinearColor::Black, false, (float)ERHIZBuffer::FarPlane, false, 0, View.ViewRect); // set the state RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); TShaderMapRef< FPostProcessVS > VertexShader(Context.GetShaderMap()); #define CASE(A, B) \ case (A + 2 * (B + 3 * 0 )): \ { \ TShaderMapRef< FPostProcessScreenSpaceReflectionsPS<A, B> > PixelShader(Context.GetShaderMap()); \ static FGlobalBoundShaderState BoundShaderState; \ SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); \ VertexShader->SetParameters(Context); \ PixelShader->SetParameters(Context); \ }; \ break switch (iPreFrame + 2 * (SSRQuality + 3 * 0)) { CASE(0,0); CASE(0,1); CASE(1,1); CASE(0,2); CASE(1,2); CASE(0,3); CASE(1,3); CASE(0,4); CASE(1,4); CASE(0,5); CASE(1,5); //SSRConeQuality default: check(!"Missing case in FRCPassPostProcessScreenSpaceReflections"); } #undef CASE // Draw a quad mapping scene color to the view's render target DrawRectangle( RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY(), *VertexShader, EDRF_UseTriangleOptimization); RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); } // ScreenSpaceReflections }