Minor DDGI changes

This commit is contained in:
2026-06-26 14:51:59 +02:00
parent 42241410d4
commit 1a2d86826d
3 changed files with 50 additions and 28 deletions
+1 -1
View File
@@ -1638,7 +1638,7 @@ void Foliage::Deserialize(DeserializeStream& stream, ISerializeModifier* modifie
{
const DeserializeStream& items = foliageInstancesMember->value;
int32 chunksCount = (int32)items.Size() - 1;
if (chunksCount <= 0)
if (chunksCount <= 0 || !items[0].IsInt())
return;
int32 foliageInstancesCount = items[0].GetInt();
Instances.Resize(foliageInstancesCount);
@@ -41,7 +41,6 @@
#define DDGI_TRACE_RAYS_LIMIT 256 // Limit of rays per-probe (runtime value can be smaller)
#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_PROBE_UPDATE_BORDERS_GROUP_SIZE 8
#define DDGI_PROBE_CLASSIFY_GROUP_SIZE 32
#define DDGI_PROBE_EMPTY_AREA_DENSITY 8 // Spacing (in probe grid) between fallback probes placed into empty areas to provide valid GI for nearby dynamic objects or transparency
#define DDGI_DEBUG_STATS 0 // Enables additional GPU-driven stats for probe/rays count
+49 -26
View File
@@ -577,12 +577,12 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID)
#if defined(_CS_UpdateProbes)
#if DDGI_PROBE_UPDATE_MODE == 0
#if DDGI_PROBE_UPDATE_IRRADIANCE
// Update irradiance
#define DDGI_PROBE_RESOLUTION DDGI_PROBE_RESOLUTION_IRRADIANCE
groupshared float4 CachedProbesTraceRadiance[DDGI_TRACE_RAYS_LIMIT];
groupshared float OutputInstability[DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION];
#else
#elif DDGI_PROBE_UPDATE_DEPTH
// Update distance
#define DDGI_PROBE_RESOLUTION DDGI_PROBE_RESOLUTION_DISTANCE
groupshared float CachedProbesTraceDistance[DDGI_TRACE_RAYS_LIMIT];
@@ -693,29 +693,27 @@ static const uint4 BorderOffsets[BorderOffsetsSize] = {
uint4(1, 1, 15, 15)
};
#else
#error "Unsupported probe size for border values copy."
#undef BorderOffsetsSize
#endif
groupshared float3 CachedProbesTraceDirection[DDGI_TRACE_RAYS_LIMIT];
RWTexture2D<float4> RWOutput : register(u0);
#if DDGI_PROBE_UPDATE_MODE == 0
#if DDGI_PROBE_UPDATE_IRRADIANCE
RWTexture2D<snorm float4> RWProbesData : register(u1);
#if DDGI_DEBUG_INSTABILITY
RWTexture2D<float> RWOutputInstability : register(u2);
#endif
#else
#elif DDGI_PROBE_UPDATE_DEPTH
Texture2D<snorm float4> ProbesData : register(t0);
#endif
Texture2D<float4> ProbesTrace : register(t1);
ByteAddressBuffer ActiveProbes : register(t2);
// Compute shader for updating probes irradiance or distance texture.
#define DDGI_PROBE_UPDATE_IRRADIANCE 0
#define DDGI_PROBE_UPDATE_DISTANCE 1
META_CS(true, FEATURE_LEVEL_SM5)
META_PERMUTATION_1(DDGI_PROBE_UPDATE_MODE=0) // Irradiance
META_PERMUTATION_1(DDGI_PROBE_UPDATE_MODE=1) // Distance
META_PERMUTATION_1(DDGI_PROBE_UPDATE_IRRADIANCE=1)
META_PERMUTATION_1(DDGI_PROBE_UPDATE_DEPTH=1)
[numthreads(DDGI_PROBE_RESOLUTION, DDGI_PROBE_RESOLUTION, 1)]
void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_GroupID, uint GroupIndex : SV_GroupIndex)
{
@@ -727,20 +725,20 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords);
// Load probe data
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
int2 probeDataCoords = GetDDGIProbeTexelCoords(DDGI, CascadeIndex, probeIndex);
float4 probeData = RWProbesData[probeDataCoords];
#else
#elif DDGI_PROBE_UPDATE_DEPTH
float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex);
#endif
float probeAttention = DecodeDDGIProbeAttention(probeData);
uint probeState = DecodeDDGIProbeState(probeData);
uint probeRaysCount = GetProbeRaysCount(DDGI, probeAttention);
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
uint backfacesCount = 0;
uint backfacesLimit = uint(probeRaysCount * 0.1f);
#else
#elif DDGI_PROBE_UPDATE_DEPTH
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
float distanceLimit = probesSpacing * 1.5f;
#endif
@@ -752,9 +750,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
for (uint i = 0; i < raysCount; i++)
{
uint rayIndex = raysStart + i;
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
CachedProbesTraceRadiance[rayIndex] = ProbesTrace[uint2(rayIndex, GroupId.x)];
#else
#elif DDGI_PROBE_UPDATE_DEPTH
float rayDistance = ProbesTrace[uint2(rayIndex, GroupId.x)].w;
CachedProbesTraceDistance[rayIndex] = min(abs(rayDistance), distanceLimit);
#endif
@@ -775,7 +773,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
float3 rayDirection = CachedProbesTraceDirection[rayIndex];
float rayWeight = max(dot(octahedralDirection, rayDirection), 0.0f);
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
float4 rayRadiance = CachedProbesTraceRadiance[rayIndex];
#if DDGI_TRACE_NEGATIVE
if (rayRadiance.w < 0.0f)
@@ -795,7 +793,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
// Add radiance (RGB) and weight (A)
result += float4(rayRadiance.rgb * rayWeight, rayWeight);
#else
#elif DDGI_PROBE_UPDATE_DEPTH
// Increase reaction speed for depth discontinuities
rayWeight = pow(rayWeight, 10.0f);
@@ -807,9 +805,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
// Normalize results
float epsilon = (float)probeRaysCount * 1e-9f;
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
result.rgb *= 1.0f / (2.0f * max(result.a, epsilon));
#else
#elif DDGI_PROBE_UPDATE_DEPTH
result.rgb *= 1.0f / max(result.a, epsilon);
#endif
@@ -820,7 +818,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
if (wasActivated)
previous = result.rgb;
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
// Calculate instability of the irradiance
float previousLuma = Luminance(previous.rgb);
float resultLuma = Luminance(result.rgb);
@@ -840,7 +838,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
// Blend current value with the previous probe data
float historyWeightFast = DDGI.ProbeHistoryWeight;
float historyWeightSlow = 0.97f;
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
float3 irradianceDelta = result.rgb - previous;
float irradianceDeltaMax = Max3(abs(irradianceDelta));
float irradianceDeltaLen = length(irradianceDelta);
@@ -853,7 +851,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
float historyWeight = lerp(historyWeightSlow, historyWeightFast, probeAttention * probeAttention * probeAttention);
//historyWeight = 1.0f; // Debug full-blend
//historyWeight = 0.0f; // Debug no-blend
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_DISTANCE
#if DDGI_PROBE_UPDATE_DEPTH
// Reduce blending when the distance changes too much to avoid ghosting artifacts
float instability = abs(previous.x - result.x) / previous.x;
if (instability > 0.5f) historyWeight *= 0.5f;
@@ -861,7 +859,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
if (wasActivated)
historyWeight = 0.0f;
result.rgb = max(result.rgb, 0);
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
result *= DDGI.IndirectLightingIntensity;
#if DDGI_SRGB_BLENDING == 1
result.rgb = pow(result.rgb, 0.5f / DDGI_SRGB_BLENDING_GAMMA);
@@ -876,16 +874,18 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
// Apply quantization error to reduce yellowish artifacts due to R11G11B10 format
float noise = InterleavedGradientNoise(octahedralCoords * 10, FrameIndexMod8);
result.rgb = QuantizeColor(result.rgb, noise, QuantizationError);
#else
#elif DDGI_PROBE_UPDATE_DEPTH
result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f);
#endif
RWOutput[outputCoords] = result;
#ifdef BorderOffsetsSize
GroupMemoryBarrierWithGroupSync();
#endif
uint2 baseCoords = GetDDGIProbeTexelCoords(DDGI, CascadeIndex, probeIndex) * (DDGI_PROBE_RESOLUTION + 2);
#if DDGI_PROBE_UPDATE_MODE == DDGI_PROBE_UPDATE_IRRADIANCE
#if DDGI_PROBE_UPDATE_IRRADIANCE
// The first thread updates the probe attention based on the instability of all texels
BRANCH
if (GroupIndex == 0 && probeState != DDGI_PROBE_STATE_INACTIVE)
@@ -912,7 +912,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
RWProbesData[probeDataCoords] = EncodeDDGIProbeData(probeData.xyz, probeState, probeAttention);
}
#if DDGI_DEBUG_INSTABILITY
#if DDGI_DEBUG_INSTABILITY && defined(BorderOffsetsSize)
// Copy border pixels
for (uint borderIndex = GroupIndex; borderIndex < BorderOffsetsSize; borderIndex += DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION)
{
@@ -923,11 +923,34 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
#endif
// Copy border pixels
#ifdef BorderOffsetsSize
for (uint borderIndex = GroupIndex; borderIndex < BorderOffsetsSize; borderIndex += DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION)
{
uint4 borderOffsets = BorderOffsets[borderIndex];
RWOutput[baseCoords + borderOffsets.zw] = RWOutput[baseCoords + borderOffsets.xy];
}
#else
bool isEdgeX = GroupThreadId.x == 0 || GroupThreadId.x == DDGI_PROBE_RESOLUTION - 1;
bool isEdgeY = GroupThreadId.y == 0 || GroupThreadId.y == DDGI_PROBE_RESOLUTION - 1;
if (isEdgeX)
{
outputCoords.x = baseCoords.x + (GroupThreadId.x == 0 ? 0 : (DDGI_PROBE_RESOLUTION + 1));
outputCoords.y = baseCoords.y + DDGI_PROBE_RESOLUTION - GroupThreadId.y;
RWOutput[outputCoords] = result;
}
if (isEdgeY)
{
outputCoords.x = baseCoords.x + DDGI_PROBE_RESOLUTION - GroupThreadId.x;
outputCoords.y = baseCoords.y + (GroupThreadId.y == 0 ? 0 : (DDGI_PROBE_RESOLUTION + 1));
RWOutput[outputCoords] = result;
}
if (isEdgeX && isEdgeY)
{
outputCoords.x = baseCoords.x + (GroupThreadId.x == 0 ? DDGI_PROBE_RESOLUTION + 1 : 0);
outputCoords.y = baseCoords.y + (GroupThreadId.y == 0 ? DDGI_PROBE_RESOLUTION + 1 : 0);
RWOutput[outputCoords] = result;
}
#endif
}
#endif