diff --git a/bin/resources/shaders/dx11/shadeboost.fx b/bin/resources/shaders/dx11/shadeboost.fx index e9911d203d..c39b45e7d6 100644 --- a/bin/resources/shaders/dx11/shadeboost.fx +++ b/bin/resources/shaders/dx11/shadeboost.fx @@ -21,6 +21,7 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL float brt = params.x; float con = params.y; float sat = params.z; + float gam = params.w; // Increase or decrease these values to adjust r, g and b color channels separately const float AvgLumR = 0.5; @@ -34,8 +35,10 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL float3 intensity = dot(brtColor, LumCoeff); float3 satColor = lerp(intensity, brtColor, sat); float3 conColor = lerp(AvgLumin, satColor, con); - - color.rgb = conColor; + + float3 csb = conColor; + csb = pow(csb, 1.0 / gam); + color.rgb = csb; return color; } diff --git a/bin/resources/shaders/opengl/shadeboost.glsl b/bin/resources/shaders/opengl/shadeboost.glsl index 19abb3cbe5..4d5cc16bc4 100644 --- a/bin/resources/shaders/opengl/shadeboost.glsl +++ b/bin/resources/shaders/opengl/shadeboost.glsl @@ -30,6 +30,7 @@ vec4 ContrastSaturationBrightness(vec4 color) float brt = params.x; float con = params.y; float sat = params.z; + float gam = params.w; // Increase or decrease these values to adjust r, g and b color channels separately const float AvgLumR = 0.5; @@ -45,7 +46,10 @@ vec4 ContrastSaturationBrightness(vec4 color) vec3 satColor = mix(intensity, brtColor, sat); vec3 conColor = mix(AvgLumin, satColor, con); - color.rgb = conColor; + vec3 csb = conColor; + csb = pow(csb, vec3(1.0 / gam)); + color.rgb = csb; + return color; } diff --git a/bin/resources/shaders/vulkan/shadeboost.glsl b/bin/resources/shaders/vulkan/shadeboost.glsl index b604fdcd8d..c8c61ecf02 100644 --- a/bin/resources/shaders/vulkan/shadeboost.glsl +++ b/bin/resources/shaders/vulkan/shadeboost.glsl @@ -44,6 +44,7 @@ vec4 ContrastSaturationBrightness(vec4 color) float brt = params.x; float con = params.y; float sat = params.z; + float gam = params.w; // Increase or decrease these values to adjust r, g and b color channels separately const float AvgLumR = 0.5; @@ -59,7 +60,9 @@ vec4 ContrastSaturationBrightness(vec4 color) vec3 satColor = mix(intensity, brtColor, sat); vec3 conColor = mix(AvgLumin, satColor, con); - color.rgb = conColor; + vec3 csb = conColor; + csb = pow(csb, vec3(1.0 / gam)); + color.rgb = csb; return color; } diff --git a/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp b/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp index 7f98eccb7b..a95e1e34f4 100644 --- a/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp +++ b/pcsx2-qt/Settings/GraphicsSettingsWidget.cpp @@ -135,6 +135,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.shadeBoost, "EmuCore/GS", "ShadeBoost", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostBrightness, "EmuCore/GS", "ShadeBoost_Brightness", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostContrast, "EmuCore/GS", "ShadeBoost_Contrast", false); + SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostGamma, "EmuCore/GS", "ShadeBoost_Gamma", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostSaturation, "EmuCore/GS", "ShadeBoost_Saturation", false); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.tvShader, "EmuCore/GS", "TVShader", DEFAULT_TV_SHADER_MODE); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.casMode, "EmuCore/GS", "CASMode", static_cast(GSCASMode::Disabled)); @@ -727,6 +728,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* dialog->registerWidgetHelp(m_ui.shadeBoostContrast, tr("Contrast"), tr("50"), tr("Adjusts contrast. 50 is normal.")); + dialog->registerWidgetHelp(m_ui.shadeBoostGamma, tr("Gamma"), tr("50"), tr("Adjusts gamma. 50 is normal.")); + dialog->registerWidgetHelp(m_ui.shadeBoostSaturation, tr("Saturation"), tr("50"), tr("Adjusts saturation. 50 is normal.")); dialog->registerWidgetHelp(m_ui.tvShader, tr("TV Shader"), tr("None (Default)"), @@ -944,6 +947,7 @@ void GraphicsSettingsWidget::onShadeBoostChanged() const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "ShadeBoost", false); m_ui.shadeBoostBrightness->setEnabled(enabled); m_ui.shadeBoostContrast->setEnabled(enabled); + m_ui.shadeBoostGamma->setEnabled(enabled); m_ui.shadeBoostSaturation->setEnabled(enabled); } diff --git a/pcsx2-qt/Settings/GraphicsSettingsWidget.ui b/pcsx2-qt/Settings/GraphicsSettingsWidget.ui index a0b3eae032..cca1473f8b 100644 --- a/pcsx2-qt/Settings/GraphicsSettingsWidget.ui +++ b/pcsx2-qt/Settings/GraphicsSettingsWidget.ui @@ -1433,6 +1433,23 @@ + + + + Gamma: + + + + + + + 1 + + + 100 + + + diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 1e939ce31a..d6a8549988 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -840,6 +840,7 @@ struct Pcsx2Config u8 ShadeBoost_Brightness = 50; u8 ShadeBoost_Contrast = 50; u8 ShadeBoost_Saturation = 50; + u8 ShadeBoost_Gamma = 50; u8 PNGCompressionLevel = 1; u16 SWExtraThreads = 2; diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index fdcfd05389..ccc6891917 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -835,6 +835,7 @@ void GSDevice::ShadeBoost() static_cast(GSConfig.ShadeBoost_Brightness) * (1.0f / 50.0f), static_cast(GSConfig.ShadeBoost_Contrast) * (1.0f / 50.0f), static_cast(GSConfig.ShadeBoost_Saturation) * (1.0f / 50.0f), + static_cast(GSConfig.ShadeBoost_Gamma) * (1.0f / 50.0f), }; DoShadeBoost(m_current, m_target_tmp, params); diff --git a/pcsx2/GS/Renderers/Metal/convert.metal b/pcsx2/GS/Renderers/Metal/convert.metal index 9e6f3a7826..eaed4d1970 100644 --- a/pcsx2/GS/Renderers/Metal/convert.metal +++ b/pcsx2/GS/Renderers/Metal/convert.metal @@ -527,11 +527,12 @@ fragment half4 ps_imgui(ImGuiShaderData data [[stage_in]], texture2d textu return data.c * texture.sample(s, data.t); } -fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn tex, constant float3& cb [[buffer(GSMTLBufferIndexUniforms)]]) +fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn tex, constant float4& cb [[buffer(GSMTLBufferIndexUniforms)]]) { const float brt = cb.x; const float con = cb.y; const float sat = cb.z; + const float gam = cb.w; // Increase or decrease these values to adjust r, g and b color channels separately const float AvgLumR = 0.5; const float AvgLumG = 0.5; @@ -546,5 +547,7 @@ fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn float3 satColor = mix(intensity, brtColor, sat); float3 conColor = mix(AvgLumin, satColor, con); - return float4(conColor, 1); + float3 csb = pow(conColor, float3(1.0 / gam)); + + return float4(csb, 1); } diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 1d857020e7..dec3cdbde6 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -4403,12 +4403,14 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad { const bool shadeboost_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "ShadeBoost", false); - DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GEM, "Shade Boost"), FSUI_CSTR("Enables brightness/contrast/saturation adjustment."), "EmuCore/GS", + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GEM, "Shade Boost"), FSUI_CSTR("Enables brightness/contrast/gamma/saturation adjustment."), "EmuCore/GS", "ShadeBoost", false); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_SUN, "Shade Boost Brightness"), FSUI_CSTR("Adjusts brightness. 50 is normal."), "EmuCore/GS", "ShadeBoost_Brightness", 50, 1, 100, "%d", shadeboost_active); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Shade Boost Contrast"), FSUI_CSTR("Adjusts contrast. 50 is normal."), "EmuCore/GS", "ShadeBoost_Contrast", 50, 1, 100, "%d", shadeboost_active); + DrawIntRangeSetting(bsi, FSUI_CSTR("Shade Boost Gamma"), FSUI_CSTR("Adjusts gamma. 50 is normal."), "EmuCore/GS", + "ShadeBoost_Gamma", 50, 1, 100, "%d", shadeboost_active); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_DROPLET, "Shade Boost Saturation"), FSUI_CSTR("Adjusts saturation. 50 is normal."), "EmuCore/GS", "ShadeBoost_Saturation", 50, 1, 100, "%d", shadeboost_active); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index 296c62da25..f10c22ba8e 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -850,6 +850,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const OpEqu(ShadeBoost_Brightness) && OpEqu(ShadeBoost_Contrast) && OpEqu(ShadeBoost_Saturation) && + OpEqu(ShadeBoost_Gamma) && OpEqu(PNGCompressionLevel) && OpEqu(SaveDrawStart) && OpEqu(SaveDrawCount) && @@ -1042,6 +1043,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap) SettingsWrapBitfield(ShadeBoost_Brightness); SettingsWrapBitfield(ShadeBoost_Contrast); SettingsWrapBitfield(ShadeBoost_Saturation); + SettingsWrapBitfield(ShadeBoost_Gamma); SettingsWrapBitfield(ExclusiveFullscreenControl); SettingsWrapBitfieldEx(PNGCompressionLevel, "png_compression_level"); SettingsWrapBitfieldEx(SaveDrawStart, "SaveDrawStart"); diff --git a/pcsx2/ShaderCacheVersion.h b/pcsx2/ShaderCacheVersion.h index 479925478b..d4502b8811 100644 --- a/pcsx2/ShaderCacheVersion.h +++ b/pcsx2/ShaderCacheVersion.h @@ -3,4 +3,4 @@ /// Version number for GS and other shaders. Increment whenever any of the contents of the /// shaders change, to invalidate the cache. -static constexpr u32 SHADER_CACHE_VERSION = 69; +static constexpr u32 SHADER_CACHE_VERSION = 70;