How to write a Depth Value in SceneViewExtension RenderPass

Hi, I’ve been writing and customizing the rendering pass by using the SceneView Extension.

Such as this blog, Global shaders in Unreal without engine modification - Caius' Blog. I wanted to create the pixel shader to store the previous rendertarget that are stored for the depth information in the scene.

Here is the code that I started for the first pass, then I want to calculate the velocity current Frame Depth Value from the previous one divided by the delta time.

BTW, I am using the unreal engine 5.3

void myCustomViewExtension::PrePostProcessPass_RenderThread(FRDGBuilder& graphBuilder, const FSceneView& view, const FPostProcessingInputs& inputs)

{
    checkSlow(View.bIsViewInfo);
    inputs.Validate();

    if(!cameraComponent.IsValid()) return;
    const FIntRect viewport = static_cast<const FViewInfo&>(view).ViewRect;

    FScreenPassTexture sceneColor((*inputs.SceneTextures)->SceneColorTexture, viewport);
   FScreenPassTexture sceneDepth((*inputs.SceneTextures)->SceneDepthTexture, viewport);
   FSceneTextureShaderParameters scene = GetSceneTextureShaderParameters(view);
   const FGlobalShaderMap* globalShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel);
   
   RDG_EVENT_SCOPE(graphBuilder, "UpdateDepth");
   FScreenPassRenderTarget depthRenderTarget;
   FRDGTextureDesc depthTextureDesc = sceneDepth.Texture->Desc;
   depthTextureDesc.Format = EPixelFormat::PF_DepthStencil;
   depthTextureDesc.Flags |= TexCreate_DepthStencilTargetable | TexCreate_RenderTargetable;
   depthTextureDesc.ClearValue = FClearValueBinding(0);
   depthRenderTarget.Texture = graphBuilder.CreateTexture(depthTextureDesc, TEXT("PreviousRenderTarget"));
   TShaderMapRef<UpdateDepthShader> updateDepthShader(globalShaderMap);
   UpdateDepthShader::FParameters* updateDepthParam = graphBuilder.AllocParameters<UpdateDepthShader::FParameters>();
   updateDepthParam->CameraDepthTexture = (*inputs.SceneTextures)->SceneDepthTexture

constexpr uint32 stencilRef = STENCIL_SANDBOX_MASK;
	FRHIDepthStencilState* DepthStencilState =
		TStaticDepthStencilState<true, CF_DepthNearOrEqual, false, CF_Always, SO_Keep, SO_Keep, SO_Keep, false,
			CF_Always, SO_Keep, SO_Keep, SO_Keep, STENCIL_SANDBOX_MASK, STENCIL_SANDBOX_MASK>::GetRHI();

	updateDepthParam->CameraDepthSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();

	FCommonShaderParameters commonShaderParameters;
	commonShaderParameters.ViewUniformBuffer = view.ViewUniformBuffer;
	updateDepthParam->SceneColor = (*inputs.SceneTextures)->SceneColorTexture;
	updateDepthParam->CommonParameters = commonShaderParameters;
	updateDepthParam->RenderTargets[0] = SceneColorCopyRenderTarget.GetRenderTargetBinding();
	updateDepthParam->RenderTargets[1] = depthRenderTarget.GetRenderTargetBinding();
	updateDepthParam->RenderTargets.DepthStencil = FDepthStencilBinding(
		sceneDepth.Texture, ERenderTargetLoadAction::ENoAction, FExclusiveDepthStencil::DepthWrite_StencilWrite);
	previousRenderTargetTexture = depthRenderTarget.Texture; // Save the previous render target texture

	FPixelShaderUtils::AddFullscreenPass(graphBuilder, globalShaderMap, FRDGEventName(TEXT("UpdateDepth")),
		updateDepthShader, updateDepthParam, viewport, nullptr, nullptr);
	
	AddCopyTexturePass(graphBuilder, depthRenderTarget.Texture, sceneDepth.Texture);
}

then on the .usf file.

