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
- Getting the Depth Value in global shader (Complete Example)
- Getting the velocity between two rendertarget value (previous - current) / deltatime (To be exact, tracking the rendertargets between frames)