From d82368e3bc6b50f3ae9873be743ea488156b9d34 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Sun, 11 Aug 2024 17:51:37 -0400 Subject: [PATCH] feat(renodrt): add custom hue correction options --- src/shaders/RenoDRT.hlsl | 96 +++++++++++++++++++++++++++++++--------- src/shaders/tonemap.hlsl | 47 +++++++++++++------- 2 files changed, 108 insertions(+), 35 deletions(-) diff --git a/src/shaders/RenoDRT.hlsl b/src/shaders/RenoDRT.hlsl index 567c2df2..aea9542a 100644 --- a/src/shaders/RenoDRT.hlsl +++ b/src/shaders/RenoDRT.hlsl @@ -8,16 +8,18 @@ namespace tonemap { namespace renodrt { float3 BT709( float3 bt709, - float nits_peak = 1000.f / 203.f * 100.f, - float mid_gray_value = 0.18f, - float mid_gray_nits = 10.f, - float exposure = 1.f, - float highlights = 1.f, - float shadows = 1.f, // 0 = 0.10, 1.f = 0, >1 = contrast - float contrast = 1.1f, - float saturation = 1.f, - float dechroma = 0.5f, - float flare = 0.f) { + float nits_peak, + float mid_gray_value, + float mid_gray_nits, + float exposure, + float highlights, + float shadows, // 0 = 0.10, 1.f = 0, >1 = contrast + float contrast, + float saturation, + float dechroma, + float flare, + float hue_correction_strength, + float3 hue_correction_source) { const float n_r = 100.f; float n = 1000.f; @@ -46,7 +48,13 @@ float3 BT709( t_1 = flare; float y_original = renodx::color::y::from::BT709(abs(bt709)); - float3 lch_original = renodx::color::oklch::from::BT709(bt709); + + float3 restore_lab = (hue_correction_strength == 0) + ? 0 + : renodx::color::oklab::from::BT709(hue_correction_source); + float3 restore_lch = (hue_correction_strength == 0) + ? 0 + : renodx::color::oklch::from::OkLab(restore_lab); float y = y_original * exposure; @@ -82,17 +90,65 @@ float3 BT709( float y_new = clamp(flared, 0, m_0); float3 color_output = bt709 * (y_original > 0 ? (y_new / y_original) : 0); - - float3 lch_new = renodx::color::oklch::from::BT709(color_output); - lch_new[1] = lerp(lch_new[1], 0.f, saturate(pow(y_original / (10000.f / 100.f), (1.f - dechroma)))); - lch_new[1] *= saturation; - lch_new[2] = lch_original[2]; // hue correction - - float3 color = renodx::color::bt709::from::OkLCh(lch_new); - color = renodx::color::bt709::clamp::AP1(color); - color = min(m_0, color); // Clamp to Peak + float3 color = color_output; + + if (dechroma != 0.f || saturation != 1.f || hue_correction_strength != 0.f) { + float3 lab_new = renodx::color::oklab::from::BT709(color_output); + float3 lch_new = renodx::color::oklch::from::OkLab(lab_new); + + if (hue_correction_strength != 0.f) { + if (hue_correction_strength == 1.f) { + lch_new[2] = restore_lch[2]; // Full hue override + } else { + lab_new = float3(lab_new[0], lerp(lab_new.yz, restore_lab.yz, hue_correction_strength)); + float3 lch_temp = lab_new = renodx::color::oklch::from::OkLab(lab_new); + lch_temp[1] = lch_new[1]; // custom chroma restore + lch_new = lch_temp; + } + } + + if (dechroma != 0.f) { + lch_new[1] = lerp(lch_new[1], 0.f, saturate(pow(y_original / (10000.f / 100.f), (1.f - dechroma)))); + } + if (saturation != 1.f) { + lch_new[1] *= saturation; + } + + color = renodx::color::bt709::from::OkLCh(lch_new); + + color = renodx::color::bt709::clamp::AP1(color); + color = min(m_0, color); // Clamp to Peak + } return color; } +float3 BT709( + float3 bt709, + float nits_peak = 1000.f / 203.f * 100.f, + float mid_gray_value = 0.18f, + float mid_gray_nits = 10.f, + float exposure = 1.f, + float highlights = 1.f, + float shadows = 1.f, + float contrast = 1.1f, + float saturation = 1.f, + float dechroma = 0.5f, + float flare = 0.f, + float hue_correction_strength = 1.f) { + return BT709( + bt709, + nits_peak, + mid_gray_value, + mid_gray_nits, + exposure, + highlights, + shadows, + contrast, + saturation, + dechroma, + flare, + hue_correction_strength, + bt709); +} } // namespace renodrt } // namespace tonemap } // namespace renodx diff --git a/src/shaders/tonemap.hlsl b/src/shaders/tonemap.hlsl index 7fb1752c..aca0ec00 100644 --- a/src/shaders/tonemap.hlsl +++ b/src/shaders/tonemap.hlsl @@ -88,6 +88,9 @@ struct Config { float reno_drt_saturation; float reno_drt_dechroma; float reno_drt_flare; + float hue_correction_type; + float hue_correction_strength; + float3 hue_correction_color; }; float3 UpgradeToneMap(float3 color_hdr, float3 color_sdr, float3 post_process_color, float post_process_strength) { @@ -117,14 +120,20 @@ float3 UpgradeToneMap(float3 color_hdr, float3 color_sdr, float3 post_process_co namespace config { namespace type { -static const uint VANILLA = 0; -static const uint NONE = 1; -static const uint ACES = 2; -static const uint RENODRT = 3; +static const float VANILLA = 0.f; +static const float NONE = 1.f; +static const float ACES = 2.f; +static const float RENODRT = 3.f; } // namespace type +namespace hue_correction_type { +static const float INPUT = 0.f; +static const float CLAMPED = 1.f; +static const float CUSTOM = 2.f; +} // namespace hue_correction_type + Config Create( - float type = 0.f, + float type = config::type::VANILLA, float peak_nits = 203.f, float game_nits = 203.f, float gamma_correction = 0, @@ -140,7 +149,10 @@ Config Create( float reno_drt_contrast = 1.f, float reno_drt_saturation = 1.f, float reno_drt_dechroma = 0.5f, - float reno_drt_flare = 0.f) { + float reno_drt_flare = 0.f, + float hue_correction_type = config::hue_correction_type::INPUT, + float hue_correction_strength = 1.f, + float3 hue_correction_color = 0) { const Config config = { type, peak_nits, @@ -158,7 +170,10 @@ Config Create( reno_drt_contrast, reno_drt_saturation, reno_drt_dechroma, - reno_drt_flare}; + reno_drt_flare, + hue_correction_type, + hue_correction_strength, + hue_correction_color}; return config; } @@ -179,7 +194,11 @@ float3 ApplyRenoDRT(float3 color, Config config, bool sdr = false) { config.reno_drt_contrast, config.reno_drt_saturation, config.reno_drt_dechroma, - config.reno_drt_flare); + config.reno_drt_flare, + config.hue_correction_strength, + (config.hue_correction_type == config::hue_correction_type::CUSTOM) ? config.hue_correction_color + : (config.hue_correction_type == config::hue_correction_type::CLAMPED) ? clamp(color, 0, 1) + : color); } float3 ApplyACES(float3 color, Config config, bool sdr = false) { @@ -204,12 +223,10 @@ float3 ApplyACES(float3 color, Config config, bool sdr = false) { return color; } - - float3 Apply(float3 untonemapped, Config config) { float3 color = untonemapped; - if (config.type == 3.f) { + if (config.type == config::type::RENODRT) { config.reno_drt_highlights *= config.highlights; config.reno_drt_shadows *= config.shadows; config.reno_drt_contrast *= config.contrast; @@ -224,7 +241,7 @@ float3 Apply(float3 untonemapped, Config config) { config.shadows, config.contrast, config.saturation); - if (config.type == 2.f) { + if (config.type == config::type::ACES) { color = ApplyACES(color, config); } } @@ -240,7 +257,7 @@ float3 Apply(float3 untonemapped, Config config) { \ float3 color_hdr; \ float3 color_sdr; \ - if (config.type == 3.f) { \ + if (config.type == config::type::RENODRT) { \ config.reno_drt_saturation *= config.saturation; \ \ color_sdr = ApplyRenoDRT(color_output, config, true); \ @@ -255,7 +272,7 @@ float3 Apply(float3 untonemapped, Config config) { color_output = renodx::color::grade::UserColorGrading( \ color_output, config.exposure, config.highlights, config.shadows, config.contrast, config.saturation); \ \ - if (config.type == 2.f) { \ + if (config.type == config::type::ACES) { \ color_hdr = ApplyACES(color_output, config); \ color_sdr = ApplyACES(color_output, config, true); \ } else { \ @@ -275,7 +292,7 @@ float3 Apply(float3 untonemapped, Config config) { color_lut = min(1.f, renodx::lut::Sample(lut_texture, lut_config, color_hdr)); \ } \ \ - if (config.type == 0.f) { \ + if (config.type == config::type::VANILLA) { \ color_output = lerp(color_output, color_lut, lut_config.strength); \ } else { \ color_output = UpgradeToneMap(color_hdr, color_sdr, color_lut, lut_config.strength); \