Add option to always render Global SDF

This commit is contained in:
Wojciech Figat
2022-03-24 14:59:14 +01:00
parent 92ab3d005e
commit d5297f9047
5 changed files with 257 additions and 207 deletions

View File

@@ -62,11 +62,17 @@ public:
API_FIELD(Attributes="EditorOrder(1320), DefaultValue(false), EditorDisplay(\"Quality\", \"Allow CSM Blending\")")
bool AllowCSMBlending = false;
/// <summary>
/// If checked, enables Global SDF rendering. This can be used in materials, shaders, and particles.
/// </summary>
API_FIELD(Attributes="EditorOrder(2000), EditorDisplay(\"Global SDF\")")
bool EnableGlobalSDF = false;
#if USE_EDITOR
/// <summary>
/// If checked, the 'Generate SDF' option will be checked on model import options by default. Use it if your project uses Global SDF (eg. for Global Illumination or particles).
/// </summary>
API_FIELD(Attributes="EditorOrder(2000), EditorDisplay(\"Global SDF\")")
API_FIELD(Attributes="EditorOrder(2010), EditorDisplay(\"Global SDF\")")
bool GenerateSDFOnModelImport = false;
#endif

View File

@@ -150,6 +150,17 @@ public:
return _viewport;
}
template<class T>
const T* FindCustomBuffer(const StringView& name) const
{
for (CustomBuffer* e : CustomBuffers)
{
if (e->Name == name)
return (const T*)e;
}
return nullptr;
}
template<class T>
T* GetCustomBuffer(const StringView& name)
{

View File

@@ -110,6 +110,7 @@ public:
GPUTexture* CascadeMips[4] = {};
Vector3 Positions[4];
HashSet<RasterizeChunkKey> NonEmptyChunks[4];
GlobalSignDistanceFieldPass::BindingData Result;
~GlobalSignDistanceFieldCustomBuffer()
{
@@ -212,6 +213,17 @@ void GlobalSignDistanceFieldPass::Dispose()
ChunksCache.SetCapacity(0);
}
bool GlobalSignDistanceFieldPass::Get(const RenderBuffers* buffers, BindingData& result)
{
auto* sdfData = buffers->FindCustomBuffer<GlobalSignDistanceFieldCustomBuffer>(TEXT("GlobalSignDistanceField"));
if (sdfData && sdfData->LastFrameUsed == Engine::FrameCount)
{
result = sdfData->Result;
return false;
}
return true;
}
bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContext* context, BindingData& result)
{
// Skip if not supported
@@ -221,6 +233,16 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
return true;
auto& sdfData = *renderContext.Buffers->GetCustomBuffer<GlobalSignDistanceFieldCustomBuffer>(TEXT("GlobalSignDistanceField"));
// Skip if already done in the current frame
const auto currentFrame = Engine::FrameCount;
if (sdfData.LastFrameUsed == currentFrame)
{
result = sdfData.Result;
return false;
}
PROFILE_GPU_CPU("Global SDF");
// TODO: configurable via graphics settings
const int32 resolution = 256;
const int32 mipFactor = 4;
@@ -229,12 +251,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
const float distanceExtent = 2500.0f;
const float cascadesDistances[] = { distanceExtent, distanceExtent * 2.0f, distanceExtent * 4.0f, distanceExtent * 8.0f };
// Skip if already done in the current frame
const auto currentFrame = Engine::FrameCount;
if (sdfData.LastFrameUsed != currentFrame)
{
PROFILE_GPU_CPU("Global SDF");
// Initialize buffers
sdfData.LastFrameUsed = currentFrame;
auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
@@ -459,7 +475,6 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
context->ResetSR();
context->FlushState();
}
}
// Copy results
static_assert(ARRAY_COUNT(result.Cascades) == ARRAY_COUNT(sdfData.Cascades), "Invalid cascades count.");
@@ -476,6 +491,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
result.GlobalSDF.CascadeVoxelSize.Raw[cascade] = voxelSize;
}
result.GlobalSDF.Resolution = (float)resolution;
sdfData.Result = result;
return false;
}

View File

@@ -46,6 +46,14 @@ private:
BoundingBox _cascadeBounds;
public:
/// <summary>
/// Gets the Global SDF (only if enabled in Graphics Settings).
/// </summary>
/// <param name="buffers">The rendering context buffers.</param>
/// <param name="result">The result Global SDF data for binding to the shaders.</param>
/// <returns>True if there is no valid Global SDF rendered during this frame, otherwise false.</returns>
bool Get(const RenderBuffers* buffers, BindingData& result);
/// <summary>
/// Renders the Global SDF.
/// </summary>

View File

@@ -29,6 +29,7 @@
#include "AntiAliasing/SMAA.h"
#include "Engine/Level/Actor.h"
#include "Engine/Level/Level.h"
#include "Engine/Core/Config/GraphicsSettings.h"
#if USE_EDITOR
#include "Editor/Editor.h"
#include "Editor/QuadOverdrawPass.h"
@@ -289,6 +290,7 @@ void Renderer::DrawPostFxMaterial(GPUContext* context, const RenderContext& rend
void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
{
auto context = GPUDevice::Instance->GetMainContext();
auto* graphicsSettings = GraphicsSettings::Get();
auto& view = renderContext.View;
ASSERT(renderContext.Buffers && renderContext.Buffers->GetWidth() > 0);
@@ -338,6 +340,13 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
}
#endif
// Global SDF rendering (can be used by materials later on)
if (graphicsSettings->EnableGlobalSDF)
{
GlobalSignDistanceFieldPass::BindingData bindingData;
GlobalSignDistanceFieldPass::Instance()->Render(renderContext, context, bindingData);
}
// Fill GBuffer
GBufferPass::Instance()->Fill(renderContext, lightBuffer->View());