Add RenderSetup and allow customizing it by gameplay and postfx

This commit is contained in:
Wojciech Figat
2022-12-14 14:03:59 +01:00
parent c17477abff
commit 188428a7a9
13 changed files with 68 additions and 55 deletions

View File

@@ -44,6 +44,13 @@ public:
return GetEnabled();
}
/// <summary>
/// Pre-rendering event called before scene rendering begin. Can be used to perform custom rendering or customize render view/setup.
/// </summary>
virtual void PreRender(GPUContext* context, RenderContext& renderContext)
{
}
/// <summary>
/// Performs custom postFx rendering.
/// </summary>

View File

@@ -371,6 +371,11 @@ public:
/// <param name="renderContext">The rendering context.</param>
virtual void OnPostRender(GPUContext* context, RenderContext& renderContext);
/// <summary>
/// The action called before any rendering to override/customize setup RenderSetup inside RenderList. Can be used to enable eg. Motion Vectors rendering.
/// </summary>
Delegate<RenderContext&> SetupRender;
public:
/// <summary>
/// Gets the rendering render task viewport (before upsampling).

View File

@@ -18,7 +18,7 @@ void RenderView::Prepare(RenderContext& renderContext)
// Check if use TAA (need to modify the projection matrix)
Float2 taaJitter;
NonJitteredProjection = Projection;
if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing)
if (renderContext.List->Setup.UseTemporalAAJitter)
{
// Move to the next frame
const int MaxSampleCount = 8;

View File

@@ -63,11 +63,6 @@ void TAA::Dispose()
_shader = nullptr;
}
bool TAA::NeedMotionVectors(const RenderContext& renderContext)
{
return renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing;
}
void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextureView* output)
{
auto context = GPUDevice::Instance->GetMainContext();

View File

@@ -16,14 +16,6 @@ private:
GPUPipelineState* _psTAA;
public:
/// <summary>
/// Determinates whenever this pass requires motion vectors rendering.
/// </summary>
/// <param name="renderContext">The rendering context.</param>
/// <returns>True if need to render motion vectors, otherwise false.</returns>
static bool NeedMotionVectors(const RenderContext& renderContext);
/// <summary>
/// Performs AA pass rendering for the input task.
/// </summary>

View File

@@ -480,7 +480,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
auto& cascade = ddgiData.Cascades[cascadeIndex];
data.ProbeScrollClears[cascadeIndex] = Int4(cascade.ProbeScrollClears, 0);
}
if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing)
if (renderContext.List->Setup.UseTemporalAAJitter)
{
// Use temporal offset in the dithering factor (gets cleaned out by TAA)
const float time = Time::Draw.UnscaledTime.GetTotalSeconds();

View File

@@ -162,7 +162,7 @@ void MotionBlurPass::RenderMotionVectors(RenderContext& renderContext)
const int32 motionVectorsHeight = screenHeight / static_cast<int32>(settings.MotionVectorsResolution);
// Ensure to have valid data
if (!Renderer::NeedMotionVectors(renderContext) || checkIfSkipPass())
if (!renderContext.List->Setup.UseMotionVectors || checkIfSkipPass())
{
// Skip pass (just clear motion vectors if texture is allocated)
if (motionVectors->IsAllocated())

View File

@@ -10,6 +10,7 @@
#include "DrawCall.h"
#include "RenderListBuffer.h"
#include "RendererAllocation.h"
#include "RenderSetup.h"
enum class StaticFlags;
class RenderBuffers;
@@ -363,6 +364,11 @@ public:
/// </summary>
Array<PostProcessEffect*> PostFx;
/// <summary>
/// The renderer setup for the frame drawing.
/// </summary>
RenderSetup Setup;
/// <summary>
/// The post process settings.
/// </summary>

View File

@@ -0,0 +1,15 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Graphics/RenderTask.h"
/// <summary>
/// The utility container for rendering setup configuration. Allows to properly decide about using certain render features (eg. motion vectors, TAA jitter) before rendering happens.
/// </summary>
struct FLAXENGINE_API RenderSetup
{
RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasingPass;
bool UseMotionVectors = false;
bool UseTemporalAAJitter = false;
};

View File

@@ -5,6 +5,7 @@
#include "Engine/Graphics/RenderTargetPool.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/PostProcessEffect.h"
#include "Engine/Engine/EngineService.h"
#include "GBufferPass.h"
#include "ForwardPass.h"
@@ -224,19 +225,6 @@ void Renderer::Render(SceneRenderTask* task)
RenderList::ReturnToPool(e.List);
}
bool Renderer::NeedMotionVectors(const RenderContext& renderContext)
{
const int32 screenWidth = renderContext.Buffers->GetWidth();
const int32 screenHeight = renderContext.Buffers->GetHeight();
if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut)
return false;
MotionBlurSettings& motionBlurSettings = renderContext.List->Settings.MotionBlur;
return ((renderContext.View.Flags & ViewFlags::MotionBlur) != 0 && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) ||
renderContext.View.Mode == ViewMode::MotionVectors ||
ScreenSpaceReflectionsPass::NeedMotionVectors(renderContext) ||
TAA::NeedMotionVectors(renderContext);
}
void Renderer::DrawSceneDepth(GPUContext* context, SceneRenderTask* task, GPUTexture* output, const Array<Actor*>& customActors)
{
CHECK(context && task && output && output->IsDepthStencil());
@@ -314,20 +302,45 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
aaMode = AntialiasingMode::None; // TODO: support TAA in ortho projection (see RenderView::Prepare to jitter projection matrix better)
renderContext.List->Settings.AntiAliasing.Mode = aaMode;
// Initialize setup
RenderSetup& setup = renderContext.List->Setup;
{
PROFILE_CPU_NAMED("Setup");
if (renderContext.View.Origin != renderContext.View.PrevOrigin)
renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change
const int32 screenWidth = renderContext.Buffers->GetWidth();
const int32 screenHeight = renderContext.Buffers->GetHeight();
setup.UpscaleLocation = renderContext.Task->UpscaleLocation;
if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut)
setup.UseMotionVectors = false;
else
{
const MotionBlurSettings& motionBlurSettings = renderContext.List->Settings.MotionBlur;
const ScreenSpaceReflectionsSettings ssrSettings = renderContext.List->Settings.ScreenSpaceReflections;
setup.UseMotionVectors = ((renderContext.View.Flags & ViewFlags::MotionBlur) != 0 && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) ||
renderContext.View.Mode == ViewMode::MotionVectors ||
(ssrSettings.TemporalEffect && renderContext.View.Flags & ViewFlags::SSR) ||
renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing;
}
setup.UseTemporalAAJitter = aaMode == AntialiasingMode::TemporalAntialiasing;
// Customize setup (by postfx or custom gameplay effects)
renderContext.Task->SetupRender(renderContext);
for (PostProcessEffect* e : renderContext.List->PostFx)
e->PreRender(context, renderContext);
}
// Prepare
renderContext.View.Prepare(renderContext);
if (renderContext.View.Origin != renderContext.View.PrevOrigin)
renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change
renderContext.Buffers->Prepare();
// Build batch of render contexts (main view and shadow projections)
const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode);
const bool needMotionVectors = Renderer::NeedMotionVectors(renderContext);
{
PROFILE_CPU_NAMED("Collect Draw Calls");
view.Pass = DrawPass::GBuffer | DrawPass::Forward | DrawPass::Distortion;
if (needMotionVectors)
if (setup.UseMotionVectors)
view.Pass |= DrawPass::MotionVectors;
renderContextBatch.GetMainContext() = renderContext; // Sync render context in batch with the current value
@@ -372,7 +385,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::GBufferNoDecals);
renderContext.List->SortDrawCalls(renderContext, true, DrawCallsListType::Forward);
renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::Distortion);
if (needMotionVectors)
if (setup.UseMotionVectors)
renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::MotionVectors);
for (int32 i = 1; i < renderContextBatch.Contexts.Count(); i++)
{
@@ -555,7 +568,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
// Upscaling after scene rendering but before post processing
bool useUpscaling = task->RenderingPercentage < 1.0f;
const Viewport outputViewport = task->GetOutputViewport();
if (useUpscaling && task->UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass)
if (useUpscaling && setup.UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass)
{
useUpscaling = false;
RenderTargetPool::Release(tempBuffer);

View File

@@ -33,13 +33,6 @@ public:
/// <param name="task">The scene rendering task.</param>
static void Render(SceneRenderTask* task);
/// <summary>
/// Determinates whenever any pass requires motion vectors rendering.
/// </summary>
/// <param name="renderContext">The rendering context.</param>
/// <returns>True if need to render motion vectors, otherwise false.</returns>
static bool NeedMotionVectors(const RenderContext& renderContext);
public:
/// <summary>

View File

@@ -55,12 +55,6 @@ PACK_STRUCT(struct Data
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
});
bool ScreenSpaceReflectionsPass::NeedMotionVectors(const RenderContext& renderContext)
{
auto& settings = renderContext.List->Settings.ScreenSpaceReflections;
return settings.TemporalEffect && renderContext.View.Flags & ViewFlags::SSR;
}
String ScreenSpaceReflectionsPass::ToString() const
{
return TEXT("ScreenSpaceReflectionsPass");

View File

@@ -36,13 +36,6 @@ private:
AssetReference<Texture> _preIntegratedGF;
public:
/// <summary>
/// Determinates whenever this pass requires motion vectors rendering.
/// </summary>
/// <param name="renderContext">The rendering context.</param>
/// <returns>True if need to render motion vectors, otherwise false.</returns>
static bool NeedMotionVectors(const RenderContext& renderContext);
/// <summary>
/// Perform SSR rendering for the input task (blends reflections to given texture using alpha blending).
/// </summary>