Add Global Illumination options to PostFx Settings

This commit is contained in:
Wojciech Figat
2022-06-10 18:48:17 +02:00
parent aa58665740
commit d4839b9c78
20 changed files with 314 additions and 94 deletions

BIN
Content/Shaders/GI/DDGI.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -110,6 +110,25 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
}
/// <summary>
/// Editor for <see cref="GlobalIlluminationSettings"/> type.
/// </summary>
[CustomEditor(typeof(GlobalIlluminationSettings)), DefaultEditor]
sealed class GlobalIlluminationSettingsEditor : PostProcessSettingsEditor
{
/// <inheritdoc />
protected override int OverrideFlags
{
get => (int)((GlobalIlluminationSettings)Values[0]).OverrideFlags;
set
{
var settings = (GlobalIlluminationSettings)Values[0];
settings.OverrideFlags = (GlobalIlluminationSettingsOverride)value;
SetValue(settings);
}
}
}
/// <summary>
/// Editor for <see cref="BloomSettings"/> type.
/// </summary>

View File

@@ -72,6 +72,14 @@ namespace FlaxEditor.Windows
set => Graphics.GlobalSDFQuality = value;
}
[DefaultValue(Quality.High)]
[EditorOrder(1290), EditorDisplay("Quality"), Tooltip("The Global Illumination quality. Controls the quality of the GI effect.")]
public Quality GIQuality
{
get => Graphics.GIQuality;
set => Graphics.GIQuality = value;
}
[DefaultValue(Quality.Medium)]
[EditorOrder(1300), EditorDisplay("Quality", "Shadows Quality"), Tooltip("The shadows quality.")]
public Quality ShadowsQuality

View File

@@ -14,4 +14,5 @@ void GraphicsSettings::Apply()
Graphics::ShadowMapsQuality = ShadowMapsQuality;
Graphics::AllowCSMBlending = AllowCSMBlending;
Graphics::GlobalSDFQuality = GlobalSDFQuality;
Graphics::GIQuality = GIQuality;
}

View File

@@ -82,6 +82,12 @@ public:
bool GenerateSDFOnModelImport = false;
#endif
/// <summary>
/// The Global Illumination quality. Controls the quality of the GI effect.
/// </summary>
API_FIELD(Attributes="EditorOrder(2100), DefaultValue(Quality.High), EditorDisplay(\"Quality\")")
Quality GIQuality = Quality::High;
public:
/// <summary>
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.

View File

@@ -15,6 +15,7 @@ Quality Graphics::ShadowsQuality = Quality::Medium;
Quality Graphics::ShadowMapsQuality = Quality::Medium;
bool Graphics::AllowCSMBlending = false;
Quality Graphics::GlobalSDFQuality = Quality::High;
Quality Graphics::GIQuality = Quality::High;
#if GRAPHICS_API_NULL
extern GPUDevice* CreateGPUDeviceNull();

View File

@@ -58,6 +58,11 @@ public:
/// </summary>
API_FIELD() static Quality GlobalSDFQuality;
/// <summary>
/// The Global Illumination quality. Controls the quality of the GI effect.
/// </summary>
API_FIELD() static Quality GIQuality;
public:
/// <summary>

View File