SCREEN_PASS_TEXTURE_VIEWPORT(ViewParams)
Texture2D CameraDepthTexture;
SamplerState CameraDepthSampler;
Texture2D SceneColor;

void MainPS(float4 SvPosition
			: SV_POSITION,
			out float4 OutColor : SV_Target0,
			out float depthTexture : SV_Target1,
			out float depth : SV_Depth)
{
	float2 uv = PosToUV(SvPosition.xy);
	const int2 pixelPos = int2(SvPosition.xy);

	float SceneDeviceZ = CameraDepthTexture.SampleLevel(CameraDepthSampler, uv, 0).r;
	float SceneDepth = ConvertFromDeviceZ(SceneDeviceZ) ;

	// 0 .. 1
	half Near = CalcUnfocusedPercentCustomBound(SceneDepth, 1, 0);
	half Far = CalcUnfocusedPercentCustomBound(SceneDepth, 0, 1);

	// const float deviceZ = CameraDepthTexture.Load(int3(pixelPos, 0)).r;
	// float4(frac(ConvertFromDeviceZ(deviceZ) * 0.0001f), 0, 0, 1);
	// DepthTexture = Texture2DSample(CameraDepthTexture, CameraDepthSampler, uv);
	// CameraDepthTexture.Load(int3(pixelPos, 0));
	depthTexture = SceneDepth;
	depth = SceneDepth;
	OutColor = SceneColor.SampleLevel(CameraDepthSampler, uv, 0);
	// DepthTexture = float4(frac(ConvertFromDeviceZ(deviceZ) * 0.0001f), 0, 0, 1);
}

From this, I could not see RDG_EVENT_NAME_INFO in the renderDoc, and my pixel shader is not working properly.

Currently, Settings for SceneCaptureComponent within MyCustomSceneViewExtension is


myCustomSceneCaptureComponent->bCaptureEveryFrame = true;
myCustomSceneCaptureComponent->bCaptureOnMovement = false;
myCustomSceneCaptureComponent->PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_RenderScenePrimitives;
myCustomSceneCaptureComponent->CaptureSource = SCS_DeviceDepth;

MyRenderTargetTexture = NewObject<UTextureRenderTarget2D>();
MyRenderTargetTexture ->bGPUSharedFlag = true;
MyRenderTargetTexture ->SRGB = false;
MyRenderTargetTexture ->bAutoGenerateMips = false;
MyRenderTargetTexture ->CompressionSettings = TC_Default;
MyRenderTargetTexture ->TargetGamma = GEngine->GetDisplayGamma();
MyRenderTargetTexture ->AddressX = TextureAddress::TA_Clamp;
MyRenderTargetTexture ->AddressY = TextureAddress::TA_Clamp;
MyRenderTargetTexture ->RenderTargetFormat = RTF_RGBA8;
MyRenderTargetTexture ->InitAutoFormat(1024, 768);
MyRenderTargetTexture ->UpdateResourceImmediate();
myCustomSceneCaptureComponent->TextureTarget = MyRenderTargetTexture;

Then I want to use the previousRenderTargetTexture to track the one frame before the current frame (Warning: But the “frame” that I’m referring to is not actual delta time I think, I just wanted to experiment, whether I can get the velocity value). Also, delta time will be sent to the second pass of my second-pixel shader.

I know it seems like a spaghetti as I’ve been posting this, but I would be very appreciate for any help on

  1. Getting the Depth Value in global shader (Complete Example)
  2. Getting the velocity between two rendertarget value (previous - current) / deltatime (To be exact, tracking the rendertargets between frames)
1 Like

Did you get anywhere with this?

I’ve been playing with using a scene capture component in scene view extension as a way to do something akin to depth stencil, but since I’m in mobile LDR I don’t have any of those buffers. So, I figure I’ll use a scene capture with an actor list, or perhaps I can manually gather all prims with depth stencil values somehow? Ideally, I don’t want to have to write a manager for the actor list, but I’ll live if I have to.

I’d like to see more of your set up for where and how you’ve added a scene capture component. How are you lining it up with the player camera and matching it’s settings?