Skip to content

Commit

Permalink
Add exponential and exponential squared fog modes (#17866)
Browse files Browse the repository at this point in the history
Add density clamp to deferred fog
Add tests for new attributes of deferred fog

Signed-off-by: Akio Gaule <10719597+akioCL@users.noreply.github.com>
  • Loading branch information
akioCL committed May 3, 2024
1 parent e8daedd commit 9292148
Show file tree
Hide file tree
Showing 10 changed files with 369 additions and 199 deletions.
37 changes: 27 additions & 10 deletions AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@
'PlanetCenterAtLocalOrigin': 2,
}

# Fog Mode
FOG_MODES = {
'Linear': 0,
'Exponential': 1,
'ExponentialSquared': 2
}

# Level list used in Editor Level Load Test
# WARNING: "Sponza" level is sandboxed due to an intermittent failure.
LEVEL_LIST = ["hermanubis", "hermanubis_high", "macbeth_shaderballs", "PbrMaterialChart", "ShadowTest"]
Expand Down Expand Up @@ -392,6 +399,13 @@ def deferred_fog(property: str = 'name') -> str:
- 'Octaves Blend Factor' Blend factor between the noise octaves (0.0, 1.0).
- 'Enable Turbulence Properties' Enables Turbulence Properties (bool).
- 'Enable Fog Layer' Enables the fog layer (bool).
- 'Fog Mode' Set the fog formula
(enum, Uses above dictionary FOG_MODES)
Linear: f = (end - d)/(end - start)
Exponential: f = 1/exp(d * density)
ExponentialSquared: f = 1/exp((d * density)^2)
- 'Fog Density': Density control for Exponential and ExponentialSquared modes.
- 'Fog Density Clamp': The maximum density that the fog can reach.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
Expand All @@ -400,18 +414,21 @@ def deferred_fog(property: str = 'name') -> str:
'requires': [AtomComponentProperties.postfx_layer()],
'Enable Deferred Fog': 'Controller|Configuration|Enable Deferred Fog',
'Fog Color': 'Controller|Configuration|Fog Color',
'Fog Start Distance': 'Controller|Configuration|Fog Start Distance',
'Fog End Distance': 'Controller|Configuration|Fog End Distance',
'Fog Bottom Height': 'Controller|Configuration|Fog Bottom Height',
'Fog Max Height': 'Controller|Configuration|Fog Max Height',
'Noise Texture': 'Controller|Configuration|Noise Texture',
'Noise Texture First Octave Scale': 'Controller|Configuration|Noise Texture First Octave Scale',
'Noise Texture First Octave Velocity': 'Controller|Configuration|Noise Texture First Octave Velocity',
'Noise Texture Second Octave Scale': 'Controller|Configuration|Noise Texture Second Octave Scale',
'Noise Texture Second Octave Velocity': 'Controller|Configuration|Noise Texture Second Octave Velocity',
'Octaves Blend Factor': 'Controller|Configuration|Octaves Blend Factor',
'Fog Start Distance': 'Controller|Configuration|Distance|Fog Start Distance',
'Fog End Distance': 'Controller|Configuration|Distance|Fog End Distance',
'Fog Bottom Height': 'Controller|Configuration|Fog Layer|Fog Bottom Height',
'Fog Max Height': 'Controller|Configuration|Fog Layer|Fog Max Height',
'Noise Texture': 'Controller|Configuration|Turbulence|Noise Texture',
'Noise Texture First Octave Scale': 'Controller|Configuration|Turbulence|Noise Texture First Octave Scale',
'Noise Texture First Octave Velocity': 'Controller|Configuration|Turbulence|Noise Texture First Octave Velocity',
'Noise Texture Second Octave Scale': 'Controller|Configuration|Turbulence|Noise Texture Second Octave Scale',
'Noise Texture Second Octave Velocity': 'Controller|Configuration|Turbulence|Noise Texture Second Octave Velocity',
'Octaves Blend Factor': 'Controller|Configuration|Turbulence|Octaves Blend Factor',
'Enable Turbulence Properties': 'Controller|Configuration|Enable Turbulence Properties',
'Enable Fog Layer': 'Controller|Configuration|Enable Fog Layer',
'Fog Density': 'Controller|Configuration|Density Control|Fog Density',
'Fog Density Clamp': 'Controller|Configuration|Density Control|Fog Density Clamp',
'Fog Mode': 'Controller|Configuration|Fog Mode',
}
return properties[property]

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
float3 m_fogColor;
float m_fogStartDistance; // Distance at which the fog starts to appear
float m_fogEndDistance; // Distance for complete fog color taking over
float m_fogDensity;
float m_fogDensityClamp;

#if ENABLE_FOG_LAYER
float m_fogMinHeight; // Minmum and Maximum fog layer heights
Expand Down Expand Up @@ -79,6 +81,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback

