From c3f7e737d48a87fa87e1cc230383cb24f86a74a0 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 21 Dec 2024 17:06:47 -0800 Subject: [PATCH] Added PBR-neutral tone mapping (close #247) --- Components/src/ToneMapping.cpp | 4 +++- .../ToneMapping/public/ToneMapping.fxh | 22 +++++++++++++++++++ .../public/ToneMappingStructures.fxh | 3 +++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Components/src/ToneMapping.cpp b/Components/src/ToneMapping.cpp index 57514841..a3251094 100644 --- a/Components/src/ToneMapping.cpp +++ b/Components/src/ToneMapping.cpp @@ -86,7 +86,7 @@ bool ToneMappingUpdateUI(HLSL::ToneMappingAttribs& Attribs, float* AverageLogLum { bool AttribsChanged = false; { - std::array ToneMappingMode{}; + std::array ToneMappingMode{}; ToneMappingMode[TONE_MAPPING_MODE_NONE] = "None"; ToneMappingMode[TONE_MAPPING_MODE_EXP] = "Exp"; ToneMappingMode[TONE_MAPPING_MODE_REINHARD] = "Reinhard"; @@ -97,6 +97,8 @@ bool ToneMappingUpdateUI(HLSL::ToneMappingAttribs& Attribs, float* AverageLogLum ToneMappingMode[TONE_MAPPING_ADAPTIVE_LOG] = "Adaptive log"; ToneMappingMode[TONE_MAPPING_AGX] = "AgX"; ToneMappingMode[TONE_MAPPING_AGX_CUSTOM] = "AgX Custom"; + ToneMappingMode[TONE_MAPPING_PBR_NEUTRAL] = "PBR Neutral"; + static_assert(TONE_MAPPING_MODE_COUNT == 11, "Please update ToneMappingMode array"); if (ImGui::Combo("Tone Mapping Mode", &Attribs.iToneMappingMode, ToneMappingMode.data(), static_cast(ToneMappingMode.size()))) AttribsChanged = true; } diff --git a/Shaders/PostProcess/ToneMapping/public/ToneMapping.fxh b/Shaders/PostProcess/ToneMapping/public/ToneMapping.fxh index 2c9276ba..168e8810 100644 --- a/Shaders/PostProcess/ToneMapping/public/ToneMapping.fxh +++ b/Shaders/PostProcess/ToneMapping/public/ToneMapping.fxh @@ -170,6 +170,28 @@ float3 ToneMap(in float3 f3Color, ToneMappingAttribs Attribs, float fAveLogLum) f3ToneMappedColor = AgXEotf(f3ToneMappedColor); return f3ToneMappedColor; } +#elif TONE_MAPPING_MODE == TONE_MAPPING_PBR_NEUTRAL + { + // https://modelviewer.dev/examples/tone-mapping + // https://github.com/KhronosGroup/ToneMapping/blob/main/PBR_Neutral/README.md#pbr-neutral-specification + float F90 = 0.04; // Fresnel reflection at normal incidence + float Ks = 0.8 - F90; // Highlight compression start + float Kd = 0.15; // Speed of desaturation + + float x = min(f3Color.r, min(f3Color.g, f3Color.b)); + float Offset = (x <= 2.0 * F90) ? (x - x * x / (4.0 * F90)) : F90; + float3 f3ToneMappedColor = f3Color - float3(Offset, Offset, Offset); + + float Peak = max(f3ToneMappedColor.r, max(f3ToneMappedColor.g, f3ToneMappedColor.b)); + if (Peak > Ks) + { + float NewPeak = 1.0 - (1.0 - Ks) * (1.0 - Ks) / (Peak + 1.0 - 2.0 * Ks); + f3ToneMappedColor *= NewPeak / Peak; + float g = 1.0 / (Kd * (Peak - NewPeak) + 1.0); + f3ToneMappedColor = lerp(float3(NewPeak, NewPeak, NewPeak), f3ToneMappedColor, g); + } + return f3ToneMappedColor; + } #else { return f3Color; diff --git a/Shaders/PostProcess/ToneMapping/public/ToneMappingStructures.fxh b/Shaders/PostProcess/ToneMapping/public/ToneMappingStructures.fxh index e3fb47f2..e2922c66 100644 --- a/Shaders/PostProcess/ToneMapping/public/ToneMappingStructures.fxh +++ b/Shaders/PostProcess/ToneMapping/public/ToneMappingStructures.fxh @@ -18,6 +18,9 @@ #define TONE_MAPPING_ADAPTIVE_LOG 7 #define TONE_MAPPING_AGX 8 #define TONE_MAPPING_AGX_CUSTOM 9 +#define TONE_MAPPING_PBR_NEUTRAL 10 +#define TONE_MAPPING_MODE_COUNT 11 + struct AgXAttribs {