diff --git a/src/games/unrealengine/addon.cpp b/src/games/unrealengine/addon.cpp index 96ffa703..f074c831 100644 --- a/src/games/unrealengine/addon.cpp +++ b/src/games/unrealengine/addon.cpp @@ -209,7 +209,7 @@ renodx::utils::settings::Settings settings = { .key = "ToneMapPerChannel", .binding = &shader_injection.toneMapPerChannel, .value_type = renodx::utils::settings::SettingValueType::INTEGER, - .default_value = 1.f, + .default_value = 0.f, .label = "Per Channel", .section = "Tone Mapping", .tooltip = "Applies tonemapping per-channel instead of by luminance", diff --git a/src/games/unrealengine/common.hlsl b/src/games/unrealengine/common.hlsl index 67edd1aa..0d245c0a 100644 --- a/src/games/unrealengine/common.hlsl +++ b/src/games/unrealengine/common.hlsl @@ -19,18 +19,18 @@ float3 PostToneMapScale(float3 color) { return color; } -float UpgradeToneMapRatio(float ap1_color_hdr, float ap1_color_sdr, float ap1_post_process_color) { - if (ap1_color_hdr < ap1_color_sdr) { +float UpgradeToneMapRatio(float color_hdr, float color_sdr, float post_process_color) { + if (color_hdr < color_sdr) { // If substracting (user contrast or paperwhite) scale down instead // Should only apply on mismatched HDR - return ap1_color_hdr / ap1_color_sdr; + return color_hdr / color_sdr; } else { - float ap1_delta = ap1_color_hdr - ap1_color_sdr; - ap1_delta = max(0, ap1_delta); // Cleans up NaN - const float ap1_new = ap1_post_process_color + ap1_delta; + float delta = color_hdr - color_sdr; + delta = max(0, delta); // Cleans up NaN + const float new_value = post_process_color + delta; - const bool ap1_valid = (ap1_post_process_color > 0); // Cleans up NaN and ignore black - return ap1_valid ? (ap1_new / ap1_post_process_color) : 0; + const bool valid = (post_process_color > 0); // Cleans up NaN and ignore black + return valid ? (new_value / post_process_color) : 0; } } float3 UpgradeToneMapPerChannel(float3 color_hdr, float3 color_sdr, float3 post_process_color, float post_process_strength) { @@ -52,6 +52,25 @@ float3 UpgradeToneMapPerChannel(float3 color_hdr, float3 color_sdr, float3 post_ return lerp(color_hdr, color_scaled, post_process_strength); } +float3 UpgradeToneMapByLuminance(float3 color_hdr, float3 color_sdr, float3 post_process_color, float post_process_strength) { + // float ratio = 1.f; + + float3 bt2020_hdr = max(0, renodx::color::bt2020::from::BT709(color_hdr)); + float3 bt2020_sdr = max(0, renodx::color::bt2020::from::BT709(color_sdr)); + float3 bt2020_post_process = max(0, renodx::color::bt2020::from::BT709(post_process_color)); + + float ratio = UpgradeToneMapRatio( + renodx::color::y::from::BT2020(bt2020_hdr), + renodx::color::y::from::BT2020(bt2020_sdr), + renodx::color::y::from::BT2020(bt2020_post_process)); + + float3 color_scaled = max(0, bt2020_post_process * ratio); + color_scaled = renodx::color::bt709::from::BT2020(color_scaled); + float peak_correction = saturate(1.f - renodx::color::y::from::BT2020(bt2020_post_process)); + color_scaled = renodx::color::correct::Hue(color_scaled, post_process_color, peak_correction); + return lerp(color_hdr, color_scaled, post_process_strength); +} + float3 FinalizeOutput(float3 color) { if (injectedData.toneMapGammaCorrection == 2.f) { color = renodx::color::gamma::DecodeSafe(color, 2.4f); @@ -162,12 +181,20 @@ float3 UpgradeToneMapAP1(float3 untonemapped_ap1, float3 tonemapped_bt709) { float3 neutral_sdr_color = RenoDRTSmoothClamp(untonemapped_bt709); - float3 untonemapped_graded = UpgradeToneMapPerChannel( - untonemapped_bt709, - neutral_sdr_color, - tonemapped_bt709, - 1); - + float3 untonemapped_graded; + if (injectedData.toneMapPerChannel == 1) { + untonemapped_graded = UpgradeToneMapPerChannel( + untonemapped_bt709, + neutral_sdr_color, + tonemapped_bt709, + 1); + } else { + untonemapped_graded = UpgradeToneMapByLuminance( + untonemapped_bt709, + neutral_sdr_color, + tonemapped_bt709, + 1); + } return ToneMap(untonemapped_graded); }