Add Global SDF quality setting and support for variable cascades count and resolution
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -13,4 +13,5 @@ void GraphicsSettings::Apply()
|
||||
Graphics::ShadowsQuality = ShadowsQuality;
|
||||
Graphics::ShadowMapsQuality = ShadowMapsQuality;
|
||||
Graphics::AllowCSMBlending = AllowCSMBlending;
|
||||
Graphics::GlobalSDFQuality = GlobalSDFQuality;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(2000), EditorDisplay(\"Global SDF\")")
|
||||
bool EnableGlobalSDF = false;
|
||||
|
||||
/// <summary>
|
||||
/// The Global SDF quality. Controls the volume texture resolution and amount of cascades to use.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(2005), DefaultValue(Quality.High), EditorDisplay(\"Quality\")")
|
||||
Quality GlobalSDFQuality = Quality::High;
|
||||
|
||||
#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).
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -53,6 +53,11 @@ public:
|
||||
/// </summary>
|
||||
API_FIELD() static bool AllowCSMBlending;
|
||||
|
||||
/// <summary>
|
||||
/// The Global SDF quality. Controls the volume texture resolution and amount of cascades to use.
|
||||
/// </summary>
|
||||
API_FIELD() static Quality GlobalSDFQuality;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<CascadeData, FixedAllocation<4>> Cascades;
|
||||
HashSet<ScriptingTypeHandle> ObjectTypes;
|
||||
HashSet<GPUTexture*> 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<GlobalSignDistanceFieldCustomBuffer>(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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<float> 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<float> 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<float> 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<float> 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user