diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/AcesOutputTransformPass.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/AcesOutputTransformPass.h index 5fce71fc07..e891344bdd 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/AcesOutputTransformPass.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/AcesOutputTransformPass.h @@ -46,6 +46,7 @@ namespace AZ static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); void SetDisplayBufferFormat(RHI::Format format); + void SetAcesParameterOverrides(const DisplayMapperAcesParameters& acesParameterOverrides); private: explicit AcesOutputTransformPass(const RPI::PassDescriptor& descriptor); @@ -65,6 +66,8 @@ namespace AZ AZ::Render::DisplayMapperParameters m_displayMapperParameters = {}; RHI::Format m_displayBufferFormat = RHI::Format::Unknown; + + DisplayMapperAcesParameters m_acesParameterOverrides; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/DisplayMapperConfigurationDescriptor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/DisplayMapperConfigurationDescriptor.h index b645df4f6f..ca63fc054a 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/DisplayMapperConfigurationDescriptor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DisplayMapper/DisplayMapperConfigurationDescriptor.h @@ -24,6 +24,50 @@ namespace AZ namespace Render { + /** + * The ACES display mapper parameters. + * These parameters are input to the display mapper shader on the DisplayMapperPass. + */ + struct DisplayMapperAcesParameters + { + AZ_RTTI(DisplayMapperAcesParameters, "{3EE8C0D4-3792-46C0-B91C-B89A81C36B91}"); + AZ_CLASS_ALLOCATOR(DisplayMapperAcesParameters, SystemAllocator, 0); + + static void Reflect(ReflectContext* context); + + // When enabled allows parameter overrides for ACES configuration + bool m_overrideDefaults = false; + + // Apply gamma adjustment to compensate for dim surround + bool m_alterSurround; + // Apply desaturation to compensate for luminance difference + bool m_applyDesaturation; + // Apply Color appearance transform (CAT) from ACES white point to assumed observer adapted white point + bool m_applyCATD60toD65; + + // Reference white and black luminance values + float m_cinemaLimitsBlack = 0.02f; + float m_cinemaLimitsWhite = 48.0f; + + // luminance linear extension below this + float m_minPoint = 0.0028798957f; + // luminance mid grey + float m_midPoint = 4.8f; + // luminance linear extension above this + float m_maxPoint = 1005.71912f; + + // Gamma adjustment to be applied to compensate for the condition of the viewing environment. + // Note that ACES uses a value of 0.9811 for adjusting from dark to dim surrounding. + float m_surroundGamma = 0.9811f; + // Optional gamma value that is applied as basic gamma curve OETF + float m_gamma = 2.2f; + + // Allows specifying default preset for different ODT modes + OutputDeviceTransformType m_preset = OutputDeviceTransformType_48Nits; + + void LoadPreset(); + }; + //! A descriptor used to configure the DisplayMapper struct DisplayMapperConfigurationDescriptor final { @@ -37,6 +81,8 @@ namespace AZ bool m_ldrGradingLutEnabled = false; Data::Asset m_ldrColorGradingLut; + + DisplayMapperAcesParameters m_acesParameterOverrides; }; //! Custom pass data for DisplayMapperPass. diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/AcesOutputTransformPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/AcesOutputTransformPass.cpp index b2103739ba..1defb572aa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/AcesOutputTransformPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/AcesOutputTransformPass.cpp @@ -102,6 +102,36 @@ namespace AZ AcesDisplayMapperFeatureProcessor::GetAcesDisplayMapperParameters(&m_displayMapperParameters, OutputDeviceTransformType_48Nits); } } + + if (m_acesParameterOverrides.m_overrideDefaults) + { + m_displayMapperParameters.m_OutputDisplayTransformFlags = 0; + if (m_acesParameterOverrides.m_alterSurround) + { + m_displayMapperParameters.m_OutputDisplayTransformFlags |= 0x1; + } + if (m_acesParameterOverrides.m_applyDesaturation) + { + m_displayMapperParameters.m_OutputDisplayTransformFlags |= 0x2; + } + if (m_acesParameterOverrides.m_applyCATD60toD65) + { + m_displayMapperParameters.m_OutputDisplayTransformFlags |= 0x4; + } + + m_displayMapperParameters.m_cinemaLimits[0] = m_acesParameterOverrides.m_cinemaLimitsBlack; + m_displayMapperParameters.m_cinemaLimits[1] = m_acesParameterOverrides.m_cinemaLimitsWhite; + m_displayMapperParameters.m_acesSplineParams.minPoint[0] = m_acesParameterOverrides.m_minPoint; + m_displayMapperParameters.m_acesSplineParams.midPoint[0] = m_acesParameterOverrides.m_midPoint; + m_displayMapperParameters.m_acesSplineParams.maxPoint[0] = m_acesParameterOverrides.m_maxPoint; + m_displayMapperParameters.m_surroundGamma = m_acesParameterOverrides.m_surroundGamma; + m_displayMapperParameters.m_gamma = m_acesParameterOverrides.m_gamma; + } + } + + void AcesOutputTransformPass::SetAcesParameterOverrides(const DisplayMapperAcesParameters& acesParameterOverrides) + { + m_acesParameterOverrides = acesParameterOverrides; } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp index d80a02d083..eb73f310c0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperConfigurationDescriptor.cpp @@ -9,16 +9,58 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ + #include #include +#include namespace AZ { namespace Render { + void DisplayMapperAcesParameters::Reflect(ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("OverrideDefaults", &DisplayMapperAcesParameters::m_overrideDefaults) + ->Field("AlterSurround", &DisplayMapperAcesParameters::m_alterSurround) + ->Field("ApplyDesaturation", &DisplayMapperAcesParameters::m_applyDesaturation) + ->Field("ApplyCATD60toD65", &DisplayMapperAcesParameters::m_applyCATD60toD65) + ->Field("PresetODT", &DisplayMapperAcesParameters::m_preset) + ->Field("CinemaLimitsBlack", &DisplayMapperAcesParameters::m_cinemaLimitsBlack) + ->Field("CinemaLimitsWhite", &DisplayMapperAcesParameters::m_cinemaLimitsWhite) + ->Field("MinPoint", &DisplayMapperAcesParameters::m_minPoint) + ->Field("MidPoint", &DisplayMapperAcesParameters::m_midPoint) + ->Field("MaxPoint", &DisplayMapperAcesParameters::m_maxPoint) + ->Field("SurroundGamma", &DisplayMapperAcesParameters::m_surroundGamma) + ->Field("Gamma", &DisplayMapperAcesParameters::m_gamma); + } + } + + void DisplayMapperAcesParameters::LoadPreset() + { + DisplayMapperParameters displayMapperParameters; + AcesDisplayMapperFeatureProcessor::GetAcesDisplayMapperParameters(&displayMapperParameters, m_preset); + + m_alterSurround = (displayMapperParameters.m_OutputDisplayTransformFlags & 0x1) != 0; + m_applyDesaturation = (displayMapperParameters.m_OutputDisplayTransformFlags & 0x2) != 0; + m_applyCATD60toD65 = (displayMapperParameters.m_OutputDisplayTransformFlags & 0x4) != 0; + m_cinemaLimitsBlack = displayMapperParameters.m_cinemaLimits[0]; + m_cinemaLimitsWhite = displayMapperParameters.m_cinemaLimits[1]; + m_minPoint = displayMapperParameters.m_acesSplineParams.minPoint[0]; + m_midPoint = displayMapperParameters.m_acesSplineParams.midPoint[0]; + m_maxPoint = displayMapperParameters.m_acesSplineParams.maxPoint[0]; + m_surroundGamma = displayMapperParameters.m_surroundGamma; + m_gamma = displayMapperParameters.m_gamma; + } + void DisplayMapperConfigurationDescriptor::Reflect(AZ::ReflectContext* context) { + DisplayMapperAcesParameters::Reflect(context); + if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Enum() diff --git a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp index 1de92c42f6..8ae790e12c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DisplayMapper/DisplayMapperPass.cpp @@ -106,6 +106,7 @@ namespace AZ { if (m_acesOutputTransformPass) { + m_acesOutputTransformPass->SetAcesParameterOverrides(m_displayMapperConfigurationDescriptor.m_acesParameterOverrides); m_acesOutputTransformPass->SetDisplayBufferFormat(m_displayBufferFormat); } if (m_bakeAcesOutputTransformLutPass) @@ -509,7 +510,8 @@ namespace AZ if (desc.m_operationType != m_displayMapperConfigurationDescriptor.m_operationType || desc.m_ldrGradingLutEnabled != m_displayMapperConfigurationDescriptor.m_ldrGradingLutEnabled || - desc.m_ldrColorGradingLut != m_displayMapperConfigurationDescriptor.m_ldrColorGradingLut) + desc.m_ldrColorGradingLut != m_displayMapperConfigurationDescriptor.m_ldrColorGradingLut || + desc.m_acesParameterOverrides.m_overrideDefaults != m_displayMapperConfigurationDescriptor.m_acesParameterOverrides.m_overrideDefaults) { m_needToRebuildChildren = true; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h index 81645b25a9..f3e3c63f5a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h @@ -20,7 +20,6 @@ namespace AZ { namespace Render { - class DisplayMapperComponentConfig final : public ComponentConfig { @@ -33,6 +32,7 @@ namespace AZ DisplayMapperOperationType m_displayMapperOperation = DisplayMapperOperationType::Aces; bool m_ldrColorGradingLutEnabled = false; Data::Asset m_ldrColorGradingLut = {}; + DisplayMapperAcesParameters m_acesParameterOverrides; }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentConfig.cpp index e6afd4f21f..94b7dd6fb0 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentConfig.cpp @@ -23,13 +23,13 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("DisplayMapperOperationType", &DisplayMapperComponentConfig::m_displayMapperOperation) ->Field("LdrColorGradingLutEnabled", &DisplayMapperComponentConfig::m_ldrColorGradingLutEnabled) ->Field("LdrColorGradingLut", &DisplayMapperComponentConfig::m_ldrColorGradingLut) + ->Field("AcesParameters", &DisplayMapperComponentConfig::m_acesParameterOverrides) ; } } - } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp index d90e170322..0e283199e7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/DisplayMapperComponentController.cpp @@ -85,6 +85,7 @@ namespace AZ desc.m_operationType = m_configuration.m_displayMapperOperation; desc.m_ldrGradingLutEnabled = m_configuration.m_ldrColorGradingLutEnabled; desc.m_ldrColorGradingLut = m_configuration.m_ldrColorGradingLut; + desc.m_acesParameterOverrides = m_configuration.m_acesParameterOverrides; fp->RegisterDisplayMapperConfiguration(desc); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp index 80aad79218..9b0e5a9553 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp @@ -10,6 +10,8 @@ * */ +#include "Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h" + #include #include @@ -47,6 +49,76 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ; + editContext->Class( + "DisplayMapperAcesParameters", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &DisplayMapperAcesParameters::m_overrideDefaults, "Override Defaults", + "When enabled allows parameter overrides for ACES configuration") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &DisplayMapperAcesParameters::m_alterSurround, "Alter Surround", + "Apply gamma adjustment to compensate for dim surround") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &DisplayMapperAcesParameters::m_applyDesaturation, "Alter Desaturation", + "Apply desaturation to compensate for luminance difference") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &DisplayMapperAcesParameters::m_applyCATD60toD65, "Alter CAT D60 to D65", + "Apply Color appearance transform (CAT) from ACES white point to assumed observer adapted white point") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement( + Edit::UIHandlers::Default, &DisplayMapperAcesParameters::m_cinemaLimitsBlack, + "Cinema Limit (black)", + "Reference black luminance value") + ->DataElement( + Edit::UIHandlers::Default, &DisplayMapperAcesParameters::m_cinemaLimitsWhite, + "Cinema Limit (white)", + "Reference white luminance value") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement( + Edit::UIHandlers::Vector2, &DisplayMapperAcesParameters::m_minPoint, "Min Point (luminance)", + "Linear extension below this") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement( + Edit::UIHandlers::Vector2, &DisplayMapperAcesParameters::m_midPoint, "Mid Point (luminance)", + "Middle gray") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement( + Edit::UIHandlers::Vector2, &DisplayMapperAcesParameters::m_maxPoint, "Max Point (luminance)", + "Linear extension above this") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + ->DataElement( + AZ::Edit::UIHandlers::Default, &DisplayMapperAcesParameters::m_surroundGamma, "Surround Gamma", + "Gamma adjustment to be applied to compensate for the condition of the viewing environment") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement( + AZ::Edit::UIHandlers::Default, &DisplayMapperAcesParameters::m_gamma, "Gamma", + "Optional gamma value that is applied as basic gamma curve OETF") + ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + + // Load preset group + ->ClassElement(AZ::Edit::ClassElements::Group, "Load Preset") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement( + Edit::UIHandlers::ComboBox, &DisplayMapperAcesParameters::m_preset, "Preset Selection", + "Allows specifying default preset for different ODT modes") + ->EnumAttribute(OutputDeviceTransformType::OutputDeviceTransformType_48Nits, "48 Nits") + ->EnumAttribute(OutputDeviceTransformType::OutputDeviceTransformType_1000Nits, "1000 Nits") + ->EnumAttribute(OutputDeviceTransformType::OutputDeviceTransformType_2000Nits, "2000 Nits") + ->EnumAttribute(OutputDeviceTransformType::OutputDeviceTransformType_4000Nits, "4000 Nits") + ->UIElement(AZ::Edit::UIHandlers::Button, "Load", "Load default preset") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &DisplayMapperAcesParameters::LoadPreset) + ->Attribute(AZ::Edit::Attributes::ButtonText, "Load") + ; + editContext->Class("ToneMapperComponentConfig", "") ->ClassElement(Edit::ClassElements::EditorData, "") ->DataElement(Edit::UIHandlers::ComboBox, @@ -64,7 +136,10 @@ namespace AZ &DisplayMapperComponentConfig::m_ldrColorGradingLutEnabled, "Enable LDR color grading LUT", "Enable LDR color grading LUT.") - ->DataElement(AZ::Edit::UIHandlers::Default, &DisplayMapperComponentConfig::m_ldrColorGradingLut, "LDR color Grading LUT", "LDR color grading LUT"); + ->DataElement(AZ::Edit::UIHandlers::Default, &DisplayMapperComponentConfig::m_ldrColorGradingLut, "LDR color Grading LUT", "LDR color grading LUT") + ->DataElement(AZ::Edit::UIHandlers::Default, &DisplayMapperComponentConfig::m_acesParameterOverrides, "ACES Parameters", "Parameter overrides for ACES.") + ; + } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.h index 12c3f5292c..ed69509bac 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.h @@ -34,6 +34,7 @@ namespace AZ //! EditorRenderComponentAdapter overrides... AZ::u32 OnConfigurationChanged() override; + }; } // namespace Render