From daddf4cd9cf7c45820f5cadd1539c6a6b366cfbc Mon Sep 17 00:00:00 2001 From: Filoppi Date: Sat, 10 Jun 2023 11:48:40 +0300 Subject: [PATCH] Qt: add color correction and HDR Qt settings widgets --- Source/Core/DolphinQt/CMakeLists.txt | 2 + .../Graphics/ColorCorrectionConfigWindow.cpp | 181 ++++++++++++++++++ .../Graphics/ColorCorrectionConfigWindow.h | 36 ++++ .../Config/Graphics/EnhancementsWidget.cpp | 36 ++++ .../Config/Graphics/EnhancementsWidget.h | 3 + Source/Core/DolphinQt/DolphinQt.vcxproj | 2 + 6 files changed, 260 insertions(+) create mode 100644 Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp create mode 100644 Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 3c2c848d33..e302287677 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -87,6 +87,8 @@ add_executable(dolphin-emu Config/Graphics/GraphicsWindow.h Config/Graphics/HacksWidget.cpp Config/Graphics/HacksWidget.h + Config/Graphics/ColorCorrectionConfigWindow.cpp + Config/Graphics/ColorCorrectionConfigWindow.h Config/Graphics/PostProcessingConfigWindow.cpp Config/Graphics/PostProcessingConfigWindow.h Config/GraphicsModListWidget.cpp diff --git a/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp new file mode 100644 index 0000000000..5946b9210e --- /dev/null +++ b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp @@ -0,0 +1,181 @@ +// Copyright 2018 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h" + +#include +#include +#include +#include +#include + +#include "Core/Config/GraphicsSettings.h" + +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigChoice.h" +#include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h" + +#include "VideoCommon/VideoConfig.h" + +ColorCorrectionConfigWindow::ColorCorrectionConfigWindow(QWidget* parent) : QDialog(parent) +{ + setWindowTitle(tr("Color Correction Configuration")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + Create(); + ConnectWidgets(); +} + +void ColorCorrectionConfigWindow::Create() +{ + static const char TR_COLOR_SPACE_CORRECTION_DESCRIPTION[] = QT_TR_NOOP( + "Converts the colors to the color spaces that GC/Wii were meant to work with to sRGB/Rec.709." + "

There's no way of knowing what exact color space games were meant for," + "
given there were multiple standards and most games didn't acknowledge them," + "
so it's not correct to assume a format from the game disc region." + "
Just pick the one that looks more natural to you," + " or match it with the region the game was developed in." + "

HDR output is required to show all the colors from the PAL and NTSC-J color spaces." + "

If unsure, leave this unchecked."); + static const char TR_GAME_GAMMA_DESCRIPTION[] = + QT_TR_NOOP("NTSC-M and NTSC-J target gamma ~2.2. PAL targets gamma ~2.8." + "
None of the two were necessarily followed by games or TVs. 2.35 is a good " + "generic value for all regions." + "
If a game allows you to chose a gamma value, match it here."); + static const char TR_GAMMA_CORRECTION_DESCRIPTION[] = QT_TR_NOOP( + "Converts the gamma from what the game targeted to what your current SDR display targets." + "
Monitors often target sRGB. TVs often target 2.2." + "

If unsure, leave this unchecked."); + + // Color Space: + + auto* const color_space_box = new QGroupBox(tr("Color Space")); + auto* const color_space_layout = new QGridLayout(); + color_space_layout->setVerticalSpacing(7); + color_space_layout->setColumnStretch(1, 1); + color_space_box->setLayout(color_space_layout); + + m_correct_color_space = + new ConfigBool(tr("Correct Color Space"), Config::GFX_CC_CORRECT_COLOR_SPACE); + color_space_layout->addWidget(m_correct_color_space, 0, 0); + m_correct_color_space->SetDescription(tr(TR_COLOR_SPACE_CORRECTION_DESCRIPTION)); + + // "ColorCorrectionRegion" + const QStringList game_color_space_enum{tr("NTSC-M (SMPTE 170M)"), tr("NTSC-J (ARIB TR-B9)"), + tr("PAL (EBU)")}; + + m_game_color_space = new ConfigChoice(game_color_space_enum, Config::GFX_CC_GAME_COLOR_SPACE); + color_space_layout->addWidget(new QLabel(tr("Game Color Space")), 1, 0); + color_space_layout->addWidget(m_game_color_space, 1, 1); + + m_game_color_space->setEnabled(m_correct_color_space->isChecked()); + + // Gamma: + + auto* const gamma_box = new QGroupBox(tr("Gamma")); + auto* const gamma_layout = new QGridLayout(); + gamma_layout->setVerticalSpacing(7); + gamma_layout->setColumnStretch(1, 1); + gamma_box->setLayout(gamma_layout); + + m_game_gamma = new ConfigFloatSlider(Config::GFX_CC_GAME_GAMMA_MIN, Config::GFX_CC_GAME_GAMMA_MAX, + Config::GFX_CC_GAME_GAMMA, 0.01f); + gamma_layout->addWidget(new QLabel(tr("Game Gamma")), 0, 0); + gamma_layout->addWidget(m_game_gamma, 0, 1); + m_game_gamma->SetDescription(tr(TR_GAME_GAMMA_DESCRIPTION)); + m_game_gamma_value = new QLabel(tr("")); + gamma_layout->addWidget(m_game_gamma_value, 0, 2); + + m_correct_gamma = new ConfigBool(tr("Correct SDR Gamma"), Config::GFX_CC_CORRECT_GAMMA); + gamma_layout->addWidget(m_correct_gamma, 1, 0); + m_correct_gamma->SetDescription(tr(TR_GAMMA_CORRECTION_DESCRIPTION)); + + m_sdr_display_gamma_srgb = + new ConfigBool(tr("SDR Display Gamma sRGB"), Config::GFX_CC_SDR_DISPLAY_GAMMA_SRGB); + gamma_layout->addWidget(m_sdr_display_gamma_srgb, 2, 0); + + m_sdr_display_custom_gamma = + new ConfigFloatSlider(Config::GFX_CC_DISPLAY_GAMMA_MIN, Config::GFX_CC_DISPLAY_GAMMA_MAX, + Config::GFX_CC_SDR_DISPLAY_CUSTOM_GAMMA, 0.01f); + gamma_layout->addWidget(new QLabel(tr("SDR Display Custom Gamma")), 3, 0); + gamma_layout->addWidget(m_sdr_display_custom_gamma, 3, 1); + m_sdr_display_custom_gamma_value = new QLabel(tr("")); + gamma_layout->addWidget(m_sdr_display_custom_gamma_value, 3, 2); + + m_sdr_display_gamma_srgb->setEnabled(m_correct_gamma->isChecked()); + m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() && + !m_sdr_display_gamma_srgb->isChecked()); + m_game_gamma_value->setText(QString::asprintf("%f", m_game_gamma->GetValue())); + m_sdr_display_custom_gamma_value->setText( + QString::asprintf("%f", m_sdr_display_custom_gamma->GetValue())); + + // HDR: + + auto* const hdr_box = new QGroupBox(tr("HDR")); + auto* const hdr_layout = new QGridLayout(); + hdr_layout->setVerticalSpacing(7); + hdr_layout->setColumnStretch(1, 1); + hdr_box->setLayout(hdr_layout); + + m_hdr_paper_white_nits = new ConfigFloatSlider(Config::GFX_CC_HDR_PAPER_WHITE_NITS_MIN, + Config::GFX_CC_HDR_PAPER_WHITE_NITS_MAX, + Config::GFX_CC_HDR_PAPER_WHITE_NITS, 1.f); + hdr_layout->addWidget(new QLabel(tr("HDR Paper White Nits")), 0, 0); + hdr_layout->addWidget(m_hdr_paper_white_nits, 0, 1); + m_hdr_paper_white_nits_value = new QLabel(tr("")); + hdr_layout->addWidget(m_hdr_paper_white_nits_value, 0, 2); + + m_hdr_paper_white_nits_value->setText( + QString::asprintf("%f", m_hdr_paper_white_nits->GetValue())); + + // Other: + + m_button_box = new QDialogButtonBox(QDialogButtonBox::Close); + + auto* layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignTop); + layout->addWidget(color_space_box); + layout->addWidget(gamma_box); + layout->addWidget(hdr_box); + layout->addWidget(m_button_box); + setLayout(layout); +} + +void ColorCorrectionConfigWindow::ConnectWidgets() +{ + connect(m_correct_color_space, &QCheckBox::toggled, this, + [this] { m_game_color_space->setEnabled(m_correct_color_space->isChecked()); }); + + connect(m_game_gamma, &ConfigFloatSlider::valueChanged, this, [this] { + m_game_gamma_value->setText(QString::asprintf("%f", m_game_gamma->GetValue())); + }); + + connect(m_correct_gamma, &QCheckBox::toggled, this, [this] { + // The "m_game_gamma" shouldn't be grayed out as it can still affect the color space correction + + // For the moment we leave this enabled even when we are outputting in HDR + // (which means they'd have no influence on the final image), + // mostly because we don't have a simple way to determine if HDR is engaged from here + m_sdr_display_gamma_srgb->setEnabled(m_correct_gamma->isChecked()); + m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() && + !m_sdr_display_gamma_srgb->isChecked()); + }); + + connect(m_sdr_display_gamma_srgb, &QCheckBox::toggled, this, [this] { + m_sdr_display_custom_gamma->setEnabled(m_correct_gamma->isChecked() && + !m_sdr_display_gamma_srgb->isChecked()); + }); + + connect(m_sdr_display_custom_gamma, &ConfigFloatSlider::valueChanged, this, [this] { + m_sdr_display_custom_gamma_value->setText( + QString::asprintf("%f", m_sdr_display_custom_gamma->GetValue())); + }); + + connect(m_hdr_paper_white_nits, &ConfigFloatSlider::valueChanged, this, [this] { + m_hdr_paper_white_nits_value->setText( + QString::asprintf("%f", m_hdr_paper_white_nits->GetValue())); + }); + + connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); +} diff --git a/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h new file mode 100644 index 0000000000..bcc27ce1c8 --- /dev/null +++ b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h @@ -0,0 +1,36 @@ +// Copyright 2018 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +class QWidget; +class QLabel; +class ConfigBool; +class ConfigChoice; +class ConfigFloatSlider; +class QDialogButtonBox; + +class ColorCorrectionConfigWindow final : public QDialog +{ + Q_OBJECT +public: + explicit ColorCorrectionConfigWindow(QWidget* parent); + +private: + void Create(); + void ConnectWidgets(); + + ConfigBool* m_correct_color_space; + ConfigChoice* m_game_color_space; + ConfigFloatSlider* m_game_gamma; + QLabel* m_game_gamma_value; + ConfigBool* m_correct_gamma; + ConfigBool* m_sdr_display_gamma_srgb; + ConfigFloatSlider* m_sdr_display_custom_gamma; + QLabel* m_sdr_display_custom_gamma_value; + ConfigFloatSlider* m_hdr_paper_white_nits; + QLabel* m_hdr_paper_white_nits_value; + QDialogButtonBox* m_button_box; +}; diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index c5889d2ad4..c1c0495929 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -18,6 +18,7 @@ #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigRadio.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" @@ -102,6 +103,8 @@ void EnhancementsWidget::CreateWidgets() m_texture_filtering_combo->addItem(tr("Force Linear and 16x Anisotropic"), TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X); + m_configure_color_correction = new NonDefaultQPushButton(tr("Configure")); + m_pp_effect = new ToolTipComboBox(); m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure")); m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED); @@ -116,6 +119,7 @@ void EnhancementsWidget::CreateWidgets() new ConfigBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER); m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"), Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION); + m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT); int row = 0; enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), row, 0); @@ -130,6 +134,10 @@ void EnhancementsWidget::CreateWidgets() enhancements_layout->addWidget(m_texture_filtering_combo, row, 1, 1, -1); ++row; + enhancements_layout->addWidget(new QLabel(tr("Color Correction:")), row, 0); + enhancements_layout->addWidget(m_configure_color_correction, row, 1, 1, -1); + ++row; + enhancements_layout->addWidget(new QLabel(tr("Post-Processing Effect:")), row, 0); enhancements_layout->addWidget(m_pp_effect, row, 1); enhancements_layout->addWidget(m_configure_pp_effect, row, 2); @@ -148,6 +156,7 @@ void EnhancementsWidget::CreateWidgets() ++row; enhancements_layout->addWidget(m_disable_copy_filter, row, 0); + enhancements_layout->addWidget(m_hdr, row, 1, 1, -1); ++row; // Stereoscopy @@ -188,11 +197,14 @@ void EnhancementsWidget::ConnectWidgets() [this](int) { SaveSettings(); }); connect(m_3d_mode, qOverload(&QComboBox::currentIndexChanged), [this] { m_block_save = true; + m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); LoadPPShaders(); m_block_save = false; SaveSettings(); }); + connect(m_configure_color_correction, &QPushButton::clicked, this, + &EnhancementsWidget::ConfigureColorCorrection); connect(m_configure_pp_effect, &QPushButton::clicked, this, &EnhancementsWidget::ConfigurePostProcessingShader); } @@ -311,6 +323,8 @@ void EnhancementsWidget::LoadSettings() break; } + m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); + // Post Processing Shader LoadPPShaders(); @@ -320,6 +334,9 @@ void EnhancementsWidget::LoadSettings() m_3d_convergence->setEnabled(supports_stereoscopy); m_3d_depth->setEnabled(supports_stereoscopy); m_3d_swap_eyes->setEnabled(supports_stereoscopy); + + m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput); + m_block_save = false; } @@ -436,6 +453,9 @@ void EnhancementsWidget::AddDescriptions() "scaling filter selected by the game.