option bool o_useNoiseTexture = true;
option bool o_enableFogLayer = true;
// "Linear" is a reserved keyword, so we change it to "LinearMode"
option enum class FogMode { LinearMode, ExponentialMode, ExponentialSquaredMode } o_fogMode = FogMode::LinearMode;

#if ENABLE_FOG_LAYER
float CalculateFogDensity(float3 surfacePosWS, float depthInLayer)
Expand Down Expand Up @@ -194,17 +198,32 @@ PSOutput MainPS(VSOutput IN)
linearDepth *= lerp(1.0, fogDensity, fogDistanceDeviationRatio);

// The following line is the linear depth traversing the layer
linearDepth = fogTraversalRelLength * linearDepth - max( 0, PassSrg::m_fogStartDistance - distToFogLayer * linearDepth);
linearDepth = max(0, fogTraversalRelLength * linearDepth - max( 0, PassSrg::m_fogStartDistance - distToFogLayer * linearDepth));
}
else
#endif // ENABLE_FOG_LAYER
{
linearDepth = max( 0, linearDepth - PassSrg::m_fogStartDistance );
}

float layerFogAmountWithStartDist = saturate(linearDepth / (PassSrg::m_fogEndDistance - PassSrg::m_fogStartDistance));
float density = 0.0f;
switch(o_fogMode)
{
case FogMode::LinearMode:
density = saturate(linearDepth / (PassSrg::m_fogEndDistance - PassSrg::m_fogStartDistance));
break;
case FogMode::ExponentialMode:
density = 1.0 - exp(-linearDepth * PassSrg::m_fogDensity);
break;
case FogMode::ExponentialSquaredMode:
density = 1.0 - exp(-pow(linearDepth * PassSrg::m_fogDensity, 2));
break;
default:
break;
}

OUT.m_color = float4(PassSrg::m_fogColor, layerFogAmountWithStartDist);
density = clamp(density, 0.0, PassSrg::m_fogDensityClamp);
OUT.m_color = float4(PassSrg::m_fogColor, density);

return OUT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ AZ_GFX_FLOAT_PARAM(FogEndDistance, m_fogEndDistance, 5.0f )
AZ_GFX_FLOAT_PARAM(FogMinHeight, m_fogMinHeight, 0.01f)
AZ_GFX_FLOAT_PARAM(FogMaxHeight, m_fogMaxHeight, 1.0f)

AZ_GFX_FLOAT_PARAM(FogDensity, m_fogDensity, 0.33f)
AZ_GFX_FLOAT_PARAM(FogDensityClamp, m_fogDensityClamp, 1.0f)
AZ_GFX_COMMON_PARAM(Render::FogMode, FogMode, m_fogMode, FogMode::Linear)

AZ_GFX_TEXTURE2D_PARAM(NoiseTexture, m_noiseTexture, "textures/cloudnoise_01.jpg.streamingimage")

// First noise octave
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@

#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/Preprocessor/Enum.h>

namespace AZ
{
namespace Render
{
AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE(
FogMode,
uint8_t,
(Linear, 0), //!< f = (end - d)/(end - start). "d" represents depth, or the distance from the viewpoint
(Exponential, 1), //!< f = 1/exp(d * density). "density" is an arbitrary fog density that can range from 0.0 to 1.0.
(ExponentialSquared, 2) //!< f = 1/exp((d * density)^2). "density" is an arbitrary fog density that can range from 0.0 to 1.0.
);

class DeferredFogSettingsInterface
{
public:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ namespace AZ
{
namespace Render
{
static const char* const FogModeOptionName{ "o_fogMode" };

AZ_CVAR(bool, r_enableFog, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable fog");

DeferredFogPass::DeferredFogPass(const RPI::PassDescriptor& descriptor)
: RPI::FullscreenTrianglePass(descriptor)
, m_fogModeOptionName(FogModeOptionName)
{
}

Expand Down Expand Up @@ -214,6 +216,21 @@ namespace AZ
fogSettings->GetEnableFogLayerShaderOption() ? AZ::Name("true") : AZ::Name("false"));
shaderOption.SetValue(AZ::Name("o_useNoiseTexture"),
fogSettings->GetUseNoiseTextureShaderOption() ? AZ::Name("true") : AZ::Name("false"));
switch (fogSettings->GetFogMode())
{
case FogMode::Linear:
shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::LinearMode"));
break;
case FogMode::Exponential:
shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::ExponentialMode"));
break;
case FogMode::ExponentialSquared:
shaderOption.SetValue(m_fogModeOptionName, AZ::Name("FogMode::ExponentialSquaredMode"));
break;
default:
AZ_Error("DeferredFogPass", false, "Invalid fog mode %d", fogSettings->GetFogMode());
break;
}

// The following method returns the specified options, as well as fall back values for all
// non-specified options. If all were set you can use the method GetShaderVariantKey that is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ namespace AZ

// Shader options for variant generation (texture and layer activation in this case)
AZ::RPI::ShaderVariantKey m_ShaderOptions;

// Fog mode option name
const AZ::Name m_fogModeOptionName;
};
} // namespace Render
} // namespace AZ
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include <AzCore/Component/Component.h>
#include <Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h>

namespace AZ
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ namespace AZ
return m_enableFogLayerShaderOption;
}

bool SupportsFogDensity()
{
return m_fogMode == FogMode::Exponential || m_fogMode == FogMode::ExponentialSquared;
}
bool SupportsFogEnd()
{
return m_fogMode == FogMode::Linear;
}

// Generate Get / Set methods
#define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \
virtual ValueType Get##Name() const { return MemberName; } \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace AZ
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorDeferredFogComponent, BaseClass>()
->Version(1);
->Version(2);

if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
Expand Down Expand Up @@ -53,9 +53,27 @@ namespace AZ
"Enable Deferred Fog.")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->DataElement(Edit::UIHandlers::CheckBox, &DeferredFogComponentConfig::m_enableFogLayerShaderOption,
"Enable Fog Layer",
"Enable Fog Layer")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->DataElement(Edit::UIHandlers::CheckBox, &DeferredFogComponentConfig::m_useNoiseTextureShaderOption,
"Enable Turbulence Properties",
"Enable Turbulence Properties")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->DataElement(AZ::Edit::UIHandlers::Color, &DeferredFogComponentConfig::m_fogColor,
"Fog Color", "The fog color.")
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->DataElement(Edit::UIHandlers::ComboBox, &DeferredFogComponentConfig::m_fogMode,
"Fog Mode",
"Which formula to use for calculating the fog.")
->Attribute(AZ::Edit::Attributes::EnumValues, AZ::Edit::GetEnumConstantsFromTraits<Render::FogMode>())