@@ -8,6 +8,7 @@
#define BLEND_FLOAT(name) if ((((int32)other.OverrideFlags & (int32)Override::name) != 0)) name = Math::Lerp(name, other.name, weight)
#define BLEND_INT(name) BLEND_FLOAT(name)
#define BLEND_VEC3(name) if ((((int32)other.OverrideFlags & (int32)Override::name) != 0)) name = Vector3::Lerp(name, other.name, weight)
#define BLEND_COL(name) if ((((int32)other.OverrideFlags & (int32)Override::name) != 0)) name = Color::Lerp(name, other.name, weight)
#define BLEND_ENUM(name) BLEND_BOOL(name)
#define BLEND_PROPERTY(name) BLEND_BOOL(name)
@@ -23,6 +24,16 @@ void AmbientOcclusionSettings::BlendWith(AmbientOcclusionSettings& other, float
BLEND_FLOAT(FadeDistance);
}
void GlobalIlluminationSettings::BlendWith(GlobalIlluminationSettings& other, float weight)
{
const bool isHalf = weight >= 0.5f;
BLEND_BOOL(Mode);
BLEND_FLOAT(Intensity);
BLEND_FLOAT(TemporalResponse);
BLEND_FLOAT(Distance);
BLEND_COL(FallbackIrradiance);
}
void BloomSettings::BlendWith(BloomSettings& other, float weight)
{
const bool isHalf = weight >= 0.5f;
@@ -209,6 +220,7 @@ void PostFxMaterialsSettings::BlendWith(PostFxMaterialsSettings& other, float we
void PostProcessSettings::BlendWith(PostProcessSettings& other, float weight)
{
AmbientOcclusion.BlendWith(other.AmbientOcclusion, weight);
GlobalIllumination.BlendWith(other.GlobalIllumination, weight);
Bloom.BlendWith(other.Bloom, weight);
ToneMapping.BlendWith(other.ToneMapping, weight);
ColorGrading.BlendWith(other.ColorGrading, weight);
@@ -251,6 +263,9 @@ void PostProcessSettings::Serialize(SerializeStream& stream, const void* otherOb
stream.JKEY("AO");
stream.Object(&AmbientOcclusion, other ? &other->AmbientOcclusion : nullptr);
stream.JKEY("GI");
stream.Object(&GlobalIllumination, other ? &other->GlobalIllumination : nullptr);
stream.JKEY("Bloom");
stream.Object(&Bloom, other ? &other->Bloom : nullptr);
@@ -289,6 +304,7 @@ void PostProcessSettings::Serialize(SerializeStream& stream, const void* otherOb
void PostProcessSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
AmbientOcclusion.DeserializeIfExists(stream, "AO", modifier);
GlobalIllumination.DeserializeIfExists(stream, "GI", modifier);
Bloom.DeserializeIfExists(stream, "Bloom", modifier);
ToneMapping.DeserializeIfExists(stream, "ToneMapping", modifier);
ColorGrading.DeserializeIfExists(stream, "ColorGrading", modifier);

View File

@@ -9,6 +9,27 @@
#include "Engine/Content/Assets/Texture.h"
#include "Engine/Content/Assets/MaterialBase.h"
/// <summary>
/// Global Illumination effect rendering modes.
/// </summary>
API_ENUM() enum class GlobalIlluminationMode
{
/// <summary>
/// Disabled GI effect.
/// </summary>
None = 0,
/// <summary>
/// Dynamic Diffuse Global Illumination algorithm with scrolling probes volume (with cascades). Uses software raytracing - requires Global SDF and Global Surface Atlas.
/// </summary>
DDGI = 1,
/// <summary>
/// The custom GI algorithm - plugged-in externally.
/// </summary>
Custom = 2,
};
/// <summary>
/// Tone mapping effect rendering modes.
/// </summary>
@@ -183,8 +204,8 @@ API_ENUM(Attributes="Flags") enum class AmbientOcclusionSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API AmbientOcclusionSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(AmbientOcclusionSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(AmbientOcclusionSettings);
typedef AmbientOcclusionSettingsOverride Override;
/// <summary>
@@ -230,7 +251,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(AmbientOcclusionSettings);
float FadeDistance = 500.0f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -239,6 +259,101 @@ public:
void BlendWith(AmbientOcclusionSettings& other, float weight);
};
/// <summary>
/// The <see cref="GlobalIlluminationSettings"/> structure members override flags.
/// </summary>
API_ENUM(Attributes="Flags") enum class GlobalIlluminationSettingsOverride : int32
{
/// <summary>
/// None properties.
/// </summary>
None = 0,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.Mode"/> property.
/// </summary>
Mode = 1 << 0,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.Intensity"/> property.
/// </summary>
Intensity = 1 << 1,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.TemporalResponse"/> property.
/// </summary>
TemporalResponse = 1 << 2,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.Distance"/> property.
/// </summary>
Distance = 1 << 3,
/// <summary>
/// Overrides <see cref="GlobalIlluminationSettings.FallbackIrradiance"/> property.
/// </summary>
FallbackIrradiance = 1 << 4,
/// <summary>
/// All properties.
/// </summary>
All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance,
};
/// <summary>
/// Contains settings for Global Illumination effect rendering.
/// </summary>
API_STRUCT() struct FLAXENGINE_API GlobalIlluminationSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GlobalIlluminationSettings);
typedef GlobalIlluminationSettingsOverride Override;
/// <summary>
/// The flags for overriden properties.
/// </summary>
API_FIELD(Attributes="HideInEditor")
GlobalIlluminationSettingsOverride OverrideFlags = Override::None;
/// <summary>
/// The Global Illumination mode to use.
/// </summary>
API_FIELD(Attributes="EditorOrder(0), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Mode)")
GlobalIlluminationMode Mode = GlobalIlluminationMode::None;
/// <summary>
/// Global Illumination indirect lighting intensity scale. Can be used to boost or reduce GI effect.
/// </summary>
API_FIELD(Attributes="EditorOrder(10), Limit(0, 10, 0.01f), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Intensity)")
float Intensity = 1.0f;
/// <summary>
/// Defines how quickly GI blends between the the current frame and the history buffer. Lower values update GI faster, but with more jittering and noise. If the camera in your game doesn't move much, we recommend values closer to 1.
/// </summary>
API_FIELD(Attributes="EditorOrder(20), Limit(0, 1), PostProcessSetting((int)GlobalIlluminationSettingsOverride.TemporalResponse)")
float TemporalResponse = 0.8f;
/// <summary>
/// Draw distance of the Global Illumination effect. Scene outside the range will use fallback irradiance.
/// </summary>
API_FIELD(Attributes="EditorOrder(30), Limit(1000), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Distance)")
float Distance = 20000.0f;
/// <summary>
/// The irradiance lighting outside the GI range used as a fallback to prevent pure-black scene outside the Global Illumination range.
/// </summary>
API_FIELD(Attributes="EditorOrder(40), PostProcessSetting((int)GlobalIlluminationSettingsOverride.FallbackIrradiance)")
Color FallbackIrradiance = Color::Black;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
/// <param name="other">The other settings.</param>
/// <param name="weight">The blend weight.</param>
void BlendWith(GlobalIlluminationSettings& other, float weight);
};
/// <summary>
/// The structure members override flags.
/// </summary>
@@ -285,8 +400,8 @@ API_ENUM(Attributes="Flags") enum class BloomSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API BloomSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(BloomSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(BloomSettings);
typedef BloomSettingsOverride Override;
/// <summary>
@@ -326,7 +441,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(BloomSettings);
float Limit = 10.0f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -371,8 +485,8 @@ API_ENUM(Attributes="Flags") enum class ToneMappingSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API ToneMappingSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ToneMappingSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ToneMappingSettings);
typedef ToneMappingSettingsOverride Override;
/// <summary>
@@ -400,7 +514,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(ToneMappingSettings);
ToneMappingMode Mode = ToneMappingMode::ACES;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -550,8 +663,8 @@ API_ENUM(Attributes="Flags") enum class ColorGradingSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API ColorGradingSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ColorGradingSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ColorGradingSettings);
typedef ColorGradingSettingsOverride Override;
/// <summary>
@@ -717,7 +830,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(ColorGradingSettings);
float LutWeight = 1.0f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -792,8 +904,8 @@ API_ENUM(Attributes="Flags") enum class EyeAdaptationSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API EyeAdaptationSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(EyeAdaptationSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(EyeAdaptationSettings);
typedef EyeAdaptationSettingsOverride Override;
/// <summary>
@@ -857,7 +969,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(EyeAdaptationSettings);
float HistogramHighPercent = 98.0f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -927,8 +1038,8 @@ API_ENUM(Attributes="Flags") enum class CameraArtifactsSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API CameraArtifactsSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(CameraArtifactsSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(CameraArtifactsSettings);
typedef CameraArtifactsSettingsOverride Override;
/// <summary>
@@ -986,7 +1097,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(CameraArtifactsSettings);
Color ScreenFadeColor = Color::Transparent;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1076,8 +1186,8 @@ API_ENUM(Attributes="Flags") enum class LensFlaresSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API LensFlaresSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(LensFlaresSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(LensFlaresSettings);
typedef LensFlaresSettingsOverride Override;
/// <summary>
@@ -1159,7 +1269,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(LensFlaresSettings);
AssetReference<Texture> LensStar;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1269,8 +1378,8 @@ API_ENUM(Attributes="Flags") enum class DepthOfFieldSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API DepthOfFieldSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(DepthOfFieldSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(DepthOfFieldSettings);
typedef DepthOfFieldSettingsOverride Override;
/// <summary>
@@ -1376,7 +1485,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(DepthOfFieldSettings);
float BokehDepthCutoff = 1.5f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1426,8 +1534,8 @@ API_ENUM(Attributes="Flags") enum class MotionBlurSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API MotionBlurSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(MotionBlurSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(MotionBlurSettings);
typedef MotionBlurSettingsOverride Override;
/// <summary>
@@ -1461,7 +1569,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(MotionBlurSettings);
ResolutionMode MotionVectorsResolution = ResolutionMode::Half;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1566,8 +1673,8 @@ API_ENUM(Attributes="Flags") enum class ScreenSpaceReflectionsSettingsOverride :
/// </summary>
API_STRUCT() struct FLAXENGINE_API ScreenSpaceReflectionsSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScreenSpaceReflectionsSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScreenSpaceReflectionsSettings);
typedef ScreenSpaceReflectionsSettingsOverride Override;
/// <summary>
@@ -1667,7 +1774,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScreenSpaceReflectionsSettings);
float TemporalResponse = 0.8f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1722,8 +1828,8 @@ API_ENUM(Attributes="Flags") enum class AntiAliasingSettingsOverride : int32
/// </summary>
API_STRUCT() struct FLAXENGINE_API AntiAliasingSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(AntiAliasingSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(AntiAliasingSettings);
typedef AntiAliasingSettingsOverride Override;
/// <summary>
@@ -1763,7 +1869,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(AntiAliasingSettings);
float TAA_MotionBlending = 0.4f;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1777,8 +1882,8 @@ public:
/// </summary>
API_STRUCT() struct FLAXENGINE_API PostFxMaterialsSettings : ISerializable
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostFxMaterialsSettings);
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostFxMaterialsSettings);
/// <summary>
/// The post-process materials collection for rendering (fixed capacity).
@@ -1787,7 +1892,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostFxMaterialsSettings);
Array<AssetReference<MaterialBase>, FixedAllocation<POST_PROCESS_SETTINGS_MAX_MATERIALS>> Materials;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1801,7 +1905,7 @@ public:
/// </summary>
API_STRUCT() struct FLAXENGINE_API PostProcessSettings : ISerializable
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostProcessSettings);
DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostProcessSettings);
/// <summary>
/// The ambient occlusion effect settings.
@@ -1809,6 +1913,12 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostProcessSettings);
API_FIELD()
AmbientOcclusionSettings AmbientOcclusion;
/// <summary>
/// The global illumination effect settings.
/// </summary>
API_FIELD()
GlobalIlluminationSettings GlobalIllumination;
/// <summary>
/// The bloom effect settings.
/// </summary>
@@ -1876,7 +1986,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(PostProcessSettings);
PostFxMaterialsSettings PostFxMaterials;
public:
/// <summary>
/// Blends the settings using given weight.
/// </summary>
@@ -1891,13 +2000,13 @@ public:
bool HasContentLoaded() const;
public:
// [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
};
DECLARE_ENUM_OPERATORS(AmbientOcclusionSettingsOverride);
DECLARE_ENUM_OPERATORS(GlobalIlluminationSettingsOverride);
DECLARE_ENUM_OPERATORS(BloomSettingsOverride);
DECLARE_ENUM_OPERATORS(ToneMappingSettingsOverride);
DECLARE_ENUM_OPERATORS(ColorGradingSettingsOverride);

