Skip to content

Commit

Permalink
darksouls: add tonemap blending, fix color grade not respecting peak …
Browse files Browse the repository at this point in the history
…by using upgradetonemap(), fix ui blending, remove film grain slider as game already has noise, use new hue correction code
  • Loading branch information
mqhaji authored and clshortfuse committed Aug 14, 2024
1 parent 604c561 commit 97d042a
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 104 deletions.
50 changes: 22 additions & 28 deletions src/games/darksouls/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,25 @@ renodx::utils::settings::Settings settings = {
new renodx::utils::settings::Setting{
.key = "toneMapHueCorrection",
.binding = &shader_injection.toneMapHueCorrection,
.value_type = renodx::utils::settings::SettingValueType::BOOLEAN,
.default_value = 1,
.default_value = 100.f,
.can_reset = false,
.label = "Hue Correction",
.section = "Tone Mapping",
.tooltip = "Emulates hue shifting from the vanilla tonemapper",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType != 0; },
.parse = [](float value) { return value * 0.01f; },
},
new renodx::utils::settings::Setting{
.key = "toneMapBlend",
.binding = &shader_injection.toneMapBlend,
.value_type = renodx::utils::settings::SettingValueType::BOOLEAN,
.default_value = 1,
.can_reset = false,
.label = "Blend with Vanilla",
.section = "Tone Mapping",
.tooltip = "Blends the user selected tonemapper with vanilla",
.is_enabled = []() { return shader_injection.toneMapType != 0; },
},
new renodx::utils::settings::Setting{
.key = "colorGradeExposure",
Expand All @@ -118,6 +131,7 @@ renodx::utils::settings::Settings settings = {
.section = "Color Grading",
.max = 20.f,
.format = "%.2f",
.is_enabled = []() { return shader_injection.toneMapType != 0; },
},
new renodx::utils::settings::Setting{
.key = "colorGradeHighlights",
Expand All @@ -126,6 +140,7 @@ renodx::utils::settings::Settings settings = {
.label = "Highlights",
.section = "Color Grading",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType != 0; },
.parse = [](float value) { return value * 0.02f; },
},
new renodx::utils::settings::Setting{
Expand All @@ -135,6 +150,7 @@ renodx::utils::settings::Settings settings = {
.label = "Shadows",
.section = "Color Grading",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType != 0; },
.parse = [](float value) { return value * 0.02f; },
},
new renodx::utils::settings::Setting{
Expand All @@ -144,6 +160,7 @@ renodx::utils::settings::Settings settings = {
.label = "Contrast",
.section = "Color Grading",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType != 0; },
.parse = [](float value) { return value * 0.02f; },
},
new renodx::utils::settings::Setting{
Expand All @@ -153,16 +170,18 @@ renodx::utils::settings::Settings settings = {
.label = "Saturation",
.section = "Color Grading",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType != 0; },
.parse = [](float value) { return value * 0.02f; },
},
new renodx::utils::settings::Setting{
.key = "colorGradeBlowout",
.binding = &shader_injection.colorGradeBlowout,
.default_value = 70.f,
.default_value = 65.f,
.label = "Blowout",
.section = "Color Grading",
.tooltip = "Controls highlight desaturation due to overexposure.",
.max = 100.f,
.is_enabled = []() { return shader_injection.toneMapType == 3; },
.parse = [](float value) { return value * 0.01f; },
},
new renodx::utils::settings::Setting{
Expand Down Expand Up @@ -192,15 +211,6 @@ renodx::utils::settings::Settings settings = {
.max = 100.f,
.parse = [](float value) { return value * 0.02f; },
},
new renodx::utils::settings::Setting{
.key = "fxFilmGrain",
.binding = &shader_injection.fxFilmGrain,
.default_value = 0.f,
.label = "Film Grain",
.section = "Effects",
.max = 100.f,
.parse = [](float value) { return value * 0.02f; },
},
};

void OnPresetOff() {
Expand All @@ -222,19 +232,6 @@ void OnPresetOff() {
renodx::utils::settings::UpdateSetting("fxFilmGrain", 0.f);
}

auto start = std::chrono::steady_clock::now();

void OnPresent(
reshade::api::command_queue* queue,
reshade::api::swapchain* swapchain,
const reshade::api::rect* source_rect,
const reshade::api::rect* dest_rect,
uint32_t dirty_rect_count,
const reshade::api::rect* dirty_rects) {
auto end = std::chrono::steady_clock::now();
shader_injection.elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}

} // namespace

// NOLINTBEGIN(readability-identifier-naming)
Expand Down Expand Up @@ -274,12 +271,9 @@ BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {

if (!reshade::register_addon(h_module)) return FALSE;

reshade::register_event<reshade::addon_event::present>(OnPresent);

break;
case DLL_PROCESS_DETACH:
reshade::unregister_addon(h_module);
reshade::unregister_event<reshade::addon_event::present>(OnPresent);
break;
}

Expand Down
11 changes: 11 additions & 0 deletions src/games/darksouls/gamma_0xAB7CF260.ps_5_0.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ void main(float4 v0
o0.w = 1;
o0.xyz = g_Texture.Sample(g_TextureSampler_s, v1.xy).xyz;

// linearize and scale paper white
float3 signs = sign(o0.rgb);
o0.rgb = abs(o0.rgb);
o0.rgb = (injectedData.toneMapGammaCorrection
? pow(o0.rgb, 2.2f)
: renodx::color::bt709::from::SRGB(o0.rgb));
o0.rgb *= signs;
o0.rgb *= injectedData.toneMapGameNits / 80.f;



// Removed gamma slider as it capped brightness
// Image is unchanged when set to default 5

Expand Down
3 changes: 1 addition & 2 deletions src/games/darksouls/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct ShaderInjectData {
float toneMapUINits;
float toneMapGammaCorrection;
float toneMapHueCorrection;
float toneMapBlend;
float colorGradeExposure;
float colorGradeHighlights;
float colorGradeShadows;
Expand All @@ -23,8 +24,6 @@ struct ShaderInjectData {
float colorGradeLUTStrength;
float fxBloom;
float fxDoF;
float fxFilmGrain;
float elapsedTime;
};

#ifndef __cplusplus
Expand Down
149 changes: 89 additions & 60 deletions src/games/darksouls/tonemap_0xF87B3349.ps_5_0.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ void main(float4 v0

// Initial tonemapper settings, used in case 0
float vanillaMidGray = DL_FREG_054.z / DL_FREG_054.w;
float renoDRTContrast = 1.16f;
float renoDRTContrast = 1.2f;
float renoDRTFlare = 0.f;
float renoDRTShadows = 1.f;
float renoDRTDechroma = injectedData.colorGradeBlowout;
float renoDRTSaturation = 1.3f;
float renoDRTHighlights = 1.04f;
float renoDRTHighlights = 1.f;
float3 vanillaColor;

r0.xyz = gSMP_0.Sample(gSMP_0Sampler_s, v1.xy).xyz;
r1.xyzw = gSMP_1.Sample(gSMP_1Sampler_s, v1.xy).wxyz;
Expand All @@ -119,15 +119,16 @@ void main(float4 v0

float3 untonemapped = r0.xyz;

// switch case with multiple tonemappers, not sure when alternative tonemappers enable
switch (r0.w) {
case 0: // Vanilla tonemapper 0
r0.w = gSMP_5.Sample(gSMP_5Sampler_s, float2(0.5, 0.5)).x;
r0.w = max(DL_FREG_056.z, r0.w);
r0.w = min(DL_FREG_056.w, r0.w);
r0.w = 9.99999975e-005 + r0.w;
r0.w = DL_FREG_054.x / r0.w;
r2.xyz = r0.xyz * r0.www;
if (injectedData.toneMapType != 0) { // Custom tonemappers
r2.xyz = r0.xyz * r0.www; // exposure adjustment
if (injectedData.toneMapType != 0) { // untonemapped
untonemapped = r2.xyz;
}
r0.w = DL_FREG_055.z * DL_FREG_055.y; // Start of tonemap 0
Expand All @@ -154,13 +155,12 @@ void main(float4 v0
r0.w = min(DL_FREG_056.w, r0.w);
r0.w = 9.99999975e-005 + r0.w;
r0.w = DL_FREG_054.x / r0.w;
r2.xyz = r0.xyz * r0.www;
if (injectedData.toneMapType != 0) { // Custom tonemappers
r2.xyz = r0.xyz * r0.www; // exposure adjustment
if (injectedData.toneMapType != 0) { // RenoDRT parameters + untonemapped
vanillaMidGray = .15f;
renoDRTContrast = 0.92f;
renoDRTFlare = 0.f;
renoDRTShadows = 1.f;
// renoDRTDechroma = 0.7f;
renoDRTSaturation = 1.3f;
renoDRTHighlights = 1.f;
untonemapped = r2.xyz;
Expand All @@ -180,13 +180,12 @@ void main(float4 v0
r0.w = min(DL_FREG_056.w, r0.w);
r0.w = 9.99999975e-005 + r0.w;
r0.w = DL_FREG_054.x / r0.w;
r0.xyz = r0.xyz * r0.www;
if (injectedData.toneMapType != 0) { // Custom tonemappers
r0.xyz = r0.xyz * r0.www; // exposure adjustment
if (injectedData.toneMapType != 0) { // RenoDRT parameters + untonemapped
vanillaMidGray = .151f;
renoDRTContrast = 0.94f;
renoDRTFlare = 0.f;
renoDRTShadows = 1.f;
// renoDRTDechroma = 0.7f;
renoDRTSaturation = 1.3f;
renoDRTHighlights = 1.f;
untonemapped = r0.xyz;
Expand All @@ -209,40 +208,84 @@ void main(float4 v0
break;
}

float3 hdrColor;
float3 sdrColor;
if (injectedData.toneMapType != 0) {
float3 tonemapped = renodx::tonemap::config::Apply(
untonemapped,
renodx::tonemap::config::Create(
injectedData.toneMapType,
injectedData.toneMapPeakNits,
injectedData.toneMapGameNits,
injectedData.toneMapGammaCorrection,
injectedData.colorGradeExposure,
injectedData.colorGradeHighlights,
injectedData.colorGradeShadows,
injectedData.colorGradeContrast,
injectedData.colorGradeSaturation,
vanillaMidGray,
vanillaMidGray * 100.f,
renoDRTHighlights,
renoDRTShadows,
renoDRTContrast,
renoDRTSaturation,
renoDRTDechroma,
renoDRTFlare));

if (injectedData.toneMapHueCorrection) {
r1.xyz = renodx::color::correct::Hue(tonemapped, r1.xyz);
} else {
r1.xyz = tonemapped;
vanillaColor = r1.xyz; // vanilla tonemap, used for hue correction

renodx::tonemap::Config hdrConfig = renodx::tonemap::config::Create();
hdrConfig.type = injectedData.toneMapType;
hdrConfig.peak_nits = injectedData.toneMapPeakNits;
hdrConfig.game_nits = injectedData.toneMapGameNits;
hdrConfig.gamma_correction = injectedData.toneMapGammaCorrection - 1;
hdrConfig.exposure = injectedData.colorGradeExposure;
hdrConfig.highlights = injectedData.colorGradeHighlights;
hdrConfig.shadows = injectedData.colorGradeShadows;
hdrConfig.contrast = injectedData.colorGradeContrast;
hdrConfig.saturation = injectedData.colorGradeSaturation;
hdrConfig.hue_correction_type = renodx::tonemap::config::hue_correction_type::CUSTOM;
hdrConfig.hue_correction_color = vanillaColor,
hdrConfig.hue_correction_strength = injectedData.toneMapHueCorrection;
hdrConfig.reno_drt_highlights = renoDRTHighlights;
hdrConfig.reno_drt_shadows = renoDRTShadows;
hdrConfig.reno_drt_contrast = renoDRTContrast;
hdrConfig.reno_drt_saturation = renoDRTSaturation;
hdrConfig.reno_drt_dechroma = injectedData.colorGradeBlowout;
hdrConfig.mid_gray_value = vanillaMidGray;
hdrConfig.mid_gray_nits = vanillaMidGray * 100.f;
hdrConfig.reno_drt_flare = renoDRTFlare;

// don't allow for double adjustment of color grading when blending is on
if (injectedData.toneMapBlend) {
hdrConfig.exposure = 1.f;
hdrConfig.shadows = 1.f;
hdrConfig.contrast = 1.f;
hdrConfig.saturation = 1.f;
}
} else { // Clamp vanilla tonemapper to BT709
r0.xyz = max(0, r1.xyz);

renodx::tonemap::Config sdrConfig = hdrConfig;
sdrConfig.peak_nits = injectedData.toneMapGameNits;

hdrColor = renodx::tonemap::config::Apply(untonemapped, hdrConfig);
sdrColor = renodx::tonemap::config::Apply(untonemapped, sdrConfig);

// blend custom tonemapper with vanilla by channel
if (injectedData.toneMapBlend) {
float3 negHDR = min(0, hdrColor);
sdrColor = lerp(saturate(vanillaColor), max(0, sdrColor), saturate(vanillaColor));
hdrColor += negHDR;

negHDR = min(0, hdrColor);
hdrColor = lerp(saturate(vanillaColor), max(0, hdrColor), saturate(vanillaColor));
hdrColor += negHDR;

// apply color grading post-blend
sdrColor = renodx::color::grade::UserColorGrading(
sdrColor,
injectedData.colorGradeExposure,
1.f,
injectedData.colorGradeShadows,
injectedData.colorGradeContrast,
injectedData.colorGradeSaturation);
hdrColor = renodx::color::grade::UserColorGrading(
hdrColor,
injectedData.colorGradeExposure,
1.f,
injectedData.colorGradeShadows,
injectedData.colorGradeContrast,
injectedData.colorGradeSaturation);

}
r1.xyz = sdrColor;

sdrColor = sign(sdrColor) * pow(abs(sdrColor), 1.f / 2.2f);
hdrColor = sign(hdrColor) * pow(abs(hdrColor), 1.f / 2.2f);
}

r0.xyz = sign(r1.xyz) * pow(abs(r1.xyz), 1.f / 2.2f); // Linearize before color grade
r0.xyz = sign(r1.xyz) * pow(abs(r1.xyz), 1.f / 2.2f); // color grade in gamma space

const float3 preLUT = r0.xyz;
const float3 colorGradeInput = r0.xyz;

r0.w = 1;
r1.x = dot(r0.xyzw, DL_FREG_062._m00_m10_m20_m30);
Expand All @@ -261,31 +304,17 @@ void main(float4 v0
r0.xyz = r2.xyz * r0.xyz;
r0.xyz = r3.xyz * r4.xyz + r0.xyz;
r0.xyz = r0.xyz + -r1.xyz;
// r0.xyz = DL_FREG_068.xxx * r0.xyz + r1.xyz;
// DL_FREG_068.xxx = noise
r0.xyz =
lerp(preLUT + DL_FREG_068.xxx * r0.xyz, DL_FREG_068.xxx * r0.xyz + r1.xyz,
injectedData.colorGradeLUTStrength);

if (injectedData.fxFilmGrain) {
float3 grainedColor = renodx::effects::ApplyFilmGrain(
r0.rgb, v1.xy, frac(injectedData.elapsedTime / 1000.f),
injectedData.fxFilmGrain * 0.03f, 1.f);
r0.xyz = grainedColor;
}
r0.xyz = DL_FREG_068.xxx * r0.xyz + r1.xyz;

if (injectedData.toneMapType == 0) { // Cap vanilla tonemapper
if (injectedData.toneMapType == 0) {
r0.xyz = lerp(colorGradeInput, r0.xyz, injectedData.colorGradeLUTStrength);
r0.xyz = clamp(r0.xyz, 0, injectedData.toneMapPeakNits / injectedData.toneMapGameNits);
} else {
// apply color grade to SDR tonemapped image and apply difference to HDR
// color filter will now respect peak brightness
r0.xyz = renodx::tonemap::UpgradeToneMap(hdrColor, sdrColor, r0.xyz, injectedData.colorGradeLUTStrength);
}

r0.rgb = injectedData.toneMapGammaCorrection
? sign(r0.rgb) * pow(abs(r0.rgb), 2.2f)
: renodx::color::bt709::from::SRGB(r0.rgb);

r0.rgb *= injectedData.toneMapGameNits / 80.f;

r0.rgb = renodx::color::bt709::clamp::BT2020(r0.rgb);

o0.w = dot(r0.xyz, float3(0.298999995, 0.587000012, 0.114));
o0.xyz = r0.xyz;
return;
Expand Down
Loading

0 comments on commit 97d042a

Please sign in to comment.