hi, here’s a small contribution from me:
one of hallatore’s contributions was about modifying the CurrentFrameWeight based on the camera movement. this one was the most effective method to reduce ghosting in my use case (or rather, a controllable aliasing vs ghosting tradeoff). however it had 3 downsides:
- per-frame logspam
- having to pass stuff from the CPU (via blueprint) to the renderer every frame
- taking over and invalidating anything you put into both r.TemporalAACurrentFrameWeight and r.Tonemapper.Sharpen
sadly it didn’t make it past that initial blueprint proof of concept, so I’ve just taken the concept and implemented it directly into the engine. however I took just the part about the CurrentFrameWeight and ignored the tonemapper sharpen entirely (so I expect this could work great side-by-side with the latest TemporalAASharpen from this thread
unfortunately I don’t know my way about git and having an own repo/fork etc, so I’ll just post the code here in hopes that someone picks it up
I’ve added a few lines that go before the new code so it’s easier to find in case the line numbers have changed (I’m using 4.17). everything goes in PostProcessTemporalAA.cpp
// existing code, line 41
static TAutoConsoleVariable<float> CVarTemporalAACurrentFrameWeight(
TEXT("r.TemporalAACurrentFrameWeight"),
.04f,
TEXT("Weight of current frame's contribution to the history. Low values cause blurriness and ghosting, high values fail to hide jittering."),
ECVF_Scalability | ECVF_RenderThreadSafe);
// add new code
static TAutoConsoleVariable<float> CVarTemporalAACurrentFrameWeightMax (
TEXT("r.TemporalAACurrentFrameWeightMax"),
.5f,
TEXT("Max Weight of current frame's contribution to the history."),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<float> CVarTemporalAAFrameWeightThreshold(
TEXT("r.TemporalAAFrameWeightThreshold"),
250.0f,
TEXT("Threshold to blend between TemporalAACurrentFrameWeight and TemporalAACurrentFrameWeightMax."),
ECVF_Scalability | ECVF_RenderThreadSafe);
// existing code, line 73
/** Default constructor. */
FPostProcessTemporalAAPS() {}
// add new code
FVector PrevFrameCameraLoc;
// existing code, line 192
const bool bIgnoreVelocity = (ViewState && ViewState->bSequencerIsPaused);
SetShaderValue(Context.RHICmdList, ShaderRHI, VelocityScaling, bIgnoreVelocity ? 0.0f : 1.0f);
// remove this code
SetShaderValue(Context.RHICmdList, ShaderRHI, CurrentFrameWeight, CVarTemporalAACurrentFrameWeight.GetValueOnRenderThread());
// add new code
const float frameBlend = FMath::Min(FVector(Context.View.ViewLocation - PrevFrameCameraLoc).SizeSquared(), CVarTemporalAAFrameWeightThreshold.GetValueOnRenderThread()) / CVarTemporalAAFrameWeightThreshold.GetValueOnRenderThread();
const float newFrameWeight = FMath::Lerp(CVarTemporalAACurrentFrameWeight.GetValueOnRenderThread(), CVarTemporalAACurrentFrameWeightMax.GetValueOnRenderThread(), frameBlend);
SetShaderValue(Context.RHICmdList, ShaderRHI, CurrentFrameWeight, newFrameWeight);
PrevFrameCameraLoc = Context.View.ViewLocation;
an option to make it more friendly to Epic’s policy (and more likely to be accepted as a pull request), would be to only make the blend (vs falling back to the old code) if TemporalAACurrentFrameWeightMax is above 0.0f - and the default value could be set to 0.0f instead, thus disabling the code out of the box