View File

@@ -43,6 +43,7 @@ void PostFxVolume::Collect(RenderContext& renderContext)
void PostFxVolume::Blend(PostProcessSettings& other, float weight)
{
other.AmbientOcclusion.BlendWith(AmbientOcclusion, weight);
other.GlobalIllumination.BlendWith(GlobalIllumination, weight);
other.Bloom.BlendWith(Bloom, weight);
other.ToneMapping.BlendWith(ToneMapping, weight);
other.ColorGrading.BlendWith(ColorGrading, weight);
@@ -118,6 +119,9 @@ void PostFxVolume::Serialize(SerializeStream& stream, const void* otherObj)
stream.JKEY("AO");
stream.Object(&AmbientOcclusion, other ? &other->AmbientOcclusion : nullptr);
stream.JKEY("GI");
stream.Object(&GlobalIllumination, other ? &other->GlobalIllumination : nullptr);
stream.JKEY("Bloom");
stream.Object(&Bloom, other ? &other->Bloom : nullptr);
@@ -169,6 +173,7 @@ void PostFxVolume::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
{
auto& settingsStream = settingsMember->value;
AmbientOcclusion.DeserializeIfExists(settingsStream, "AO", modifier);
GlobalIllumination.DeserializeIfExists(settingsStream, "GI", modifier);
Bloom.DeserializeIfExists(settingsStream, "Bloom", modifier);
ToneMapping.DeserializeIfExists(settingsStream, "ToneMapping", modifier);
ColorGrading.DeserializeIfExists(settingsStream, "ColorGrading", modifier);

View File

@@ -27,6 +27,12 @@ public:
API_FIELD(Attributes="EditorDisplay(\"Ambient Occlusion\"), EditorOrder(100)")
AmbientOcclusionSettings AmbientOcclusion;
/// <summary>
/// The Global Illumination effect settings.
/// </summary>
API_FIELD(Attributes="EditorDisplay(\"Global Illumination\"), EditorOrder(150)")
GlobalIlluminationSettings GlobalIllumination;
/// <summary>
/// The bloom effect settings.
/// </summary>

View File

@@ -14,6 +14,7 @@
#include "Engine/Debug/DebugDraw.h"
#include "Engine/Engine/Time.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"
@@ -45,10 +46,9 @@ PACK_STRUCT(struct Data0
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
GBufferData GBuffer;
Vector2 Padding0;
float ResetBlend;
float TemporalTime;
float IndirectLightingIntensity;
float Padding0;
});
PACK_STRUCT(struct Data1
@@ -266,22 +266,52 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
ddgiData.LastFrameUsed = currentFrame;
PROFILE_GPU_CPU("Dynamic Diffuse Global Illumination");
// TODO: configurable via graphics settings
const Quality quality = Quality::Ultra;
// Setup options
auto& settings = renderContext.List->Settings.GlobalIllumination;
// TODO: implement GI Quality to affect cascades update rate, probes spacing and rays count per probe
const float probesSpacing = 100.0f; // GI probes placement spacing nearby camera (for closest cascade; gets automatically reduced for further cascades)
switch (Graphics::GIQuality)
{
case Quality::Low:
break;
case Quality::Medium:
break;
case Quality::High:
break;
case Quality::Ultra:
default:
break;
}
bool debugProbes = false; // TODO: add debug option to draw probes locations -> in Graphics window - Editor-only
// TODO: configurable via postFx settings (maybe use Global SDF distance?)
const float indirectLightingIntensity = 1.0f;
const float probeHistoryWeight = 0.8f;
const int32 cascadesCount = 4; // in range 1-4
// TODO: use GI.Distance as a easier to adjust total distance and automatically calculate distanceExtent from it
const float distance = 20000.0f; // GI distance around the view (in each direction)
const float indirectLightingIntensity = settings.Intensity;
const float probeHistoryWeight = Math::Clamp(settings.TemporalResponse, 0.0f, 0.98f);
const float distance = settings.Distance;
const Color fallbackIrradiance = settings.FallbackIrradiance;
const int32 probeRaysCount = Math::Min(Math::AlignUp(256, DDGI_TRACE_RAYS_GROUP_SIZE_X), DDGI_TRACE_RAYS_LIMIT); // TODO: make it based on the GI Quality
// Automatically calculate amount of cascades to cover the GI distance at the current probes spacing
const int32 idealProbesCount = 20; // Ideal amount of probes per-cascade to try to fit in order to cover whole distance
int32 cascadesCount = 1;
float idealDistance = idealProbesCount * probesSpacing;
while (cascadesCount < 4 && idealDistance < distance)
{
idealDistance *= 2;
cascadesCount++;
}
// 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 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)
const float probesSpacing = 200.0f; // GI probes placement spacing nearby camera (for closest cascade; gets automatically reduced for further cascades)
const Color fallbackIrradiance = Color::Black; // Irradiance lighting outside the DDGI range used as a fallback to prevent pure-black scene outside the GI range
const Int3 probesCounts(Vector3::Ceil(Vector3(distanceExtent, distanceExtent * verticalRangeScale, distanceExtent) / probesSpacing));
const int32 probeRaysCount = Math::Min(Math::AlignUp(256, DDGI_TRACE_RAYS_GROUP_SIZE_X), DDGI_TRACE_RAYS_LIMIT); // TODO: make it based on the GI Quality
Int3 probesCounts(Vector3::Ceil(Vector3(distanceExtent, distanceExtent * verticalRangeScale, distanceExtent) / probesSpacing));
const int32 maxProbeSize = Math::Max(DDGI_PROBE_RESOLUTION_IRRADIANCE, DDGI_PROBE_RESOLUTION_DISTANCE) + 2;
const int32 maxTextureSize = Math::Min(GPUDevice::Instance->Limits.MaximumTexture2DSize, GPU_MAX_TEXTURE_SIZE);
while (probesCounts.X * probesCounts.Y * maxProbeSize > maxTextureSize
|| probesCounts.Z * cascadesCount * maxProbeSize > maxTextureSize)
{
// Decrease quality to ensure the probes texture won't overflow
probesCounts -= 1;
}
// Initialize cascades
float probesSpacings[4];
@@ -417,6 +447,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
ddgiData.Result.Constants.RaysCount = probeRaysCount;
ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight;
ddgiData.Result.Constants.IrradianceGamma = 5.0f;
ddgiData.Result.Constants.IndirectLightingIntensity = indirectLightingIntensity;
ddgiData.Result.Constants.FallbackIrradiance = fallbackIrradiance.ToVector3() * fallbackIrradiance.A;
ddgiData.Result.ProbesState = ddgiData.ProbesState->View();
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
@@ -446,7 +477,6 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
{
data.TemporalTime = 0.0f;
}
data.IndirectLightingIntensity = indirectLightingIntensity;
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
context->UpdateCB(_cb0, &data);
context->BindCB(0, _cb0);

View File

@@ -23,12 +23,12 @@ public:
float IrradianceGamma;
float ProbeHistoryWeight;
float RayMaxDistance;
float Padding0;
float IndirectLightingIntensity;
Vector4 RaysRotation;
Vector3 ViewDir;
uint32 RaysCount;
Vector3 FallbackIrradiance;
float Padding1;
float Padding0;
});
// Binding data for the GPU.

