diff --git a/Source/Editor/Windows/GraphicsQualityWindow.cs b/Source/Editor/Windows/GraphicsQualityWindow.cs
index 9ece021c5..3442a4e7c 100644
--- a/Source/Editor/Windows/GraphicsQualityWindow.cs
+++ b/Source/Editor/Windows/GraphicsQualityWindow.cs
@@ -64,6 +64,14 @@ namespace FlaxEditor.Windows
set => Graphics.VolumetricFogQuality = value;
}
+ [DefaultValue(Quality.High)]
+ [EditorOrder(1280), EditorDisplay("Quality"), Tooltip("The Global SDF quality. Controls the volume texture resolution and amount of cascades to use.")]
+ public Quality GlobalSDFQuality
+ {
+ get => Graphics.GlobalSDFQuality;
+ set => Graphics.GlobalSDFQuality = value;
+ }
+
[DefaultValue(Quality.Medium)]
[EditorOrder(1300), EditorDisplay("Quality", "Shadows Quality"), Tooltip("The shadows quality.")]
public Quality ShadowsQuality
diff --git a/Source/Engine/Core/Config/GraphicsSettings.cpp b/Source/Engine/Core/Config/GraphicsSettings.cpp
index c411fe969..f3e08b63b 100644
--- a/Source/Engine/Core/Config/GraphicsSettings.cpp
+++ b/Source/Engine/Core/Config/GraphicsSettings.cpp
@@ -13,4 +13,5 @@ void GraphicsSettings::Apply()
Graphics::ShadowsQuality = ShadowsQuality;
Graphics::ShadowMapsQuality = ShadowMapsQuality;
Graphics::AllowCSMBlending = AllowCSMBlending;
+ Graphics::GlobalSDFQuality = GlobalSDFQuality;
}
diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h
index 53bf89a61..0ec2b26b1 100644
--- a/Source/Engine/Core/Config/GraphicsSettings.h
+++ b/Source/Engine/Core/Config/GraphicsSettings.h
@@ -68,6 +68,12 @@ public:
API_FIELD(Attributes="EditorOrder(2000), EditorDisplay(\"Global SDF\")")
bool EnableGlobalSDF = false;
+ ///
+ /// The Global SDF quality. Controls the volume texture resolution and amount of cascades to use.
+ ///
+ API_FIELD(Attributes="EditorOrder(2005), DefaultValue(Quality.High), EditorDisplay(\"Quality\")")
+ Quality GlobalSDFQuality = Quality::High;
+
#if USE_EDITOR
///
/// 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).
diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp
index a1004064a..4cdbf9eb2 100644
--- a/Source/Engine/Graphics/Graphics.cpp
+++ b/Source/Engine/Graphics/Graphics.cpp
@@ -14,6 +14,7 @@ Quality Graphics::VolumetricFogQuality = Quality::High;
Quality Graphics::ShadowsQuality = Quality::Medium;
Quality Graphics::ShadowMapsQuality = Quality::Medium;
bool Graphics::AllowCSMBlending = false;
+Quality Graphics::GlobalSDFQuality = Quality::High;
#if GRAPHICS_API_NULL
extern GPUDevice* CreateGPUDeviceNull();
diff --git a/Source/Engine/Graphics/Graphics.h b/Source/Engine/Graphics/Graphics.h
index 986623b1f..a39c89fd9 100644
--- a/Source/Engine/Graphics/Graphics.h
+++ b/Source/Engine/Graphics/Graphics.h
@@ -53,6 +53,11 @@ public:
///
API_FIELD() static bool AllowCSMBlending;
+ ///
+ /// The Global SDF quality. Controls the volume texture resolution and amount of cascades to use.
+ ///
+ API_FIELD() static Quality GlobalSDFQuality;
+
public:
///
diff --git a/Source/Engine/Graphics/Materials/MaterialParams.cpp b/Source/Engine/Graphics/Materials/MaterialParams.cpp
index 87d4193ef..a118526cf 100644
--- a/Source/Engine/Graphics/Materials/MaterialParams.cpp
+++ b/Source/Engine/Graphics/Materials/MaterialParams.cpp
@@ -488,8 +488,7 @@ void MaterialParameter::Bind(BindMeta& meta) const
GlobalSignDistanceFieldPass::BindingData bindingData;
if (GlobalSignDistanceFieldPass::Instance()->Get(meta.Buffers, bindingData))
Platform::MemoryClear(&bindingData, sizeof(bindingData));
- for (int32 i = 0; i < 4; i++)
- meta.Context->BindSR(_registerIndex + i, bindingData.Cascades[i] ? bindingData.Cascades[i]->ViewVolume() : nullptr);
+ bindingData.BindCascades(meta.Context, _registerIndex);
*((GlobalSignDistanceFieldPass::ConstantsData*)(meta.Constants.Get() + _offset)) = bindingData.Constants;
break;
}
diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
index f471cb89a..0e2a9ce7a 100644
--- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
+++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
@@ -456,10 +456,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
{
PROFILE_GPU_CPU("Probes Classification");
uint32 threadGroups = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE);
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i, bindingDataSDF.Cascades[i]->ViewVolume());
- }
+ bindingDataSDF.BindCascades(context, 0);
context->BindUA(0, ddgiData.Result.ProbesState);
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
{
@@ -501,11 +498,8 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
// Global SDF with Global Surface Atlas software raytracing (thread X - per probe ray, thread Y - per probe)
ASSERT_LOW_LAYER((probeRaysCount % DDGI_TRACE_RAYS_GROUP_SIZE_X) == 0);
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i, bindingDataSDF.Cascades[i]->ViewVolume());
- context->BindSR(i + 4, bindingDataSDF.CascadeMips[i]->ViewVolume());
- }
+ bindingDataSDF.BindCascades(context, 0);
+ bindingDataSDF.BindCascadeMips(context, 4);
context->BindSR(8, bindingDataSurfaceAtlas.Chunks ? bindingDataSurfaceAtlas.Chunks->View() : nullptr);
context->BindSR(9, bindingDataSurfaceAtlas.CulledObjects ? bindingDataSurfaceAtlas.CulledObjects->View() : nullptr);
context->BindSR(10, bindingDataSurfaceAtlas.AtlasDepth->View());
diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
index eb89f0372..446981076 100644
--- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
+++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
@@ -753,11 +753,8 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
context->BindSR(2, surfaceAtlasData.AtlasGBuffer2->View());
context->BindSR(3, surfaceAtlasData.AtlasDepth->View());
context->BindSR(4, _objectsBuffer->GetBuffer()->View());
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i + 5, bindingDataSDF.Cascades[i]->ViewVolume());
- context->BindSR(i + 9, bindingDataSDF.CascadeMips[i]->ViewVolume());
- }
+ bindingDataSDF.BindCascades(context, 5);
+ bindingDataSDF.BindCascadeMips(context, 9);
context->BindCB(0, _cb0);
Data0 data;
data.ViewWorldPos = renderContext.View.Position;
@@ -921,11 +918,8 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
context->UpdateCB(_cb0, &data);
context->BindCB(0, _cb0);
}
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i, bindingDataSDF.Cascades[i]->ViewVolume());
- context->BindSR(i + 4, bindingDataSDF.CascadeMips[i]->ViewVolume());
- }
+ bindingDataSDF.BindCascades(context, 0);
+ bindingDataSDF.BindCascadeMips(context, 4);
context->BindSR(8, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
context->BindSR(9, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
context->BindSR(10, bindingData.AtlasDepth->View());
@@ -954,11 +948,8 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
context->ResetRenderTarget();
// Rebind resources
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i, bindingDataSDF.Cascades[i]->ViewVolume());
- context->BindSR(i + 4, bindingDataSDF.CascadeMips[i]->ViewVolume());
- }
+ bindingDataSDF.BindCascades(context, 0);
+ bindingDataSDF.BindCascadeMips(context, 4);
context->BindSR(8, bindingData.Chunks ? bindingData.Chunks->View() : nullptr);
context->BindSR(9, bindingData.CulledObjects ? bindingData.CulledObjects->View() : nullptr);
context->BindSR(10, bindingData.AtlasDepth->View());
diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
index d9682867b..a9346ca2c 100644
--- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
+++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp
@@ -7,6 +7,7 @@
#include "Engine/Engine/Engine.h"
#include "Engine/Content/Content.h"
#include "Engine/Graphics/GPUDevice.h"
+#include "Engine/Graphics/Graphics.h"
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Graphics/RenderTargetPool.h"
@@ -173,7 +174,8 @@ struct CascadeData
class GlobalSignDistanceFieldCustomBuffer : public RenderBuffers::CustomBuffer, public ISceneRenderingListener
{
public:
- CascadeData Cascades[4];
+ int32 Resolution = 0;
+ Array> Cascades;
HashSet ObjectTypes;
HashSet SDFTextures;
GlobalSignDistanceFieldPass::BindingData Result;
@@ -349,6 +351,18 @@ void GlobalSignDistanceFieldPass::Dispose()
ChunksCache.SetCapacity(0);
}
+void GlobalSignDistanceFieldPass::BindingData::BindCascades(GPUContext* context, int32 srvSlot)
+{
+ for (int32 i = 0; i < 4; i++)
+ context->BindSR(srvSlot + i, Cascades[i] ? Cascades[i]->ViewVolume() : nullptr);
+}
+
+void GlobalSignDistanceFieldPass::BindingData::BindCascadeMips(GPUContext* context, int32 srvSlot)
+{
+ for (int32 i = 0; i < 4; i++)
+ context->BindSR(srvSlot + i, CascadeMips[i] ? CascadeMips[i]->ViewVolume() : nullptr);
+}
+
bool GlobalSignDistanceFieldPass::Get(const RenderBuffers* buffers, BindingData& result)
{
auto* sdfData = buffers ? buffers->FindCustomBuffer(TEXT("GlobalSignDistanceField")) : nullptr;
@@ -379,49 +393,71 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
sdfData.LastFrameUsed = currentFrame;
PROFILE_GPU_CPU("Global SDF");
- // TODO: configurable via graphics settings
- const int32 resolution = 256;
+ // Setup options
+ int32 resolution, cascadesCount;
+ switch (Graphics::GlobalSDFQuality)
+ {
+ case Quality::Low:
+ resolution = 128;
+ cascadesCount = 2;
+ break;
+ case Quality::Medium:
+ resolution = 128;
+ cascadesCount = 3;
+ break;
+ case Quality::High:
+ resolution = 192;
+ cascadesCount = 4;
+ break;
+ case Quality::Ultra:
+ default:
+ resolution = 256;
+ cascadesCount = 4;
+ break;
+ }
const int32 resolutionMip = Math::DivideAndRoundUp(resolution, GLOBAL_SDF_RASTERIZE_MIP_FACTOR);
- // TODO: configurable via postFx settings
- const int32 cascadesCount = 4; // in range 1-4
const float distance = true ? 20000.0f : 16000.0f; // TODO: switch based if using GI, then use GI range
- const float cascadesDistanceScales[] = { 1.0f, 2.0f, 4.0f, 8.0f };
+ const float cascadesDistanceScales[] = { 1.0f, 2.5f, 5.0f, 10.0f };
const float distanceExtent = distance / cascadesDistanceScales[cascadesCount - 1];
// Initialize buffers
- auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
bool updated = false;
- for (auto& cascade : sdfData.Cascades)
+ if (sdfData.Cascades.Count() != cascadesCount || sdfData.Resolution != resolution)
{
- GPUTexture*& texture = cascade.Texture;
- if (texture && texture->Width() != desc.Width)
+ sdfData.Cascades.Resize(cascadesCount);
+ sdfData.Resolution = resolution;
+ updated = true;
+ auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
+ for (auto& cascade : sdfData.Cascades)
{
- RenderTargetPool::Release(texture);
- texture = nullptr;
- }
- if (!texture)
- {
- texture = RenderTargetPool::Get(desc);
+ GPUTexture*& texture = cascade.Texture;
+ if (texture && texture->Width() != desc.Width)
+ {
+ RenderTargetPool::Release(texture);
+ texture = nullptr;
+ }
if (!texture)
- return true;
- updated = true;
+ {
+ texture = RenderTargetPool::Get(desc);
+ if (!texture)
+ return true;
+ }
}
- }
- desc = GPUTextureDescription::New3D(resolutionMip, resolutionMip, resolutionMip, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
- for (auto& cascade : sdfData.Cascades)
- {
- GPUTexture*& texture = cascade.Mip;
- if (texture && texture->Width() != desc.Width)
+ desc.Width = desc.Height = desc.Depth = resolutionMip;
+ for (auto& cascade : sdfData.Cascades)
{
- RenderTargetPool::Release(texture);
- texture = nullptr;
- }
- if (!texture)
- {
- texture = RenderTargetPool::Get(desc);
+ GPUTexture*& texture = cascade.Mip;
+ if (texture && texture->Width() != desc.Width)
+ {
+ RenderTargetPool::Release(texture);
+ texture = nullptr;
+ }
if (!texture)
- return true;
- updated = true;
+ {
+ texture = RenderTargetPool::Get(desc);
+ if (!texture)
+ return true;
+ }
}
}
GPUTexture* tmpMip = nullptr;
@@ -451,7 +487,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
bool anyDraw = false;
const uint64 cascadeFrequencies[] = { 2, 3, 5, 11 };
//const uint64 cascadeFrequencies[] = { 1, 1, 1, 1 };
- for (int32 cascadeIndex = 0; cascadeIndex < 4; cascadeIndex++)
+ for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
{
// Reduce frequency of the updates
if (useCache && (Engine::FrameCount % cascadeFrequencies[cascadeIndex]) != 0)
@@ -513,12 +549,13 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
{
anyDraw = true;
context->ResetSR();
+ auto desc = GPUTextureDescription::New3D(resolution, resolution, resolution, GLOBAL_SDF_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess, 1);
tmpMip = RenderTargetPool::Get(desc);
if (!tmpMip)
return true;
}
ModelsRasterizeData data;
- data.CascadeCoordToPosMul = cascadeBounds.GetSize() / resolution;
+ data.CascadeCoordToPosMul = cascadeBounds.GetSize() / (float)resolution;
data.CascadeCoordToPosAdd = cascadeBounds.Minimum + cascadeVoxelSize * 0.5f;
data.MaxDistance = cascadeMaxDistance;
data.CascadeResolution = resolution;
@@ -725,8 +762,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
// Copy results
static_assert(ARRAY_COUNT(result.Cascades) == ARRAY_COUNT(sdfData.Cascades), "Invalid cascades count.");
static_assert(ARRAY_COUNT(result.CascadeMips) == ARRAY_COUNT(sdfData.Cascades), "Invalid cascades count.");
- static_assert(ARRAY_COUNT(sdfData.Cascades) == 4, "Invalid cascades count.");
- for (int32 cascadeIndex = 0; cascadeIndex < 4; cascadeIndex++)
+ for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
{
auto& cascade = sdfData.Cascades[cascadeIndex];
const float cascadeDistance = distanceExtent * cascadesDistanceScales[cascadeIndex];
@@ -738,7 +774,15 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
result.Cascades[cascadeIndex] = cascade.Texture;
result.CascadeMips[cascadeIndex] = cascade.Mip;
}
+ for (int32 cascadeIndex = cascadesCount; cascadeIndex < 4; cascadeIndex++)
+ {
+ result.Constants.CascadePosDistance[cascadeIndex] = result.Constants.CascadePosDistance[cascadesCount - 1];
+ result.Constants.CascadeVoxelSize.Raw[cascadeIndex] = result.Constants.CascadeVoxelSize.Raw[cascadesCount - 1];
+ result.Cascades[cascadeIndex] = nullptr;
+ result.CascadeMips[cascadeIndex] = nullptr;
+ }
result.Constants.Resolution = (float)resolution;
+ result.Constants.CascadesCount = cascadesCount;
sdfData.Result = result;
return false;
}
@@ -765,11 +809,8 @@ void GlobalSignDistanceFieldPass::RenderDebug(RenderContext& renderContext, GPUC
context->UpdateCB(_cb0, &data);
context->BindCB(0, _cb0);
}
- for (int32 i = 0; i < 4; i++)
- {
- context->BindSR(i, bindingData.Cascades[i]->ViewVolume());
- context->BindSR(i + 4, bindingData.CascadeMips[i]->ViewVolume());
- }
+ bindingData.BindCascades(context, 0);
+ bindingData.BindCascadeMips(context, 4);
context->SetState(_psDebug);
context->SetRenderTarget(output->View());
context->SetViewportAndScissors(outputSize.X, outputSize.Y);
diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.h b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.h
index 5e1f0461a..df3f730cc 100644
--- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.h
+++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.h
@@ -15,7 +15,8 @@ public:
{
Vector4 CascadePosDistance[4];
Vector4 CascadeVoxelSize;
- Vector3 Padding;
+ Vector2 Padding;
+ uint32 CascadesCount;
float Resolution;
});
@@ -25,6 +26,9 @@ public:
GPUTexture* Cascades[4];
GPUTexture* CascadeMips[4];
ConstantsData Constants;
+
+ void BindCascades(GPUContext* context, int32 srvSlot);
+ void BindCascadeMips(GPUContext* context, int32 srvSlot);
};
private:
diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader
index 08a3525e1..70cb92834 100644
--- a/Source/Shaders/GI/DDGI.shader
+++ b/Source/Shaders/GI/DDGI.shader
@@ -181,7 +181,7 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID)
{
// Sample Global Surface Atlas to get the lighting at the hit location
float3 hitPosition = hit.GetHitPosition(trace);
- float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(hit);
+ float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(GlobalSDF, hit);
float4 surfaceColor = SampleGlobalSurfaceAtlas(GlobalSurfaceAtlas, GlobalSurfaceAtlasChunks, GlobalSurfaceAtlasCulledObjects, GlobalSurfaceAtlasDepth, GlobalSurfaceAtlasTex, hitPosition, -probeRayDirection, surfaceThreshold);
radiance = float4(surfaceColor.rgb, hit.HitTime);
diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.shader b/Source/Shaders/GI/GlobalSurfaceAtlas.shader
index 194375636..30f455675 100644
--- a/Source/Shaders/GI/GlobalSurfaceAtlas.shader
+++ b/Source/Shaders/GI/GlobalSurfaceAtlas.shader
@@ -293,7 +293,7 @@ float4 PS_Debug(Quad_VS2PS input) : SV_Target
if (hit.IsHit())
{
// Sample Global Surface Atlas at the hit location
- float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(hit);
+ float surfaceThreshold = GetGlobalSurfaceAtlasThreshold(GlobalSDF, hit);
color = SampleGlobalSurfaceAtlas(GlobalSurfaceAtlas, GlobalSurfaceAtlasChunks, GlobalSurfaceAtlasCulledObjects, GlobalSurfaceAtlasDepth, GlobalSurfaceAtlasTex, hit.GetHitPosition(trace), -viewRay, surfaceThreshold).rgb;
//color = hit.HitNormal * 0.5f + 0.5f;
}
diff --git a/Source/Shaders/GlobalSignDistanceField.hlsl b/Source/Shaders/GlobalSignDistanceField.hlsl
index 6ee0efc75..e7b4c99c1 100644
--- a/Source/Shaders/GlobalSignDistanceField.hlsl
+++ b/Source/Shaders/GlobalSignDistanceField.hlsl
@@ -13,7 +13,8 @@ struct GlobalSDFData
{
float4 CascadePosDistance[4];
float4 CascadeVoxelSize;
- float3 Padding;
+ float2 Padding;
+ uint CascadesCount;
float Resolution;
};
@@ -65,7 +66,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D tex[4], float3
if (distance <= 0.0f)
return GLOBAL_SDF_WORLD_SIZE;
UNROLL
- for (uint cascade = 0; cascade < 4; cascade++)
+ for (uint cascade = 0; cascade < data.CascadesCount; cascade++)
{
float4 cascadePosDistance = data.CascadePosDistance[cascade];
float cascadeMaxDistance = cascadePosDistance.w * 2;
@@ -89,7 +90,7 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D tex[4]
if (data.CascadePosDistance[3].w <= 0.0f)
return gradient;
UNROLL
- for (uint cascade = 0; cascade < 4; cascade++)
+ for (uint cascade = 0; cascade < data.CascadesCount; cascade++)
{
float4 cascadePosDistance = data.CascadePosDistance[cascade];
float cascadeMaxDistance = cascadePosDistance.w * 2;
@@ -124,7 +125,7 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D tex[4]
float traceMaxDistance = min(trace.MaxDistance, data.CascadePosDistance[3].w * 2);
float3 traceEndPosition = trace.WorldPosition + trace.WorldDirection * traceMaxDistance;
UNROLL
- for (uint cascade = 0; cascade < 4 && hit.HitTime < 0.0f; cascade++)
+ for (uint cascade = 0; cascade < data.CascadesCount && hit.HitTime < 0.0f; cascade++)
{
float4 cascadePosDistance = data.CascadePosDistance[cascade];
float cascadeMaxDistance = cascadePosDistance.w * 2;
@@ -206,8 +207,8 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D tex[4]
}
// Calculates the surface threshold for Global Surface Atlas sampling which matches the Global SDF trace to reduce artifacts
-float GetGlobalSurfaceAtlasThreshold(GlobalSDFHit hit)
+float GetGlobalSurfaceAtlasThreshold(const GlobalSDFData data, const GlobalSDFHit hit)
{
- // Scale the threshold based on the hit cascade (less precision)
- return hit.HitCascade * 20.0f + 25.0f;
+ // Scale the threshold based on the hit cascade (less precision)
+ return data.CascadeVoxelSize[hit.HitCascade] * 1.1f;
}