Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/PostProcess/VisualizeMotionVectors.cpp
guillaume abadie 9f963239c8 Implements UMaterial::bHasPixelAnimation
TSR's anti-flickering heuristic (r.TSR.ShadingRejection.Flickering=1) analyses how opaque pixels changes overtime and whenever the period of changes get lower than r.TSR.ShadingRejection.Flickering.Period, the heuristic tries to stabilise the pixel by relaxing the rejections.

The problems this creates is that any fast moving texture paning and other pixel animation made in material might looks identically flickering to TSR, because not knowing the motion of the pixels animations. TSR currently not having optical flow yet, the artists needs a way to say that the velocity buffer containing the geometric velocities used for reprojection actually exclude pixel animations.

This changes implements UMaterial::bHasPixelAnimation the artists can define on opaque geometry. It end up encoded forcing the primitive to draws velocity so that bit can be encoded in velocity buffer when VELOCITY_ENCODE_DEPTH==1 because there is no room left in stencil or gbuffer, and this has the advantage to works for both forward and deferred shading renderer.

This gets passdown to shaders through in the primitive uniform parameters so that nanite global shaders FEmitSceneDepthPS and FDepthExportCS can encode it when writing out velocity. It also allows to not need to compile additional material shader permutation of FVelocityPS for non masked opaque geometry. But this causes the limitation currently that any primitive that have at least one shader with this setting enabled will force the entire primitive's material slots to draw this bit in the velocity.

TSR in turn disables it's r.TSR.ShadingRejection.Flickering=1 heuristic on any pixel that have it sets using DecodeHasPixelAnimationFromVelocityTexture().

The flag can be visualized by artists with the VisualizeTemporalUpscaler show flag.

#rb jeremy.moore
#jira UE-187459

[CL 27385162 by guillaume abadie in ue5-main branch]
2023-08-25 14:12:42 -04:00

120 lines
5.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PostProcess/VisualizeMotionVectors.h"
#include "PostProcess/PostProcessing.h"
#include "ScenePrivate.h"
#include "ScreenPass.h"
#include "PixelShaderUtils.h"
class FVisualizeMotionVectorsPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FVisualizeMotionVectorsPS);
SHADER_USE_PARAMETER_STRUCT(FVisualizeMotionVectorsPS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, VelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevColorTexture)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, Color)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, Velocity)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, PrevColor)
SHADER_PARAMETER_SAMPLER(SamplerState, ColorSampler)
SHADER_PARAMETER_SAMPLER(SamplerState, VelocitySampler)
SHADER_PARAMETER_SAMPLER(SamplerState, DepthSampler)
SHADER_PARAMETER_SAMPLER(SamplerState, PrevColorSampler)
SHADER_PARAMETER(FScreenTransform, SvPositionToVelocity)
SHADER_PARAMETER(FScreenTransform, SvPositionToColor)
SHADER_PARAMETER(FScreenTransform, SvPositionToScreenPos)
SHADER_PARAMETER(FScreenTransform, PrevScreenPosToPrevColor)
SHADER_PARAMETER(int32, VisualizeType)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
};
IMPLEMENT_GLOBAL_SHADER(FVisualizeMotionVectorsPS, "/Engine/Private/MotionBlur/VisualizeMotionVectors.usf", "MainPS", SF_Pixel);
FScreenPassTexture AddVisualizeMotionVectorsPass(FRDGBuilder& GraphBuilder, const FViewInfo& View, const FVisualizeMotionVectorsInputs& Inputs, EVisualizeMotionVectors Visualize)
{
check(Inputs.SceneColor.IsValid());
check(Inputs.SceneDepth.IsValid());
check(Inputs.SceneVelocity.IsValid());
checkf(Inputs.SceneDepth.ViewRect == Inputs.SceneVelocity.ViewRect, TEXT("The implementation requires that depth and velocity have the same viewport."));
FScreenPassTexture PrevColor;
if (View.PrevViewInfo.VisualizeMotionVectors.IsValid())
{
PrevColor.Texture = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.VisualizeMotionVectors);
PrevColor.ViewRect = View.PrevViewInfo.VisualizeMotionVectorsRect;
}
else
{
PrevColor.Texture = GSystemTextures.GetBlackDummy(GraphBuilder);
PrevColor.ViewRect = FIntRect(0, 0, 1, 1);
}
FScreenPassRenderTarget Output = Inputs.OverrideOutput;
{
if (!Output.IsValid())
{
Output = FScreenPassRenderTarget::CreateFromInput(GraphBuilder, Inputs.SceneColor, View.GetOverwriteLoadAction(), TEXT("MotionVectors.Visualize"));
}
FVisualizeMotionVectorsPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FVisualizeMotionVectorsPS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ColorTexture = Inputs.SceneColor.Texture;
PassParameters->DepthTexture = Inputs.SceneDepth.Texture;
PassParameters->VelocityTexture = Inputs.SceneVelocity.Texture;
PassParameters->PrevColorTexture = PrevColor.Texture;
PassParameters->Color = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(Inputs.SceneColor));
PassParameters->Velocity = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(Inputs.SceneDepth));
PassParameters->PrevColor = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(PrevColor));
PassParameters->ColorSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PassParameters->VelocitySampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PassParameters->DepthSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PassParameters->PrevColorSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
FScreenTransform SvPositionToViewportUV = FScreenTransform::SvPositionToViewportUV(Output.ViewRect);
PassParameters->SvPositionToColor = (
SvPositionToViewportUV *
FScreenTransform::ChangeTextureBasisFromTo(Inputs.SceneColor, FScreenTransform::ETextureBasis::ViewportUV, FScreenTransform::ETextureBasis::TextureUV));
PassParameters->SvPositionToVelocity = (
SvPositionToViewportUV *
FScreenTransform::ChangeTextureBasisFromTo(Inputs.SceneDepth, FScreenTransform::ETextureBasis::ViewportUV, FScreenTransform::ETextureBasis::TextureUV));
PassParameters->SvPositionToScreenPos = (
SvPositionToViewportUV *
FScreenTransform::ViewportUVToScreenPos);
PassParameters->PrevScreenPosToPrevColor = (
FScreenTransform::ChangeTextureBasisFromTo(PrevColor, FScreenTransform::ETextureBasis::ScreenPosition, FScreenTransform::ETextureBasis::TextureUV));
PassParameters->VisualizeType = int32(Visualize);
PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();
TShaderMapRef<FVisualizeMotionVectorsPS> PixelShader(View.ShaderMap);
FPixelShaderUtils::AddFullscreenPass(
GraphBuilder,
View.ShaderMap,
RDG_EVENT_NAME("VisualizeMotionVectors %dx%d", Output.ViewRect.Width(), Output.ViewRect.Height()),
PixelShader,
PassParameters,
Output.ViewRect);
}
if (View.ViewState && !View.bStatePrevViewInfoIsReadOnly)
{
GraphBuilder.QueueTextureExtraction(Inputs.SceneColor.Texture, &View.ViewState->PrevFrameViewInfo.VisualizeMotionVectors);
View.ViewState->PrevFrameViewInfo.VisualizeMotionVectorsRect = Inputs.SceneColor.ViewRect;
}
return MoveTemp(Output);
}