View File

@@ -343,11 +343,12 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
surfaceAtlasData.LastFrameUsed = currentFrame;
PROFILE_GPU_CPU("Global Surface Atlas");
// Setup options
// TODO: configurable via graphics settings
const int32 resolution = 2048;
const float resolutionInv = 1.0f / resolution;
// TODO: configurable via postFx settings (use GI distance)
const float distance = 20000.0f;
auto& giSettings = renderContext.List->Settings.GlobalIllumination;
const float distance = giSettings.Distance;
// Initialize buffers
bool noCache = surfaceAtlasData.Resolution != resolution;
@@ -847,32 +848,36 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
}
if (renderContext.View.Flags & ViewFlags::GI)
{
// TODO: add option to PostFx Volume for realtime GI type (None, DDGI)
DynamicDiffuseGlobalIlluminationPass::BindingData bindingDataDDGI;
if (!DynamicDiffuseGlobalIlluminationPass::Instance()->Get(renderContext.Buffers, bindingDataDDGI))
// Draw draw indirect light from Global Illumination
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
// Collect tiles to shade
_vertexBuffer->Clear();
for (const auto& e : surfaceAtlasData.Objects)
case GlobalIlluminationMode::DDGI:
{
DynamicDiffuseGlobalIlluminationPass::BindingData bindingDataDDGI;
if (!DynamicDiffuseGlobalIlluminationPass::Instance()->Get(renderContext.Buffers, bindingDataDDGI))
{
const auto& object = e.Value;
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
_vertexBuffer->Clear();
for (const auto& e : surfaceAtlasData.Objects)
{
auto* tile = object.Tiles[tileIndex];
if (!tile)
continue;
VB_WRITE_TILE(tile);
const auto& object = e.Value;
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
{
auto* tile = object.Tiles[tileIndex];
if (!tile)
continue;
VB_WRITE_TILE(tile);
}
}
data.DDGI = bindingDataDDGI.Constants;
context->BindSR(5, bindingDataDDGI.ProbesState);
context->BindSR(6, bindingDataDDGI.ProbesDistance);
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
context->UpdateCB(_cb0, &data);
context->SetState(_psIndirectLighting);
VB_DRAW();
}
// Draw draw indirect light
data.DDGI = bindingDataDDGI.Constants;
context->BindSR(5, bindingDataDDGI.ProbesState);
context->BindSR(6, bindingDataDDGI.ProbesDistance);
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
context->UpdateCB(_cb0, &data);
context->SetState(_psIndirectLighting);
VB_DRAW();
break;
}
}
}
@@ -888,11 +893,15 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output)
{
// Render all dependant effects
// Render all dependant effects before
if (renderContext.View.Flags & ViewFlags::GI)
{
// TODO: add option to PostFx Volume for realtime GI type (None, DDGI)
DynamicDiffuseGlobalIlluminationPass::Instance()->Render(renderContext, context, nullptr);
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
case GlobalIlluminationMode::DDGI:
DynamicDiffuseGlobalIlluminationPass::Instance()->Render(renderContext, context, nullptr);
break;
}
}
GlobalSignDistanceFieldPass::BindingData bindingDataSDF;
BindingData bindingData;

