SceneViewExtension, PostRenderViewFamily_RenderThread,Background

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);
}
1 Like

it seems that you should render you background image before anti-aliasing …