Fix DDGI cascades blending to be smoother
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
/// <summary>
|
||||
/// Current materials shader version.
|
||||
/// </summary>
|
||||
#define MATERIAL_GRAPH_VERSION 178
|
||||
#define MATERIAL_GRAPH_VERSION 179
|
||||
|
||||
class Material;
|
||||
class GPUShader;
|
||||
|
||||
@@ -338,7 +338,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
}
|
||||
|
||||
// Calculate the probes count based on the amount of cascades and the distance to cover
|
||||
const float cascadesDistanceScales[] = { 1.0f, 3.0f, 6.0f, 10.0f }; // Scales each cascade further away from the camera origin
|
||||
const float cascadesDistanceScales[] = { 1.0f, 3.0f, 5.0f, 10.0f }; // Scales each cascade further away from the camera origin
|
||||
const float distanceExtent = distance / cascadesDistanceScales[cascadesCount - 1];
|
||||
const float verticalRangeScale = 0.8f; // Scales the probes volume size at Y axis (horizontal aspect ratio makes the DDGI use less probes vertically to cover whole screen)
|
||||
Int3 probesCounts(Float3::Ceil(Float3(distanceExtent, distanceExtent * verticalRangeScale, distanceExtent) / probesSpacing));
|
||||
@@ -354,6 +354,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
// Initialize cascades
|
||||
float probesSpacings[4];
|
||||
Float3 viewOrigins[4];
|
||||
Float3 blendOrigins[4];
|
||||
for (int32 cascadeIndex = 0; cascadeIndex < cascadesCount; cascadeIndex++)
|
||||
{
|
||||
// Each cascade has higher spacing between probes
|
||||
@@ -369,9 +370,10 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
const Float3 viewRayHit = CollisionsHelper::LineHitsBox(viewOrigin, viewOrigin + viewDirection * (probesDistanceMax * 2.0f), viewOrigin - probesDistance, viewOrigin + probesDistance);
|
||||
const float viewOriginOffset = viewRayHit.Y * probesDistanceMax * 0.4f;
|
||||
viewOrigin += viewDirection * viewOriginOffset;
|
||||
//viewOrigin = Float3::Zero;
|
||||
blendOrigins[cascadeIndex] = viewOrigin;
|
||||
const float viewOriginSnapping = cascadeProbesSpacing;
|
||||
viewOrigin = Float3::Floor(viewOrigin / viewOriginSnapping) * viewOriginSnapping;
|
||||
//viewOrigin = Float3::Zero;
|
||||
viewOrigin -= UNITS_TO_METERS(0.5f); // Bias to avoid precision issues (eg. if floor mesh is exactly at Y=0)
|
||||
viewOrigins[cascadeIndex] = viewOrigin;
|
||||
}
|
||||
@@ -504,6 +506,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
{
|
||||
auto& cascade = ddgiData.Cascades[cascadeIndex];
|
||||
ddgiData.Result.Constants.ProbesOriginAndSpacing[cascadeIndex] = Float4(cascade.ProbesOrigin, cascade.ProbesSpacing);
|
||||
ddgiData.Result.Constants.BlendOrigin[cascadeIndex] = Float4(blendOrigins[cascadeIndex], 0.0f);
|
||||
ddgiData.Result.Constants.ProbesScrollOffsets[cascadeIndex] = Int4(cascade.ProbeScrollOffsets, 0);
|
||||
}
|
||||
ddgiData.Result.Constants.RayMaxDistance = distance;
|
||||
|
||||
@@ -15,7 +15,8 @@ public:
|
||||
// Constant buffer data for DDGI access on a GPU.
|
||||
GPU_CB_STRUCT(ConstantsData {
|
||||
Float4 ProbesOriginAndSpacing[4];
|
||||
Int4 ProbesScrollOffsets[4];
|
||||
Float4 BlendOrigin[4]; // w is unused
|
||||
Int4 ProbesScrollOffsets[4]; // w is unused
|
||||
uint32 ProbesCounts[3];
|
||||
uint32 CascadesCount;
|
||||
float IrradianceGamma;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define DDGI_PROBE_ATTENTION_MAX 0.98f // Maximum probe attention value that still makes it active (but not activated which is 1.0f).
|
||||
#define DDGI_PROBE_RESOLUTION_IRRADIANCE 6 // Resolution (in texels) for probe irradiance data (excluding 1px padding on each side)
|
||||
#define DDGI_PROBE_RESOLUTION_DISTANCE 14 // Resolution (in texels) for probe distance data (excluding 1px padding on each side)
|
||||
#define DDGI_CASCADE_BLEND_SIZE 2.5f // Distance in probes over which cascades blending happens
|
||||
#define DDGI_CASCADE_BLEND_SIZE 2.0f // Distance in probes over which cascades blending happens
|
||||
#ifndef DDGI_CASCADE_BLEND_SMOOTH
|
||||
#define DDGI_CASCADE_BLEND_SMOOTH 0 // Enables smooth cascade blending, otherwise dithering will be used
|
||||
#endif
|
||||
@@ -31,7 +31,8 @@
|
||||
struct DDGIData
|
||||
{
|
||||
float4 ProbesOriginAndSpacing[4];
|
||||
int4 ProbesScrollOffsets[4]; // w unused
|
||||
float4 BlendOrigin[4]; // w is unused
|
||||
int4 ProbesScrollOffsets[4]; // w is unused
|
||||
uint3 ProbesCounts;
|
||||
uint CascadesCount;
|
||||
float IrradianceGamma;
|
||||
@@ -290,6 +291,13 @@ float3 GetDDGISurfaceBias(float3 viewDir, float probesSpacing, float3 worldNorma
|
||||
return (worldNormal * 0.2f + viewDir * 0.8f) * (0.6f * probesSpacing * bias);
|
||||
}
|
||||
|
||||
// [Inigo Quilez, https://iquilezles.org/articles/distfunctions/]
|
||||
float sdRoundBox(float3 p, float3 b, float r)
|
||||
{
|
||||
float3 q = abs(p) - b + r;
|
||||
return length(max(q, 0.0f)) + min(max(q.x, max(q.y, q.z)), 0.0f) - r;
|
||||
}
|
||||
|
||||
// Samples DDGI probes volume at the given world-space position and returns the irradiance.
|
||||
// bias - scales the bias vector to the initial sample point to reduce self-shading artifacts
|
||||
// dither - randomized per-pixel value in range 0-1, used to smooth dithering for cascades blending
|
||||
@@ -312,13 +320,10 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
||||
biasedWorldPosition = worldPosition + GetDDGISurfaceBias(viewDir, probesSpacing, worldNormal, bias);
|
||||
|
||||
// Calculate cascade blending weight (use input bias to smooth transition)
|
||||
float cascadeBlendSmooth = frac(max(distance(data.ViewPos, worldPosition) - probesExtent.x, 0) / probesSpacing) * 0.1f;
|
||||
float3 cascadeBlendPoint = worldPosition - probesOrigin - cascadeBlendSmooth * probesSpacing;
|
||||
float fadeDistance = probesSpacing * DDGI_CASCADE_BLEND_SIZE;
|
||||
#if DDGI_CASCADE_BLEND_SMOOTH
|
||||
fadeDistance *= 2.0f; // Make it even smoother when using linear blending
|
||||
#endif
|
||||
cascadeWeight = saturate(Min3(probesExtent - abs(cascadeBlendPoint)) / fadeDistance);
|
||||
float3 blendPos = worldPosition - data.BlendOrigin[cascadeIndex].xyz;
|
||||
cascadeWeight = sdRoundBox(blendPos, probesExtent - probesSpacing, probesSpacing * 2) + fadeDistance;
|
||||
cascadeWeight = 1 - saturate(cascadeWeight / fadeDistance);
|
||||
if (cascadeWeight > dither)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
float prevProbesSpacing = DDGI.ProbesOriginAndSpacing[prevCascade].w;
|
||||
float3 prevProbesOrigin = DDGI.ProbesScrollOffsets[prevCascade].xyz * prevProbesSpacing + DDGI.ProbesOriginAndSpacing[prevCascade].xyz;
|
||||
float3 prevProbesExtent = (DDGI.ProbesCounts - 1) * (prevProbesSpacing * 0.5f);
|
||||
prevProbesExtent -= probesSpacing * ceil(DDGI_CASCADE_BLEND_SIZE); // Apply safe margin to allow probes on cascade edges
|
||||
prevProbesExtent -= probesSpacing * ceil(DDGI_CASCADE_BLEND_SIZE) * 2; // Apply safe margin to allow probes on cascade edges
|
||||
float prevCascadeWeight = Min3(prevProbesExtent - abs(probeBasePosition - prevProbesOrigin));
|
||||
if (prevCascadeWeight > 0.1f)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user