I want to render a background image for the current level. To prevent the background image from being affected by lighting, shadows, post-processing exposure, and other effects, I added a pass in the PostRenderView_RenderThread
function of SceneViewExtension
. I used depth testing to ensure the background image appears behind the level. However, in the rendered result, the objects in the level are jittering at the edge.
there is project:
ComposeBackground.zip (2.4 MB)
void FBackgroundSceneView::PostRenderView_RenderThread(FRDGBuilder& GraphBuilder, FSceneView& View)
{
const FIntRect PrimaryViewRect = static_cast<const FViewInfo&>(View).ViewRect;
FViewInfo* ViewInfo = (FViewInfo*)(&View);
FSceneTextures& SceneTextures = ((FViewFamilyInfo*)ViewInfo->Family)->GetSceneTextures();
TRDGUniformBufferRef<FSceneTextureUniformParameters> UniforBuffer = SceneTextures.UniformBuffer;
FScreenPassTexture SceneColor((*UniforBuffer)->SceneColorTexture, PrimaryViewRect);
FScreenPassRenderTarget SceneColorRenderTarget(SceneColor, ERenderTargetLoadAction::ELoad);
FScreenPassTexture SceneDepth((*UniforBuffer)->SceneDepthTexture, PrimaryViewRect);
FTextureResource* Resource = Background->GetResource();
FRDGTexture* ViewFamilySceneTexture = GraphBuilder.FindExternalTexture(View.Family->RenderTarget->GetRenderTargetTexture());
FBackgroundShaderPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FBackgroundShaderPS::FParameters>();
PassParameters->RenderTargets[0] = FRenderTargetBinding(ViewFamilySceneTexture, ERenderTargetLoadAction::ELoad);//SceneColorRenderTarget.GetRenderTargetBinding();
PassParameters->BackgroundSample = TStaticSamplerState<SF_Trilinear>::GetRHI();
PassParameters->BackgroundTexture = //SceneDepth.Texture;
RegisterExternalTexture(
GraphBuilder, Resource->GetTextureRHI()->GetTexture2D(),
TEXT("BGRHI"));
PassParameters->RenderTargets.DepthStencil = FDepthStencilBinding(SceneDepth.Texture,
ERenderTargetLoadAction::ELoad,
ERenderTargetLoadAction::ENoAction,
FExclusiveDepthStencil::DepthRead_StencilNop);
PassParameters->SceneTextures = GetSceneTextureShaderParameters(UniforBuffer);
PassParameters->SceneTexturesStruct = (UniforBuffer);
TShaderMapRef<FBackgroundShaderVS> VertexShader(GetGlobalShaderMap(View.GetFeatureLevel()));
TShaderMapRef<FBackgroundShaderPS> PixelShader(GetGlobalShaderMap(View.GetFeatureLevel()));
ClearUnusedGraphResources(PixelShader, PassParameters);
const FViewMatrices* ViewMatrices = &View.ViewMatrices;
const FMatrix ProjectionMatrix = ViewMatrices->GetProjectionMatrix();
float HalfHorizontalFOV = FMath::Atan(1.0f / ProjectionMatrix.M[0][0]);
float HalfVerticalFOV = FMath::Atan(1.0f / ProjectionMatrix.M[1][1]);
float StartDepthViewCm = FMath::Cos(FMath::Max(HalfHorizontalFOV, HalfVerticalFOV)) * 10000;
StartDepthViewCm = FMath::Max(StartDepthViewCm, View.NearClippingDistance);
const FVector4 Projected = ProjectionMatrix.TransformFVector4(FVector4(0.0f, 0.0f, StartDepthViewCm, 1.0f));
float StartDepthZ = float(Projected.Z / Projected.W);
GraphBuilder.AddPass(
RDG_EVENT_NAME("CustomBackgroundPass"),
PassParameters,
ERDGPassFlags::Raster,
[StartDepthZ,PrimaryViewRect, VertexShader, PixelShader, PassParameters](FRHICommandList& RHICmdList)
{
RHICmdList.SetViewport(0.0f, 0.0f, 0.0f, PrimaryViewRect.Max.X, PrimaryViewRect.Max.Y, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false,CF_Greater>::GetRHI();
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GEmptyVertexDeclaration.VertexDeclarationRHI;//GFilterVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit,0);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
FBackgroundShaderVS::FParameters VsPassParameters;
VsPassParameters.StartDepthZ = StartDepthZ;
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), VsPassParameters);
//RHICmdList.SetStreamSource(0, GScreenSpaceVertexBuffer.VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 1, 1);
}
);
}
// Shader file, refered to SkyatmoSphere.usf
float StartDepthZ;
SamplerState BackgroundSample;
Texture2D BackgroundTexture;
void MainVS(
in uint VertexId : SV_VertexID,
out float4 Position : SV_POSITION,
out float2 OutUV : TEXCOORD0
)
{
float2 UV = -1.0f;
UV = VertexId == 1 ? float2(-1.0f, 3.0f) : UV;
UV = VertexId == 2 ? float2( 3.0f, -1.0f) : UV;
Position = float4(UV, StartDepthZ, 1.0f);
OutUV = (UV+1)*0.5f;
}
void MainPS(
in float4 SVPos : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0
)
{
float2 UV = float2(InUV.x, 1.0f-InUV.y);
float4 Color = Texture2DSampleLevel(BackgroundTexture, BackgroundSample, UV, 0);
OutColor = float4(LinearToSrgb(Color), 1.0f);
}