Add IndirectShadowsStrength to GI settings for artist-controlled light leaking

This commit is contained in:
2026-06-23 12:33:11 +02:00
parent 1c5197f3a8
commit 0477d37aeb
5 changed files with 19 additions and 4 deletions
@@ -33,6 +33,7 @@ void GlobalIlluminationSettings::BlendWith(GlobalIlluminationSettings& other, fl
BLEND_FLOAT(BounceIntensity);
BLEND_FLOAT(TemporalResponse);
BLEND_FLOAT(Distance);
BLEND_FLOAT(IndirectShadowsStrength);
BLEND_COL(FallbackIrradiance);
}
+12 -1
View File
@@ -334,10 +334,15 @@ API_ENUM(Attributes="Flags") enum class GlobalIlluminationSettingsOverride : int
/// </summary>
BounceIntensity = 1 << 5,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.IndirectShadowsStrength"/> property.
/// </summary>
IndirectShadowsStrength = 1 << 6,
/// <summary>
/// All properties.
/// </summary>
All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity,
All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity | IndirectShadowsStrength,
};
/// <summary>
@@ -385,6 +390,12 @@ API_STRUCT() struct FLAXENGINE_API GlobalIlluminationSettings : ISerializable
API_FIELD(Attributes="EditorOrder(30), Limit(1000), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Distance), ValueCategory(Utils.ValueCategory.Distance)")
float Distance = 20000.0f;
/// <summary>
/// Indirect lighting shadows intensity. Default is 1 for fully opaque shadowing, lower values bleed the lighting into shadowed areas. Can be sued for artistic control over GI.
/// </summary>
API_FIELD(Attributes = "EditorOrder(35), Limit(0.0f, 1.0f, 0.001f), PostProcessSetting((int)GlobalIlluminationSettingsOverride.IndirectShadowsStrength)")
float IndirectShadowsStrength = 1.0f;
/// <summary>
/// The irradiance lighting outside the GI range used as a fallback to prevent pure-black scene outside the Global Illumination range.
/// </summary>
@@ -546,6 +546,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
ddgiData.Result.Constants.RaysCount = probeRaysCount;
ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight;
ddgiData.Result.Constants.IndirectLightingIntensity = indirectLightingIntensity;
ddgiData.Result.Constants.IndirectShadowsStrength = settings.IndirectShadowsStrength;
ddgiData.Result.Constants.FallbackIrradiance = settings.FallbackIrradiance.ToFloat4();
ddgiData.Result.ProbesData = ddgiData.ProbesData->View();
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
@@ -19,10 +19,10 @@ public:
Int4 ProbesScrollOffsets[4]; // w is unused
uint32 ProbesCounts[3];
uint32 CascadesCount;
float Padding;
float ProbeHistoryWeight;
float RayMaxDistance;
float IndirectLightingIntensity;
float IndirectShadowsStrength;
Float3 ViewPos;
uint32 RaysCount;
Float4 FallbackIrradiance;
+4 -2
View File
@@ -41,10 +41,10 @@ struct DDGIData
int4 ProbesScrollOffsets[4]; // w is unused
uint3 ProbesCounts;
uint CascadesCount;
float Padding;
float ProbeHistoryWeight;
float RayMaxDistance;
float IndirectLightingIntensity;
float IndirectShadowsStrength;
float3 ViewPos;
uint RaysCount;
float4 FallbackIrradiance;
@@ -245,6 +245,7 @@ float3 SampleDDGIIrradianceCascade(DDGIData data, Texture2D<snorm float4> probes
{
float variance = abs(Square(probeDistance.x) - probeDistance.y);
float visibilityWeight = variance / (variance + Square(biasedPosToProbeDist - probeDistance.x));
visibilityWeight = lerp(1, visibilityWeight, data.IndirectShadowsStrength);
weights *= max(visibilityWeight * visibilityWeight * visibilityWeight, 0.0f);
}
@@ -294,7 +295,8 @@ float3 SampleDDGIIrradianceCascade(DDGIData data, Texture2D<snorm float4> probes
#if !DDGI_FALLBACK_OUTER_DEDICATED_PROBE
canNormalize += invalidCascade ? 1 : 0; // Normalize when outside the last cascade to preserve ambient GI when not using ambient probe
#endif
totalIrradiance.rgb /= lerp(1, totalIrradiance.a, saturate(canNormalize));
float shadowNormalization = lerp(1, totalIrradiance.a, saturate(canNormalize));
totalIrradiance.rgb /= lerp(totalIrradiance.a, shadowNormalization, data.IndirectShadowsStrength);
if (fallbacks >= 5 && totalIrradianceNonDir.a > 0.00001f)
{
// Use non-directional irradiance when sampling mostly fallback probes (out of place)