From f811d8df68a139ee336b6318bb1fb9dc9084b999 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 12 Aug 2024 16:50:35 -0400 Subject: [PATCH 1/5] lint(shaders): code cleanup --- src/shaders/DICE.hlsl | 4 ++ src/shaders/aces.hlsl | 38 ++++++-------- src/shaders/math.hlsl | 112 ++++++++++++++++++++-------------------- src/shaders/renodx.hlsl | 1 + 4 files changed, 77 insertions(+), 78 deletions(-) diff --git a/src/shaders/DICE.hlsl b/src/shaders/DICE.hlsl index c3943bf3..e31fa016 100644 --- a/src/shaders/DICE.hlsl +++ b/src/shaders/DICE.hlsl @@ -1,3 +1,5 @@ +#ifndef SRC_SHADERS_DICE_HLSL_ +#define SRC_SHADERS_DICE_HLSL_ #include "./math.hlsl" @@ -72,3 +74,5 @@ float3 BT709(float3 color, float output_luminance_max, float highlights_shoulder } // namespace dice } // namespace tonemap } // namespace renodx + +#endif // SRC_SHADERS_DICE_HLSL_ \ No newline at end of file diff --git a/src/shaders/aces.hlsl b/src/shaders/aces.hlsl index 05b0a691..cd69a0d0 100644 --- a/src/shaders/aces.hlsl +++ b/src/shaders/aces.hlsl @@ -1,33 +1,27 @@ -#ifndef SRC_COMMON_ACES_HLSL_ -#define SRC_COMMON_ACES_HLSL_ +#ifndef SRC_SHADERS_ACES_HLSL_ +#define SRC_SHADERS_ACES_HLSL_ #include "./color.hlsl" #include "./math.hlsl" - namespace renodx { namespace tonemap { namespace aces { -// clang-format off + static const float3x3 RRT_SAT_MAT = float3x3( - 0.9708890, 0.0269633, 0.00214758, - 0.0108892, 0.9869630, 0.00214758, - 0.0108892, 0.0269633, 0.96214800 -); + 0.9708890, 0.0269633, 0.00214758, + 0.0108892, 0.9869630, 0.00214758, + 0.0108892, 0.0269633, 0.96214800); static const float3x3 ODT_SAT_MAT = float3x3( - 0.949056, 0.0471857, 0.00375827, - 0.019056, 0.9771860, 0.00375827, - 0.019056, 0.0471857, 0.93375800 -); + 0.949056, 0.0471857, 0.00375827, + 0.019056, 0.9771860, 0.00375827, + 0.019056, 0.0471857, 0.93375800); static const float3x3 M = float3x3( - 0.5, -1.0, 0.5, - -1.0, 1.0, 0.0, - 0.5, 0.5, 0.0 -); - -// clang-format on + 0.5, -1.0, 0.5, + -1.0, 1.0, 0.0, + 0.5, 0.5, 0.0); float Rgb2Yc(float3 rgb) { const float yc_radius_weight = 1.75; @@ -460,14 +454,14 @@ float3 RRTAndODT(float3 color, float min_y, float max_y, float3x3 odt_matrix = r // Output Display Transform float3 RGCAndRRTAndODT(float3 color, float min_y, float max_y, float3x3 odt_matrix = renodx::color::AP1_TO_BT709_MAT) { color = mul(renodx::color::BT709_TO_AP1_MAT, color); // BT709 to AP1 - color = GamutCompress(color); // Compresses to AP1 + color = GamutCompress(color); // Compresses to AP1 color = mul(renodx::color::AP1_TO_AP0_MAT, color); // Convert to AP0 - color = RRT(color); // RRT AP0 => AP1 - color = ODT(color, min_y, max_y, odt_matrix); // ODT AP1 => Matrix + color = RRT(color); // RRT AP0 => AP1 + color = ODT(color, min_y, max_y, odt_matrix); // ODT AP1 => Matrix return color; } } // namespace aces } // namespace tonemap } // namespace renodx -#endif // SRC_COMMON_ACES_HLSL_ \ No newline at end of file +#endif // SRC_SHADERS_ACES_HLSL_ \ No newline at end of file diff --git a/src/shaders/math.hlsl b/src/shaders/math.hlsl index 4d3f487d..05a61b16 100644 --- a/src/shaders/math.hlsl +++ b/src/shaders/math.hlsl @@ -1,56 +1,56 @@ -#ifndef SRC_COMMON_MATH_HLSL_ -#define SRC_COMMON_MATH_HLSL_ - -namespace renodx { -namespace math { - -static const float FLT_MIN = asfloat(0x00800000); // 1.175494351e-38f -static const float FLT_MAX = asfloat(0x7F7FFFFF); // 3.402823466e+38f -static const float FLT10_MAX = 64512.f; -static const float FLT11_MAX = 65024.f; -static const float FLT16_MAX = 65504.f; - - float3 SafePow(float3 color, float exponent){ - return sign(color) * pow(abs(color), exponent); - } - - float SafePow(float color, float exponent){ - return sign(color) * pow(abs(color), exponent); - } - -float3 Pow(float3 color, float exponent){ - return pow(color, exponent); - } - -float Average(float3 color) { - return (color.x + color.y + color.z) / 3.f; -} - -// Returns 1 or FLT_MAX if "dividend" is 0 -float SafeDivision(float quotient, float dividend) { - return (dividend == 0.f) - ? FLT_MAX * sign(quotient) - : (quotient / dividend); -} - -float SafeDivision(float quotient, float dividend, float fallback) { - return (dividend == 0.f) - ? fallback - : (quotient / dividend); -} - -float3 SafeDivision(float3 quotient, float3 dividend) { - return float3(SafeDivision(quotient.x, dividend.x, FLT_MAX * sign(quotient.x)), - SafeDivision(quotient.y, dividend.y, FLT_MAX * sign(quotient.y)), - SafeDivision(quotient.z, dividend.z, FLT_MAX * sign(quotient.z))); -} - -float3 SafeDivision(float3 quotient, float3 dividend, float3 fallback) { - return float3(SafeDivision(quotient.x, dividend.x, fallback.x), - SafeDivision(quotient.y, dividend.y, fallback.y), - SafeDivision(quotient.z, dividend.z, fallback.z)); -} - -} // namespace math -} // namespace renodx -#endif // SRC_COMMON_MATH_HLSL_ +#ifndef SRC_SHADERS_MATH_HLSL_ +#define SRC_SHADERS_MATH_HLSL_ + +namespace renodx { +namespace math { + +static const float FLT_MIN = asfloat(0x00800000); // 1.175494351e-38f +static const float FLT_MAX = asfloat(0x7F7FFFFF); // 3.402823466e+38f +static const float FLT10_MAX = 64512.f; +static const float FLT11_MAX = 65024.f; +static const float FLT16_MAX = 65504.f; + +float3 SafePow(float3 color, float exponent) { + return sign(color) * pow(abs(color), exponent); +} + +float1 SafePow(float color, float exponent) { + return sign(color) * pow(abs(color), exponent); +} + +float3 Pow(float3 color, float exponent) { + return pow(color, exponent); +} + +float Average(float3 color) { + return (color.x + color.y + color.z) / 3.f; +} + +// Returns 1 or FLT_MAX if "dividend" is 0 +float SafeDivision(float quotient, float dividend) { + return (dividend == 0.f) + ? FLT_MAX * sign(quotient) + : (quotient / dividend); +} + +float SafeDivision(float quotient, float dividend, float fallback) { + return (dividend == 0.f) + ? fallback + : (quotient / dividend); +} + +float3 SafeDivision(float3 quotient, float3 dividend) { + return float3(SafeDivision(quotient.x, dividend.x, FLT_MAX * sign(quotient.x)), + SafeDivision(quotient.y, dividend.y, FLT_MAX * sign(quotient.y)), + SafeDivision(quotient.z, dividend.z, FLT_MAX * sign(quotient.z))); +} + +float3 SafeDivision(float3 quotient, float3 dividend, float3 fallback) { + return float3(SafeDivision(quotient.x, dividend.x, fallback.x), + SafeDivision(quotient.y, dividend.y, fallback.y), + SafeDivision(quotient.z, dividend.z, fallback.z)); +} + +} // namespace math +} // namespace renodx +#endif // SRC_SHADERS_MATH_HLSL_ \ No newline at end of file diff --git a/src/shaders/renodx.hlsl b/src/shaders/renodx.hlsl index 4da3908d..f8c28bc5 100644 --- a/src/shaders/renodx.hlsl +++ b/src/shaders/renodx.hlsl @@ -11,5 +11,6 @@ #include "./random.hlsl" #include "./tonemap.hlsl" #include "./DICE.hlsl" +#include "./math.hlsl" #endif // SRC_SHADERS_RENODX_HLSL_ \ No newline at end of file From c1eaac49801318b065e274bdba5c6457bfb3c9c4 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 12 Aug 2024 18:06:40 -0400 Subject: [PATCH 2/5] feat(tonemap): support hue_correction with luts --- src/shaders/tonemap.hlsl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shaders/tonemap.hlsl b/src/shaders/tonemap.hlsl index aca0ec00..f0163c26 100644 --- a/src/shaders/tonemap.hlsl +++ b/src/shaders/tonemap.hlsl @@ -265,9 +265,13 @@ float3 Apply(float3 untonemapped, Config config) { config.reno_drt_highlights *= config.highlights; \ config.reno_drt_shadows *= config.shadows; \ config.reno_drt_contrast *= config.contrast; \ + uint previous_hue_correction_type = config.hue_correction_type; \ + config.hue_correction_type = config::hue_correction_type::INPUT; \ \ color_hdr = ApplyRenoDRT(color_output, config); \ \ + config.hue_correction_type = previous_hue_correction_type; \ + \ } else { \ color_output = renodx::color::grade::UserColorGrading( \ color_output, config.exposure, config.highlights, config.shadows, config.contrast, config.saturation); \ From 3ef21f5b4296396b1c7e3df9ca761c6f626dbb31 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 12 Aug 2024 18:06:58 -0400 Subject: [PATCH 3/5] feat(tonemap): add Reinhard --- src/shaders/tonemap.hlsl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/shaders/tonemap.hlsl b/src/shaders/tonemap.hlsl index f0163c26..9dfc6f7c 100644 --- a/src/shaders/tonemap.hlsl +++ b/src/shaders/tonemap.hlsl @@ -25,6 +25,15 @@ float SmoothClamp(float x) { return (abs(1.0 - x) < u) ? q : saturate(x); } +float3 Reinhard(float3 color) { + return color / (1.0f + color); +} + +float3 ReinhardExtended(float3 color, float max_white = 1000.f / 203.f) { + return (color * (1.0f + (color / (max_white * max_white)))) + / (1.0f + color); +} + // https://www.slideshare.net/ozlael/hable-john-uncharted2-hdr-lighting // http://filmicworlds.com/blog/filmic-tonemapping-operators/ From e148255d6838db93b4368b7b6e0d20d194676e81 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 12 Aug 2024 18:07:33 -0400 Subject: [PATCH 4/5] feat(tunic): add hue correction --- src/games/tunic/addon.cpp | 11 ++++ .../tunic/lutsample2_0xAA66A0B6.ps_4_0.hlsl | 49 ++++++++---------- .../tunic/lutsample_0xEEFE9737.ps_4_0.hlsl | 51 ++++++++----------- src/games/tunic/shared.h | 1 + 4 files changed, 55 insertions(+), 57 deletions(-) diff --git a/src/games/tunic/addon.cpp b/src/games/tunic/addon.cpp index 22a4a0f1..ad76809f 100644 --- a/src/games/tunic/addon.cpp +++ b/src/games/tunic/addon.cpp @@ -84,6 +84,17 @@ renodx::utils::settings::Settings settings = { .min = 48.f, .max = 500.f, }, + new renodx::utils::settings::Setting{ + .key = "toneMapHueCorrection", + .binding = &shader_injection.toneMapHueCorrection, + .default_value = 100.f, + .label = "Hue Correction", + .section = "Tone Mapping", + .tooltip = "Emulates Vanilla hue shifts.", + .min = 0.f, + .max = 100.f, + .parse = [](float value) { return value * 0.01f; }, + }, new renodx::utils::settings::Setting{ .key = "colorGradeExposure", .binding = &shader_injection.colorGradeExposure, diff --git a/src/games/tunic/lutsample2_0xAA66A0B6.ps_4_0.hlsl b/src/games/tunic/lutsample2_0xAA66A0B6.ps_4_0.hlsl index d0216d16..8c668cfe 100644 --- a/src/games/tunic/lutsample2_0xAA66A0B6.ps_4_0.hlsl +++ b/src/games/tunic/lutsample2_0xAA66A0B6.ps_4_0.hlsl @@ -34,33 +34,27 @@ void main(float4 v0 : SV_POSITION0, float4 v1 : TEXCOORD0, float4 v2 : TEXCOORD1 float3 untonemapped = r0.rgb; - float vanillaMidGray = 0.18f; - - float renoDRTContrast = 1.1f; - float renoDRTFlare = 0.f; - float renoDRTShadows = 1.f; - float renoDRTDechroma = injectedData.colorGradeBlowout; - float renoDRTSaturation = 1.05f; - float renoDRTHighlights = 1.f; - - renodx::tonemap::Config config = renodx::tonemap::config::Create( - injectedData.toneMapType, - injectedData.toneMapPeakNits, - injectedData.toneMapGameNits, - 0, - injectedData.colorGradeExposure, - injectedData.colorGradeHighlights, - injectedData.colorGradeShadows, - injectedData.colorGradeContrast, - injectedData.colorGradeSaturation, - vanillaMidGray, - vanillaMidGray * 100.f, - renoDRTHighlights, - renoDRTShadows, - renoDRTContrast, - renoDRTSaturation, - renoDRTDechroma, - renoDRTFlare); + untonemapped = max(0, renodx::color::bt709::from::SRGB(untonemapped)); + + renodx::tonemap::Config config = renodx::tonemap::config::Create(); + + config.type = injectedData.toneMapType; + config.peak_nits = injectedData.toneMapPeakNits; + config.game_nits = injectedData.toneMapGameNits; + config.exposure = injectedData.colorGradeExposure; + config.highlights = injectedData.colorGradeHighlights; + config.shadows = injectedData.colorGradeShadows; + config.contrast = injectedData.colorGradeContrast; + config.saturation = injectedData.colorGradeSaturation; + config.hue_correction_type = renodx::tonemap::config::hue_correction_type::CUSTOM; + config.hue_correction_color = lerp( + untonemapped, + renodx::tonemap::Reinhard(untonemapped), + injectedData.toneMapHueCorrection); + + config.reno_drt_contrast = 1.1f; + config.reno_drt_saturation = 1.05f; + config.reno_drt_dechroma = injectedData.colorGradeBlowout; renodx::lut::Config lut_config = renodx::lut::config::Create( s1_s, @@ -74,7 +68,6 @@ void main(float4 v0 : SV_POSITION0, float4 v1 : TEXCOORD0, float4 v2 : TEXCOORD1 untonemapped = saturate(untonemapped); } - untonemapped = max(0, renodx::color::bt709::from::SRGB(untonemapped)); float3 outputColor = renodx::tonemap::config::Apply(untonemapped, config, lut_config, t1); diff --git a/src/games/tunic/lutsample_0xEEFE9737.ps_4_0.hlsl b/src/games/tunic/lutsample_0xEEFE9737.ps_4_0.hlsl index 297b9a88..3c7a0a49 100644 --- a/src/games/tunic/lutsample_0xEEFE9737.ps_4_0.hlsl +++ b/src/games/tunic/lutsample_0xEEFE9737.ps_4_0.hlsl @@ -28,33 +28,28 @@ void main(float4 v0 : SV_POSITION0, float4 v1 : TEXCOORD0, float4 v2 : TEXCOORD1 r0.xyz = cb0[6].yyy * r0.xyz; // scale float3 untonemapped = r0.rgb; - float vanillaMidGray = 0.18f; - - float renoDRTContrast = 1.1f; - float renoDRTFlare = 0.f; - float renoDRTShadows = 1.f; - float renoDRTDechroma = injectedData.colorGradeBlowout; - float renoDRTSaturation = 1.05f; - float renoDRTHighlights = 1.f; - - renodx::tonemap::Config config = renodx::tonemap::config::Create( - injectedData.toneMapType, - injectedData.toneMapPeakNits, - injectedData.toneMapGameNits, - 0, - injectedData.colorGradeExposure, - injectedData.colorGradeHighlights, - injectedData.colorGradeShadows, - injectedData.colorGradeContrast, - injectedData.colorGradeSaturation, - vanillaMidGray, - vanillaMidGray * 100.f, - renoDRTHighlights, - renoDRTShadows, - renoDRTContrast, - renoDRTSaturation, - renoDRTDechroma, - renoDRTFlare); + untonemapped = max(0, renodx::color::bt709::from::SRGB(untonemapped)); + + renodx::tonemap::Config config = renodx::tonemap::config::Create(); + + config.type = injectedData.toneMapType; + config.peak_nits = injectedData.toneMapPeakNits; + config.game_nits = injectedData.toneMapGameNits; + config.exposure = injectedData.colorGradeExposure; + config.highlights = injectedData.colorGradeHighlights; + config.shadows = injectedData.colorGradeShadows; + config.contrast = injectedData.colorGradeContrast; + config.saturation = injectedData.colorGradeSaturation; + config.hue_correction_type = renodx::tonemap::config::hue_correction_type::CUSTOM; + config.hue_correction_color = lerp( + untonemapped, + renodx::tonemap::Reinhard(untonemapped), + injectedData.toneMapHueCorrection); + + config.reno_drt_contrast = 1.1f; + config.reno_drt_saturation = 1.05f; + config.reno_drt_dechroma = injectedData.colorGradeBlowout; + renodx::lut::Config lut_config = renodx::lut::config::Create( s1_s, injectedData.colorGradeLUTStrength, @@ -67,8 +62,6 @@ void main(float4 v0 : SV_POSITION0, float4 v1 : TEXCOORD0, float4 v2 : TEXCOORD1 untonemapped = saturate(untonemapped); } - untonemapped = max(0, renodx::color::bt709::from::SRGB(untonemapped)); - float3 outputColor = renodx::tonemap::config::Apply(untonemapped, config, lut_config, t1); outputColor = sign(outputColor) * pow(abs(outputColor), 1.f / 2.2f); diff --git a/src/games/tunic/shared.h b/src/games/tunic/shared.h index 2d9dbb3e..c0219394 100644 --- a/src/games/tunic/shared.h +++ b/src/games/tunic/shared.h @@ -12,6 +12,7 @@ struct ShaderInjectData { float toneMapPeakNits; float toneMapGameNits; float toneMapUINits; + float toneMapHueCorrection; float colorGradeExposure; float colorGradeHighlights; float colorGradeShadows; From e2635b276023100b3350e5a0496355a583ea3a76 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 12 Aug 2024 19:02:08 -0400 Subject: [PATCH 5/5] feat(tonemap): add aces fitted sdr --- src/shaders/tonemap.hlsl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/shaders/tonemap.hlsl b/src/shaders/tonemap.hlsl index 9dfc6f7c..63ed0682 100644 --- a/src/shaders/tonemap.hlsl +++ b/src/shaders/tonemap.hlsl @@ -25,6 +25,10 @@ float SmoothClamp(float x) { return (abs(1.0 - x) < u) ? q : saturate(x); } +float3 Reinhard(float x) { + return x / (1.0f + x); +} + float3 Reinhard(float3 color) { return color / (1.0f + color); } @@ -34,6 +38,17 @@ float3 ReinhardExtended(float3 color, float max_white = 1000.f / 203.f) { / (1.0f + color); } +// Narkowicz +float3 ACESFittedSDR(float3 color) { + color *= 0.6f; + const float a = 2.51f; + const float b = 0.03f; + const float c = 2.43f; + const float d = 0.59f; + const float e = 0.14f; + return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0f, 1.0f); +} + // https://www.slideshare.net/ozlael/hable-john-uncharted2-hdr-lighting // http://filmicworlds.com/blog/filmic-tonemapping-operators/