View File

@@ -416,7 +416,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
break;
}
const int32 resolutionMip = Math::DivideAndRoundUp(resolution, GLOBAL_SDF_RASTERIZE_MIP_FACTOR);
const float distance = true ? 20000.0f : 16000.0f; // TODO: switch based if using GI, then use GI range
auto& giSettings = renderContext.List->Settings.GlobalIllumination;
const float distance = giSettings.Mode == GlobalIlluminationMode::DDGI ? giSettings.Distance : 15000.0f;
const float cascadesDistanceScales[] = { 1.0f, 2.5f, 5.0f, 10.0f };
const float distanceExtent = distance / cascadesDistanceScales[cascadesCount - 1];

View File

@@ -401,8 +401,12 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
LightPass::Instance()->RenderLight(renderContext, *lightBuffer);
if (renderContext.View.Flags & ViewFlags::GI)
{
// TODO: add option to PostFx Volume for realtime GI type (None, DDGI)
DynamicDiffuseGlobalIlluminationPass::Instance()->Render(renderContext, context, *lightBuffer);
switch (renderContext.List->Settings.GlobalIllumination.Mode)
{
case GlobalIlluminationMode::DDGI:
DynamicDiffuseGlobalIlluminationPass::Instance()->Render(renderContext, context, *lightBuffer);
break;
}
}
if (renderContext.View.Mode == ViewMode::LightBuffer)
{

View File

@@ -30,12 +30,12 @@ struct DDGIData
float IrradianceGamma;
float ProbeHistoryWeight;
float RayMaxDistance;
float Padding0;
float IndirectLightingIntensity;
float4 RaysRotation;
float3 ViewDir;
uint RaysCount;
float3 FallbackIrradiance;
float Padding1;
float Padding0;
};
uint GetDDGIProbeIndex(DDGIData data, uint3 probeCoords)

View File

@@ -27,10 +27,9 @@ DDGIData DDGI;
GlobalSDFData GlobalSDF;
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
GBufferData GBuffer;
float2 Padding0;
float ResetBlend;
float TemporalTime;
float IndirectLightingIntensity;
float2 Padding0;
META_CB_END
META_CB_BEGIN(1, Data1)
@@ -343,7 +342,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
if (ResetBlend || dot(previous, previous) == 0)
historyWeight = 0.0f;
#if DDGI_PROBE_UPDATE_MODE == 0
result *= IndirectLightingIntensity;
result *= DDGI.IndirectLightingIntensity;
#if DDGI_SRGB_BLENDING
result.rgb = pow(result.rgb, 1.0f / DDGI.IrradianceGamma);
#endif

View File

@@ -120,6 +120,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target
// Sample irradiance
float bias = 1.0f;
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias);
irradiance /= DDGI.IndirectLightingIntensity;
//irradiance = 0;
// Calculate lighting