Fix TAA jitter in post-resolve passes such as editor primitives and debug gizmos

This commit is contained in:
Wojtek Figat
2024-03-19 16:02:50 +01:00
parent 1a68a52611
commit cf3145273f
6 changed files with 67 additions and 3 deletions

View File

@@ -739,6 +739,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
}
Context->LastViewPos = view.Position;
Context->LastViewProj = view.Projection;
TaaJitterRemoveContext taaJitterRemove(view);
// Fallback to task buffers
if (target == nullptr && renderContext.Task)
@@ -766,7 +767,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
const auto cb = DebugDrawShader->GetShader()->GetCB(0);
Data data;
Matrix vp;
Matrix::Multiply(view.View, view.NonJitteredProjection, vp);
Matrix::Multiply(view.View, view.Projection, vp);
Matrix::Transpose(vp, data.ViewProjection);
data.EnableDepthTest = enableDepthTest;
context->UpdateCB(cb, &data);

View File

@@ -18,6 +18,7 @@ void RenderView::Prepare(RenderContext& renderContext)
// Check if use TAA (need to modify the projection matrix)
Float2 taaJitter;
NonJitteredProjection = Projection;
IsTaaResolved = false;
if (renderContext.List->Setup.UseTemporalAAJitter)
{
// Move to the next frame
@@ -82,6 +83,18 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f
MainScreenSize = mainView->ScreenSize;
}
void RenderView::UpdateCachedData()
{
Matrix::Invert(View, IV);
Matrix::Invert(Projection, IP);
Matrix viewProjection;
Matrix::Multiply(View, Projection, viewProjection);
Frustum.SetMatrix(viewProjection);
Matrix::Invert(viewProjection, IVP);
CullingFrustum = Frustum;
NonJitteredProjection = Projection;
}
void RenderView::SetUp(const Matrix& viewProjection)
{
// Copy data
@@ -201,3 +214,27 @@ void RenderView::GetWorldMatrix(const Transform& transform, Matrix& world) const
const Float3 translation = transform.Translation - Origin;
Matrix::Transformation(transform.Scale, transform.Orientation, translation, world);
}
TaaJitterRemoveContext::TaaJitterRemoveContext(const RenderView& view)
{
if (view.IsTaaResolved)
{
// Cancel-out sub-pixel jitter when drawing geometry after TAA has been resolved
_view = (RenderView*)&view;
_prevProjection = view.Projection;
_prevNonJitteredProjection = view.NonJitteredProjection;
_view->Projection = _prevNonJitteredProjection;
_view->UpdateCachedData();
}
}
TaaJitterRemoveContext::~TaaJitterRemoveContext()
{
if (_view)
{
// Restore projection
_view->Projection = _prevProjection;
_view->UpdateCachedData();
_view->NonJitteredProjection = _prevNonJitteredProjection;
}
}

View File

@@ -117,6 +117,11 @@ public:
/// </summary>
API_FIELD() bool IsCullingDisabled = false;
/// <summary>
/// True if TAA has been resolved when rendering view and frame doesn't contain jitter anymore. Rendering geometry after this point should not use jitter anymore (eg. editor gizmos or custom geometry as overlay).
/// </summary>
API_FIELD() bool IsTaaResolved = false;
/// <summary>
/// The static flags mask used to hide objects that don't have a given static flags. Eg. use StaticFlags::Lightmap to render only objects that can use lightmap.
/// </summary>
@@ -160,7 +165,7 @@ public:
API_FIELD() DEPRECATED float ShadowModelLODDistanceFactor = 1.0f;
/// <summary>
/// The Temporal Anti-Aliasing jitter frame index.
/// Temporal Anti-Aliasing jitter frame index.
/// </summary>
API_FIELD() int32 TaaFrameIndex = 0;
@@ -261,6 +266,11 @@ public:
RenderView& operator=(const RenderView& other) = default;
PRAGMA_ENABLE_DEPRECATION_WARNINGS
/// <summary>
/// Updates the cached data for the view (inverse matrices, etc.).
/// </summary>
void UpdateCachedData();
// Set up view with custom params
// @param viewProjection View * Projection matrix
void SetUp(const Matrix& viewProjection);
@@ -344,3 +354,15 @@ public:
world.M43 -= Origin.Z;
}
};
// Removes TAA jitter from the RenderView when drawing geometry after TAA has been resolved to prevent unwanted jittering.
struct TaaJitterRemoveContext
{
private:
RenderView* _view = nullptr;
Matrix _prevProjection, _prevNonJitteredProjection;
public:
TaaJitterRemoveContext(const RenderView& view);
~TaaJitterRemoveContext();
};

View File

@@ -146,4 +146,7 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu
context->Draw(output);
renderContext.Buffers->TemporalAA = outputHistory;
}
// Mark TAA jitter as resolved for future drawing
(bool&)renderContext.View.IsTaaResolved = true;
}

View File

@@ -652,6 +652,7 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
const auto* batchesData = list.Batches.Get();
const auto context = GPUDevice::Instance->GetMainContext();
bool useInstancing = list.CanUseInstancing && CanUseInstancing(renderContext.View.Pass) && GPUDevice::Instance->Limits.HasInstancing;
TaaJitterRemoveContext taaJitterRemove(renderContext.View);
// Clear SR slots to prevent any resources binding issues (leftovers from the previous passes)
context->ResetSR();

View File

@@ -612,7 +612,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
// Color Grading LUT generation
auto colorGradingLUT = ColorGradingPass::Instance()->RenderLUT(renderContext);
// Post processing
// Post-processing
EyeAdaptationPass::Instance()->Render(renderContext, frameBuffer);
PostProcessingPass::Instance()->Render(renderContext, frameBuffer, tempBuffer, colorGradingLUT);
RenderTargetPool::Release(colorGradingLUT);