Add new temporal upsampling option (TAAU) when using location DuringAntiAliasing

Refactor `RenderingUpscaleLocation` enum item names.
This commit is contained in:
2026-08-13 11:26:27 +02:00
parent 371a7cd091
commit 05ebbe7448
8 changed files with 64 additions and 39 deletions
Binary file not shown.
@@ -104,7 +104,7 @@ namespace FlaxEditor.Windows
set => MainRenderTask.Instance.RenderScale = value;
}
[NoSerialize, DefaultValue(RenderingUpscaleLocation.AfterAntiAliasingPass), VisibleIf(nameof(UpscaleLocation_Visible))]
[NoSerialize, DefaultValue(RenderingUpscaleLocation.DuringAntiAliasing), VisibleIf(nameof(UpscaleLocation_Visible))]
[EditorOrder(1401), EditorDisplay("Quality")]
[Tooltip("The image resolution upscale location within rendering pipeline.")]
public RenderingUpscaleLocation UpscaleLocation
+8 -3
View File
@@ -206,12 +206,17 @@ API_ENUM() enum class RenderingUpscaleLocation
/// <summary>
/// The up-scaling happens directly to the output buffer (backbuffer) after post processing and anti-aliasing.
/// </summary>
AfterAntiAliasingPass = 0,
AfterAntiAliasing = 0,
/// <summary>
/// The up-scaling happens before the post processing after scene rendering (after geometry, lighting, volumetrics, transparency and SSR/SSAO).
/// </summary>
BeforePostProcessingPass = 1,
BeforePostProcessing = 1,
/// <summary>
/// The up-scaling happens during anti-aliasing. For example, when using Temporal Anti-Aliasing (TAA) it work as Temporal Anti-Aliasing Upsampling (TAAU) to both remove aliasing and upscale the image.
/// </summary>
DuringAntiAliasing = 2,
};
/// <summary>
@@ -285,7 +290,7 @@ public:
/// <summary>
/// The image resolution upscale location within rendering pipeline. Unused if RenderingPercentage is 1.
/// </summary>
API_FIELD() RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasingPass;
API_FIELD() RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::DuringAntiAliasing;
public:
/// <summary>
+12 -11
View File
@@ -58,24 +58,26 @@ void TAA::Dispose()
_shader = nullptr;
}
void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextureView* output)
void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTexture* output)
{
auto viewport = Viewport(0, 0, (float)output->Width(), (float)output->Height());
auto inputSize = Float2((float)input->Width(), (float)input->Height());
auto context = GPUDevice::Instance->GetMainContext();
if (checkIfSkipPass())
{
// Resources are missing. Do not perform rendering, just copy source frame.
context->SetRenderTarget(output);
context->SetViewportAndScissors(viewport);
context->SetRenderTarget(output->View());
context->Draw(input);
return;
}
const auto& settings = renderContext.List->Settings.AntiAliasing;
PROFILE_GPU_CPU("Temporal Antialiasing");
// Get history buffers
bool resetHistory = renderContext.Task->IsCameraCut;
renderContext.Buffers->LastFrameTemporalAA = Engine::FrameCount;
const auto tempDesc = GPUTextureDescription::New2D(input->Width(), input->Height(), input->Format());
const auto tempDesc = GPUTextureDescription::New2D(output->Width(), output->Height(), output->Format());
if (renderContext.Buffers->TemporalAA == nullptr)
{
// Missing temporal buffer
@@ -99,13 +101,11 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu
float blendStrength = 1.0f;
if (resetHistory)
{
#if 0
context->CopyTexture(inputHistory, 0, 0, 0, 0, input, 0);
#else
context->SetViewportAndScissors(viewport);
context->SetRenderTarget(inputHistory->View());
// TODO: when using upscalimg, copu history via MultiScaler to reduce aliasing
context->Draw(input);
context->ResetRenderTarget();
#endif
blendStrength = 0.0f;
}
@@ -113,8 +113,8 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu
Data data;
data.ScreenSizeInv.X = renderContext.View.ScreenSize.Z;
data.ScreenSizeInv.Y = renderContext.View.ScreenSize.W;
data.JitterInv.X = renderContext.View.TemporalAAJitter.X / (float)tempDesc.Width;
data.JitterInv.Y = renderContext.View.TemporalAAJitter.Y / (float)tempDesc.Height;
data.JitterInv.X = renderContext.View.TemporalAAJitter.X / inputSize.X;
data.JitterInv.Y = renderContext.View.TemporalAAJitter.Y / inputSize.Y;
data.Sharpness = settings.TAA_Sharpness * 3; // Hardcoded scale
data.StationaryBlending = settings.TAA_StationaryBlending * blendStrength;
data.MotionBlending = settings.TAA_MotionBlending * blendStrength;
@@ -130,7 +130,8 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu
context->BindSR(3, renderContext.Buffers->DepthBuffer);
// Render
context->SetRenderTarget(output);
context->SetViewportAndScissors(viewport);
context->SetRenderTarget(output->View());
int qualityLevel;
switch (Graphics::AAQuality)
{
+1 -1
View File
@@ -21,7 +21,7 @@ public:
/// <param name="renderContext">The rendering context.</param>
/// <param name="input">The input render target.</param>
/// <param name="output">The output render target.</param>
void Render(const RenderContext& renderContext, GPUTexture* input, GPUTextureView* output);
void Render(const RenderContext& renderContext, GPUTexture* input, GPUTexture* output);
private:
#if COMPILE_WITH_DEV_ENV
+1 -1
View File
@@ -9,7 +9,7 @@
/// </summary>
struct FLAXENGINE_API RenderSetup
{
RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasingPass;
RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::DuringAntiAliasing;
bool UseShadows = false;
bool UseMotionVectors = false;
bool UseTemporalAAJitter = false;
+28 -9
View File
@@ -192,7 +192,7 @@ void RenderLightBuffer(const SceneRenderTask* task, GPUContext* context, RenderC
context->ResetRenderTarget();
if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing)
{
TAA::Instance()->Render(renderContext, tempBuffer, lightBuffer->View());
TAA::Instance()->Render(renderContext, tempBuffer, lightBuffer);
Swap(lightBuffer, tempBuffer);
}
RenderTargetPool::Release(lightBuffer);
@@ -387,6 +387,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
const int32 screenWidth = renderContext.Buffers->GetWidth();
const int32 screenHeight = renderContext.Buffers->GetHeight();
setup.UpscaleLocation = renderContext.Task->UpscaleLocation;
if (setup.UpscaleLocation == RenderingUpscaleLocation::DuringAntiAliasing && renderContext.List->Settings.AntiAliasing.Mode != AntialiasingMode::TemporalAntialiasing)
setup.UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasing; // Fall-back when AA doesn't support uplscaling
setup.UseShadows = !isGBufferDebug && EnumHasAnyFlags(view.Flags, ViewFlags::Shadows) && ShadowsPass::Instance()->IsReady();
switch (renderContext.View.Mode)
{
@@ -750,18 +752,35 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::BeforePostProcessingPass, frameBuffer, tempBuffer);
// Temporal Anti-Aliasing (goes before post processing)
if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing)
{
TAA::Instance()->Render(renderContext, frameBuffer, tempBuffer->View());
Swap(frameBuffer, tempBuffer);
}
// Upscaling after scene rendering but before post-processing
PRAGMA_DISABLE_DEPRECATION_WARNINGS
bool useUpscaling = task->RenderingPercentage * task->RenderScale < 1.0f;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
const Viewport outputViewport = task->GetOutputViewport();
if (useUpscaling && setup.UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass)
if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing)
{
if (useUpscaling && setup.UpscaleLocation == RenderingUpscaleLocation::DuringAntiAliasing)
{
// TAAU
useUpscaling = false;
RenderTargetPool::Release(tempBuffer);
tempDesc.Width = (int32)outputViewport.Width;
tempDesc.Height = (int32)outputViewport.Height;
tempBuffer = RenderTargetPool::Get(tempDesc);
context->ResetSR();
TAA::Instance()->Render(renderContext, frameBuffer, tempBuffer);
RenderTargetPool::Release(frameBuffer);
frameBuffer = RenderTargetPool::Get(tempDesc);
}
else
{
// TAA
TAA::Instance()->Render(renderContext, frameBuffer, tempBuffer);
}
Swap(frameBuffer, tempBuffer);
}
// Upscaling after scene rendering but before post-processing
if (useUpscaling && setup.UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessing)
{
useUpscaling = false;
RenderTargetPool::Release(tempBuffer);
+11 -11
View File
@@ -160,9 +160,9 @@ float4 PS(Quad_VS2PS input) : SV_Target0
// Sample image and history
#if UNJITTER_INPUT
float4 current = SAMPLE_RT(Input, input.TexCoord - JitterInv.xy);
float4 current = SAMPLE_RT_LINEAR(Input, input.TexCoord - JitterInv.xy);
#else
float4 current = SAMPLE_RT(Input, input.TexCoord);
float4 current = SAMPLE_RT_LINEAR(Input, input.TexCoord);
#endif
float4 history = SAMPLE_RT_LINEAR(InputHistory, input.TexCoord - velocityDepth.xy);
@@ -176,15 +176,15 @@ float4 PS(Quad_VS2PS input) : SV_Target0
float2 du = float2(ScreenSizeInv.x, 0.0);
float2 dv = float2(0.0, ScreenSizeInv.y);
float4 ctl = SAMPLE_RT(Input, uv - dv - du);
float4 ctc = SAMPLE_RT(Input, uv - dv);
float4 ctr = SAMPLE_RT(Input, uv - dv + du);
float4 cml = SAMPLE_RT(Input, uv - du);
float4 cmc = SAMPLE_RT(Input, uv);
float4 cmr = SAMPLE_RT(Input, uv + du);
float4 cbl = SAMPLE_RT(Input, uv + dv - du);
float4 cbc = SAMPLE_RT(Input, uv + dv);
float4 cbr = SAMPLE_RT(Input, uv + dv + du);
float4 ctl = SAMPLE_RT_LINEAR(Input, uv - dv - du);
float4 ctc = SAMPLE_RT_LINEAR(Input, uv - dv);
float4 ctr = SAMPLE_RT_LINEAR(Input, uv - dv + du);
float4 cml = SAMPLE_RT_LINEAR(Input, uv - du);
float4 cmc = SAMPLE_RT_LINEAR(Input, uv);
float4 cmr = SAMPLE_RT_LINEAR(Input, uv + du);
float4 cbl = SAMPLE_RT_LINEAR(Input, uv + dv - du);
float4 cbc = SAMPLE_RT_LINEAR(Input, uv + dv);
float4 cbr = SAMPLE_RT_LINEAR(Input, uv + dv + du);
float4 cMin = min(ctl, min(ctc, min(ctr, min(cml, min(cmc, min(cmr, min(cbl, min(cbc, cbr))))))));
float4 cMax = max(ctl, max(ctc, max(ctr, max(cml, max(cmc, max(cmr, max(cbl, max(cbc, cbr))))))));