->ClassElement(Edit::ClassElements::Group, "Distance")
->Attribute(Edit::Attributes::AutoExpand, true)

->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogStartDistance,
"Fog Start Distance", "The distance from the viewer when the fog starts")
Expand All @@ -66,20 +84,40 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogEndDistance,
"Fog End Distance", "At what distance from the viewer does the fog take over and mask the background scene out")
"Fog End Distance", "At what distance from the viewer does the fog take over and mask the background scene out.")
->Attribute(AZ::Edit::Attributes::Min, &DeferredFogComponentConfig::m_fogStartDistance)
->Attribute(AZ::Edit::Attributes::Max, 5000.0f)
->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
->Attribute(AZ::Edit::Attributes::SoftMax, 100.0f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::SupportsFogEnd)

// Fog layer properties
->DataElement(Edit::UIHandlers::CheckBox,
&DeferredFogComponentConfig::m_enableFogLayerShaderOption,
"Enable Fog Layer",
"Enable Fog Layer")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->ClassElement(Edit::ClassElements::Group, "Density Control")
->Attribute(Edit::Attributes::AutoExpand, true)

->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogDensity,
"Fog Density",
"Density of the fog that can range from 0.0 to 1.0")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Max, 1.0f)
->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
->Attribute(AZ::Edit::Attributes::SoftMax, 1.0f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::SupportsFogDensity)

->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogDensityClamp,
"Fog Density Clamp",
"The maximum density that the fog can reach. This enables the sky, horizon, and other bright, distant objects to be visible through dense fog.")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Max, 1.0f)
->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
->Attribute(AZ::Edit::Attributes::SoftMax, 1.0f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

// Fog layer properties
->ClassElement(Edit::ClassElements::Group, "Fog Layer")
->Attribute(Edit::Attributes::AutoExpand, true)
->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::GetEnableFogLayerShaderOption)
->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogMinHeight,
"Fog Bottom Height", "The height at which the fog layer starts")
->Attribute(AZ::Edit::Attributes::Min, -5000.0f)
Expand All @@ -88,6 +126,7 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::SoftMax, 1000.0f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)


->DataElement(AZ::Edit::UIHandlers::Slider, &DeferredFogComponentConfig::m_fogMaxHeight,
"Fog Max Height", "The height of the fog layer top")
->Attribute(AZ::Edit::Attributes::Min, -5000.0f)
Expand All @@ -97,12 +136,9 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

// Fog turbulence properties
->DataElement(Edit::UIHandlers::CheckBox,
&DeferredFogComponentConfig::m_useNoiseTextureShaderOption,
"Enable Turbulence Properties",
"Enable Turbulence Properties")
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)

->ClassElement(Edit::ClassElements::Group, "Turbulence")
->Attribute(Edit::Attributes::AutoExpand, true)
->Attribute(Edit::Attributes::Visibility, &DeferredFogComponentConfig::GetUseNoiseTextureShaderOption)
->DataElement(AZ::Edit::UIHandlers::LineEdit, &DeferredFogComponentConfig::m_noiseTexture,
"Noise Texture", "The noise texture used for creating the fog turbulence")
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
Expand Down

0 comments on commit 9292148

Please sign in to comment.