diff --git a/Source/Engine/Graphics/PostProcessSettings.cpp b/Source/Engine/Graphics/PostProcessSettings.cpp
index 7c728bcf7..51281dba0 100644
--- a/Source/Engine/Graphics/PostProcessSettings.cpp
+++ b/Source/Engine/Graphics/PostProcessSettings.cpp
@@ -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);
}
diff --git a/Source/Engine/Graphics/PostProcessSettings.h b/Source/Engine/Graphics/PostProcessSettings.h
index 20d886fa3..f9ae1a53b 100644
--- a/Source/Engine/Graphics/PostProcessSettings.h
+++ b/Source/Engine/Graphics/PostProcessSettings.h
@@ -334,10 +334,15 @@ API_ENUM(Attributes="Flags") enum class GlobalIlluminationSettingsOverride : int
///
BounceIntensity = 1 << 5,
+ ///
+ /// Overrides property.
+ ///
+ IndirectShadowsStrength = 1 << 6,
+
///
/// All properties.
///
- All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity,
+ All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity | IndirectShadowsStrength,
};
///
@@ -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;
+ ///
+ /// 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.
+ ///
+ API_FIELD(Attributes = "EditorOrder(35), Limit(0.0f, 1.0f, 0.001f), PostProcessSetting((int)GlobalIlluminationSettingsOverride.IndirectShadowsStrength)")
+ float IndirectShadowsStrength = 1.0f;
+
///
/// The irradiance lighting outside the GI range used as a fallback to prevent pure-black scene outside the Global Illumination range.
///
diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
index 22b063d4e..00127fbc9 100644
--- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
+++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp
@@ -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();
diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h
index 0e4c2612d..d58eee47a 100644
--- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h
+++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h
@@ -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;
diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl
index 718fd2aaa..88b9a4cb8 100644
--- a/Source/Shaders/GI/DDGI.hlsl
+++ b/Source/Shaders/GI/DDGI.hlsl
@@ -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 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 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)