Any option except 'Default' will alter the look " "of the game's textures and might cause issues in a small number of " "games.

If unsure, select 'Default'."); + static const char TR_COLOR_CORRECTION_DESCRIPTION[] = + QT_TR_NOOP("A group of features to make the colors more accurate," + " matching the color space Wii and GC games were meant for."); static const char TR_POSTPROCESSING_DESCRIPTION[] = QT_TR_NOOP("Applies a post-processing effect after rendering a frame.

If unsure, select (off)."); @@ -498,6 +518,13 @@ void EnhancementsWidget::AddDescriptions() "reduce stutter in games that frequently load new textures. This feature is not compatible " "with GPU Texture Decoding.

If unsure, leave this " "checked."); + static const char TR_HDR_DESCRIPTION[] = QT_TR_NOOP( + "Enables scRGB HDR output (if supported by your graphics backend and monitor)." + " Fullscreen might be required." + "

This gives post process shaders more room for accuracy, allows \"AutoHDR\" " + "post-process shaders to work, and allows to fully display the PAL and NTSC-J color spaces." + "

Note that games still render in SDR internally." + "

If unsure, leave this unchecked."); m_ir_combo->SetTitle(tr("Internal Resolution")); m_ir_combo->SetDescription(tr(TR_INTERNAL_RESOLUTION_DESCRIPTION)); @@ -508,6 +535,8 @@ void EnhancementsWidget::AddDescriptions() m_texture_filtering_combo->SetTitle(tr("Texture Filtering")); m_texture_filtering_combo->SetDescription(tr(TR_FORCE_TEXTURE_FILTERING_DESCRIPTION)); + m_configure_color_correction->setToolTip(tr(TR_COLOR_CORRECTION_DESCRIPTION)); + m_pp_effect->SetTitle(tr("Post-Processing Effect")); m_pp_effect->SetDescription(tr(TR_POSTPROCESSING_DESCRIPTION)); @@ -525,6 +554,8 @@ void EnhancementsWidget::AddDescriptions() m_arbitrary_mipmap_detection->SetDescription(tr(TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION)); + m_hdr->SetDescription(tr(TR_HDR_DESCRIPTION)); + m_3d_mode->SetTitle(tr("Stereoscopic 3D Mode")); m_3d_mode->SetDescription(tr(TR_3D_MODE_DESCRIPTION)); @@ -537,6 +568,11 @@ void EnhancementsWidget::AddDescriptions() m_3d_swap_eyes->SetDescription(tr(TR_3D_SWAP_EYES_DESCRIPTION)); } +void EnhancementsWidget::ConfigureColorCorrection() +{ + ColorCorrectionConfigWindow(this).exec(); +} + void EnhancementsWidget::ConfigurePostProcessingShader() { const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER); diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h index 90d25a7040..56d8741b9c 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h @@ -30,6 +30,7 @@ private: void CreateWidgets(); void ConnectWidgets(); void AddDescriptions(); + void ConfigureColorCorrection(); void ConfigurePostProcessingShader(); void LoadPPShaders(); @@ -38,6 +39,7 @@ private: ToolTipComboBox* m_aa_combo; ToolTipComboBox* m_texture_filtering_combo; ToolTipComboBox* m_pp_effect; + QPushButton* m_configure_color_correction; QPushButton* m_configure_pp_effect; ConfigBool* m_scaled_efb_copy; ConfigBool* m_per_pixel_lighting; @@ -46,6 +48,7 @@ private: ConfigBool* m_force_24bit_color; ConfigBool* m_disable_copy_filter; ConfigBool* m_arbitrary_mipmap_detection; + ConfigBool* m_hdr; // Stereoscopy ConfigChoice* m_3d_mode; diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index cd0f3a7487..79b05b372b 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -80,6 +80,7 @@ + @@ -283,6 +284,7 @@ +