// Copyright 2017 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "DolphinQt/Config/Graphics/EnhancementsWidget.h" #include <cmath> #include <QGridLayout> #include <QGroupBox> #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include "Common/CommonTypes.h" #include "Core/Config/GraphicsSettings.h" #include "Core/ConfigManager.h" #include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigRadio.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" #include "DolphinQt/Config/GameConfigWidget.h" #include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h" #include "DolphinQt/Config/ToolTipControls/ToolTipPushButton.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/Settings.h" #include "VideoCommon/PostProcessing.h" #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) { CreateWidgets(); LoadPPShaders(); ConnectWidgets(); AddDescriptions(); // BackendChanged is called by parent on window creation. connect(parent, &GraphicsWindow::BackendChanged, this, &EnhancementsWidget::OnBackendChanged); connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, [this]() { m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); }); connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this, [this]() { m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); }); } EnhancementsWidget::EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer) { CreateWidgets(); LoadPPShaders(); ConnectWidgets(); AddDescriptions(); connect(&Settings::Instance(), &Settings::ConfigChanged, this, &EnhancementsWidget::OnConfigChanged); } constexpr int ANISO_DEFAULT = 0; constexpr int ANISO_2X = 1; constexpr int ANISO_4X = 2; constexpr int ANISO_8X = 3; constexpr int ANISO_16X = 4; constexpr int FILTERING_DEFAULT = 0; constexpr int FILTERING_NEAREST = 1; constexpr int FILTERING_LINEAR = 2; void EnhancementsWidget::CreateWidgets() { auto* main_layout = new QVBoxLayout; // Enhancements auto* enhancements_box = new QGroupBox(tr("Enhancements")); auto* enhancements_layout = new QGridLayout(); enhancements_box->setLayout(enhancements_layout); QStringList resolution_options{tr("Auto (Multiple of 640x528)"), tr("Native (640x528)")}; // From 2x up. // To calculate the suggested internal resolution scale for each common output resolution, // we find the minimum multiplier that results in an equal or greater resolution than the // output one, on both width and height. // Note that often games don't render to the full resolution, but have some black bars // on the edges; this is not accounted for in the calculations. const QStringList resolution_extra_options{ tr("720p"), tr("1080p"), tr("1440p"), QStringLiteral(""), tr("4K"), QStringLiteral(""), tr("5K"), QStringLiteral(""), QStringLiteral(""), QStringLiteral(""), tr("8K")}; const int visible_resolution_option_count = static_cast<int>(resolution_options.size()) + static_cast<int>(resolution_extra_options.size()); // If the current scale is greater than the max scale in the ini, add sufficient options so that // when the settings are saved we don't lose the user-modified value from the ini. const int max_efb_scale = std::max(ReadSetting(Config::GFX_EFB_SCALE), ReadSetting(Config::GFX_MAX_EFB_SCALE)); for (int scale = static_cast<int>(resolution_options.size()); scale <= max_efb_scale; scale++) { const QString scale_text = QString::number(scale); const QString width_text = QString::number(static_cast<int>(EFB_WIDTH) * scale); const QString height_text = QString::number(static_cast<int>(EFB_HEIGHT) * scale); const int extra_index = resolution_options.size() - 2; const QString extra_text = resolution_extra_options.size() > extra_index ? resolution_extra_options[extra_index] : QStringLiteral(""); if (extra_text.isEmpty()) { resolution_options.append(tr("%1x Native (%2x%3)").arg(scale_text, width_text, height_text)); } else { resolution_options.append( tr("%1x Native (%2x%3) for %4").arg(scale_text, width_text, height_text, extra_text)); } } m_ir_combo = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE, m_game_layer); m_ir_combo->setMaxVisibleItems(visible_resolution_option_count); m_aa_combo = new ConfigComplexChoice(Config::GFX_MSAA, Config::GFX_SSAA, m_game_layer); m_aa_combo->Add(tr("None"), (u32)1, false); m_texture_filtering_combo = new ConfigComplexChoice(Config::GFX_ENHANCE_MAX_ANISOTROPY, Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_game_layer); m_texture_filtering_combo->Add(tr("Default"), ANISO_DEFAULT, FILTERING_DEFAULT); m_texture_filtering_combo->Add(tr("2x Anisotropic"), ANISO_2X, FILTERING_DEFAULT); m_texture_filtering_combo->Add(tr("4x Anisotropic"), ANISO_4X, FILTERING_DEFAULT); m_texture_filtering_combo->Add(tr("8x Anisotropic"), ANISO_8X, FILTERING_DEFAULT); m_texture_filtering_combo->Add(tr("16x Anisotropic"), ANISO_16X, FILTERING_DEFAULT); m_texture_filtering_combo->Add(tr("Force Nearest"), ANISO_DEFAULT, FILTERING_NEAREST); m_texture_filtering_combo->Add(tr("Force Linear"), ANISO_DEFAULT, FILTERING_LINEAR); m_texture_filtering_combo->Add(tr("Force Linear and 2x Anisotropic"), ANISO_2X, FILTERING_LINEAR); m_texture_filtering_combo->Add(tr("Force Linear and 4x Anisotropic"), ANISO_4X, FILTERING_LINEAR); m_texture_filtering_combo->Add(tr("Force Linear and 8x Anisotropic"), ANISO_8X, FILTERING_LINEAR); m_texture_filtering_combo->Add(tr("Force Linear and 16x Anisotropic"), ANISO_16X, FILTERING_LINEAR); m_texture_filtering_combo->Refresh(); m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); m_output_resampling_combo = new ConfigChoice( {tr("Default"), tr("Bilinear"), tr("Bicubic: B-Spline"), tr("Bicubic: Mitchell-Netravali"), tr("Bicubic: Catmull-Rom"), tr("Sharp Bilinear"), tr("Area Sampling")}, Config::GFX_ENHANCE_OUTPUT_RESAMPLING, m_game_layer); m_configure_color_correction = new ToolTipPushButton(tr("Configure")); m_pp_effect = new ConfigStringChoice(VideoCommon::PostProcessing::GetShaderList(), Config::GFX_ENHANCE_POST_SHADER, m_game_layer); m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure")); m_configure_pp_effect->setDisabled(true); m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer); m_per_pixel_lighting = new ConfigBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING, m_game_layer); m_widescreen_hack = new ConfigBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK, m_game_layer); m_disable_fog = new ConfigBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG, m_game_layer); m_force_24bit_color = new ConfigBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_game_layer); m_disable_copy_filter = new ConfigBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_game_layer); m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"), Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION, m_game_layer); m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT, m_game_layer); int row = 0; enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), row, 0); enhancements_layout->addWidget(m_ir_combo, row, 1, 1, -1); ++row; enhancements_layout->addWidget(new QLabel(tr("Anti-Aliasing:")), row, 0); enhancements_layout->addWidget(m_aa_combo, row, 1, 1, -1); ++row; enhancements_layout->addWidget(new QLabel(tr("Texture Filtering:")), row, 0); enhancements_layout->addWidget(m_texture_filtering_combo, row, 1, 1, -1); ++row; enhancements_layout->addWidget(new QLabel(tr("Output Resampling:")), row, 0); enhancements_layout->addWidget(m_output_resampling_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); ++row; enhancements_layout->addWidget(m_scaled_efb_copy, row, 0); enhancements_layout->addWidget(m_per_pixel_lighting, row, 1, 1, -1); ++row; enhancements_layout->addWidget(m_widescreen_hack, row, 0); enhancements_layout->addWidget(m_force_24bit_color, row, 1, 1, -1); ++row; enhancements_layout->addWidget(m_disable_fog, row, 0); enhancements_layout->addWidget(m_arbitrary_mipmap_detection, row, 1, 1, -1); ++row; enhancements_layout->addWidget(m_disable_copy_filter, row, 0); enhancements_layout->addWidget(m_hdr, row, 1, 1, -1); ++row; // Stereoscopy auto* stereoscopy_box = new QGroupBox(tr("Stereoscopy")); auto* stereoscopy_layout = new QGridLayout(); stereoscopy_box->setLayout(stereoscopy_layout); m_3d_mode = new ConfigChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"), tr("HDMI 3D"), tr("Passive")}, Config::GFX_STEREO_MODE, m_game_layer); m_3d_depth = new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH, m_game_layer); m_3d_convergence = new ConfigSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM, Config::GFX_STEREO_CONVERGENCE, m_game_layer, 100); m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES, m_game_layer); m_3d_per_eye_resolution = new ConfigBool( tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL, m_game_layer); stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0); stereoscopy_layout->addWidget(m_3d_mode, 0, 1); stereoscopy_layout->addWidget(new ConfigSliderLabel(tr("Depth:"), m_3d_depth), 1, 0); stereoscopy_layout->addWidget(m_3d_depth, 1, 1); stereoscopy_layout->addWidget(new ConfigSliderLabel(tr("Convergence:"), m_3d_convergence), 2, 0); stereoscopy_layout->addWidget(m_3d_convergence, 2, 1); stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0); stereoscopy_layout->addWidget(m_3d_per_eye_resolution, 4, 0); auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); if (current_stereo_mode != StereoMode::SBS && current_stereo_mode != StereoMode::TAB) m_3d_per_eye_resolution->hide(); main_layout->addWidget(enhancements_box); main_layout->addWidget(stereoscopy_box); main_layout->addStretch(); setLayout(main_layout); } void EnhancementsWidget::ConnectWidgets() { connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] { auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); LoadPPShaders(); if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB) m_3d_per_eye_resolution->show(); else m_3d_per_eye_resolution->hide(); }); connect(m_pp_effect, &QComboBox::currentIndexChanged, this, &EnhancementsWidget::ShaderChanged); connect(m_configure_color_correction, &QPushButton::clicked, this, &EnhancementsWidget::ConfigureColorCorrection); connect(m_configure_pp_effect, &QPushButton::clicked, this, &EnhancementsWidget::ConfigurePostProcessingShader); } template <typename T> T EnhancementsWidget::ReadSetting(const Config::Info<T>& setting) const { if (m_game_layer != nullptr) return m_game_layer->Get(setting); else return Config::Get(setting); } void EnhancementsWidget::LoadPPShaders() { auto stereo_mode = ReadSetting(Config::GFX_STEREO_MODE); const QSignalBlocker blocker(m_pp_effect); m_pp_effect->clear(); // Get shader list std::vector<std::string> shaders = VideoCommon::PostProcessing::GetShaderList(); if (stereo_mode == StereoMode::Anaglyph) shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList(); else if (stereo_mode == StereoMode::Passive) shaders = VideoCommon::PostProcessing::GetPassiveShaderList(); // Populate widget if (stereo_mode != StereoMode::Anaglyph && stereo_mode != StereoMode::Passive) m_pp_effect->addItem(tr("(off)")); auto selected_shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); bool found = false; for (const auto& shader : shaders) { m_pp_effect->addItem(QString::fromStdString(shader)); if (selected_shader == shader) { m_pp_effect->setCurrentIndex(m_pp_effect->count() - 1); found = true; } } // Force a shader for StereoModes that require it. if (!found) { if (stereo_mode == StereoMode::Anaglyph) selected_shader = "dubois"; else if (stereo_mode == StereoMode::Passive) selected_shader = "horizontal"; else selected_shader = ""; int index = m_pp_effect->findText(QString::fromStdString(selected_shader)); if (index >= 0) m_pp_effect->setCurrentIndex(index); else m_pp_effect->setCurrentIndex(0); // Save forced shader, but avoid forcing an option into a game ini layer. if (m_game_layer == nullptr && ReadSetting(Config::GFX_ENHANCE_POST_SHADER) != selected_shader) Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, selected_shader); } m_pp_effect->Load(); ShaderChanged(); } void EnhancementsWidget::OnBackendChanged() { m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing); m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput); // Stereoscopy const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders; m_3d_mode->setEnabled(supports_stereoscopy); m_3d_convergence->setEnabled(supports_stereoscopy); m_3d_depth->setEnabled(supports_stereoscopy); m_3d_swap_eyes->setEnabled(supports_stereoscopy); // PostProcessing const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing; if (!supports_postprocessing) { m_configure_pp_effect->setEnabled(false); m_pp_effect->setEnabled(false); m_pp_effect->setToolTip( tr("%1 doesn't support this feature.").arg(tr(g_video_backend->GetDisplayName().c_str()))); } else if (!m_pp_effect->isEnabled() && supports_postprocessing) { m_configure_pp_effect->setEnabled(true); m_pp_effect->setEnabled(true); m_pp_effect->setToolTip(QString{}); LoadPPShaders(); } UpdateAAOptions(); } void EnhancementsWidget::ShaderChanged() { auto shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); if (shader == "(off)" || shader == "") { shader = ""; // Setting a shader to null in a game ini could be confusing, as it won't be bolded. Remove it // instead. if (m_game_layer != nullptr) m_game_layer->DeleteKey(Config::GFX_ENHANCE_POST_SHADER.GetLocation()); else Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, shader); } if (shader != "" && m_pp_effect->isEnabled()) { VideoCommon::PostProcessingConfiguration pp_shader; pp_shader.LoadShader(shader); m_configure_pp_effect->setEnabled(pp_shader.HasOptions()); } else { m_configure_pp_effect->setEnabled(false); } } void EnhancementsWidget::OnConfigChanged() { // Only used for the GameConfigWidget. Bypasses graphics window signals and backend info due to it // being global. m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING)); m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING)); UpdateAAOptions(); // Needs to update after deleting a key for 3d settings. LoadPPShaders(); } void EnhancementsWidget::UpdateAAOptions() { const QSignalBlocker blocker_aa(m_aa_combo); m_aa_combo->Reset(); m_aa_combo->Add(tr("None"), (u32)1, false); std::vector<u32> aa_modes = g_Config.backend_info.AAModes; for (const u32 aa_mode : aa_modes) { if (aa_mode > 1) m_aa_combo->Add(tr("%1x MSAA").arg(aa_mode), aa_mode, false); } if (g_Config.backend_info.bSupportsSSAA) { for (const u32 aa_mode : aa_modes) { if (aa_mode > 1) m_aa_combo->Add(tr("%1x SSAA").arg(aa_mode), aa_mode, true); } } m_aa_combo->Refresh(); // Backend info can't be populated in the local game settings window. Only enable local game AA // edits when the backend info is correct - global and local have the same backend. const bool good_info = m_game_layer == nullptr || !m_game_layer->Exists(Config::MAIN_GFX_BACKEND.GetLocation()) || Config::Get(Config::MAIN_GFX_BACKEND) == m_game_layer->Get(Config::MAIN_GFX_BACKEND); m_aa_combo->setEnabled(m_aa_combo->count() > 1 && good_info); } void EnhancementsWidget::AddDescriptions() { static const char TR_INTERNAL_RESOLUTION_DESCRIPTION[] = QT_TR_NOOP("Controls the rendering resolution.<br><br>A high resolution greatly improves " "visual quality, but also greatly increases GPU load and can cause issues in " "certain games. Generally speaking, the lower the internal resolution, the " "better performance will be.<br><br><dolphin_emphasis>If unsure, " "select Native.</dolphin_emphasis>"); static const char TR_ANTIALIAS_DESCRIPTION[] = QT_TR_NOOP( "Reduces the amount of aliasing caused by rasterizing 3D graphics, resulting " "in smoother edges on objects. Increases GPU load and sometimes causes graphical " "issues.<br><br>SSAA is significantly more demanding than MSAA, but provides top quality " "geometry anti-aliasing and also applies anti-aliasing to lighting, shader " "effects, and textures.<br><br><dolphin_emphasis>If unsure, select " "None.</dolphin_emphasis>"); static const char TR_FORCE_TEXTURE_FILTERING_DESCRIPTION[] = QT_TR_NOOP( "Adjust the texture filtering. Anisotropic filtering enhances the visual quality of textures " "that are at oblique viewing angles. Force Nearest and Force Linear override the texture " "scaling filter selected by the game.<br><br>Any option except 'Default' will alter the look " "of the game's textures and might cause issues in a small number of games.<br><br>This " "setting is disabled when Manual Texture Sampling is enabled.<br><br>" "<dolphin_emphasis>If unsure, select 'Default'.</dolphin_emphasis>"); static const char TR_OUTPUT_RESAMPLING_DESCRIPTION[] = QT_TR_NOOP("Affects how the game output is scaled to the window resolution." "<br>The performance mostly depends on the number of samples each method uses." "<br>Compared to SSAA, resampling is useful in case the output window" "<br>resolution isn't a multiplier of the native emulation resolution." "<br><br><b>Default</b> - [fastest]" "<br>Internal GPU bilinear sampler which is not gamma corrected." "<br>This setting might be ignored if gamma correction is forced on." "<br><br><b>Bilinear</b> - [4 samples]" "<br>Gamma corrected linear interpolation between pixels." "<br><br><b>Bicubic</b> - [16 samples]" "<br>Gamma corrected cubic interpolation between pixels." "<br>Good when rescaling between close resolutions, e.g. 1080p and 1440p." "<br>Comes in various flavors:" "<br><b>B-Spline</b>: Blurry, but avoids all lobing artifacts" "<br><b>Mitchell-Netravali</b>: Good middle ground between blurry and lobing" "<br><b>Catmull-Rom</b>: Sharper, but can cause lobing artifacts" "<br><br><b>Sharp Bilinear</b> - [1-4 samples]" "<br>Similar to \"Nearest Neighbor\", it maintains a sharp look," "<br>but also does some blending to avoid shimmering." "<br>Works best with 2D games at low resolutions." "<br><br><b>Area Sampling</b> - [up to 324 samples]" "<br>Weighs pixels by the percentage of area they occupy. Gamma corrected." "<br>Best for downscaling by more than 2x." "<br><br><dolphin_emphasis>If unsure, select 'Default'.</dolphin_emphasis>"); 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.<br><br " "/><dolphin_emphasis>If unsure, select (off).</dolphin_emphasis>"); static const char TR_SCALED_EFB_COPY_DESCRIPTION[] = QT_TR_NOOP("Greatly increases the quality of textures generated using render-to-texture " "effects.<br><br>Slightly increases GPU load and causes relatively few graphical " "issues. Raising the internal resolution will improve the effect of this setting. " "<br><br><dolphin_emphasis>If unsure, leave this checked.</dolphin_emphasis>"); static const char TR_PER_PIXEL_LIGHTING_DESCRIPTION[] = QT_TR_NOOP( "Calculates lighting of 3D objects per-pixel rather than per-vertex, smoothing out the " "appearance of lit polygons and making individual triangles less noticeable.<br><br " "/>Rarely " "causes slowdowns or graphical issues.<br><br><dolphin_emphasis>If unsure, leave " "this unchecked.</dolphin_emphasis>"); static const char TR_WIDESCREEN_HACK_DESCRIPTION[] = QT_TR_NOOP( "Forces the game to output graphics at any aspect ratio by expanding the view frustum " "without stretching the image.<br>This is a hack, and its results will vary widely game " "to game (it often causes the UI to stretch).<br>" "Game-specific AR/Gecko-code aspect ratio patches are preferable over this if available." "<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"); static const char TR_REMOVE_FOG_DESCRIPTION[] = QT_TR_NOOP("Makes distant objects more visible by removing fog, thus increasing the overall " "detail.<br><br>Disabling fog will break some games which rely on proper fog " "emulation.<br><br><dolphin_emphasis>If unsure, leave this " "unchecked.</dolphin_emphasis>"); static const char TR_3D_MODE_DESCRIPTION[] = QT_TR_NOOP( "Selects the stereoscopic 3D mode. Stereoscopy allows a better feeling " "of depth if the necessary hardware is present. Heavily decreases " "emulation speed and sometimes causes issues.<br><br>Side-by-Side and Top-and-Bottom are " "used by most 3D TVs.<br>Anaglyph is used for Red-Cyan colored glasses.<br>HDMI 3D is " "used when the monitor supports 3D display resolutions.<br>Passive is another type of 3D " "used by some TVs.<br><br><dolphin_emphasis>If unsure, select Off.</dolphin_emphasis>"); static const char TR_3D_DEPTH_DESCRIPTION[] = QT_TR_NOOP( "Controls the separation distance between the virtual cameras.<br><br>A higher " "value creates a stronger feeling of depth while a lower value is more comfortable."); static const char TR_3D_CONVERGENCE_DESCRIPTION[] = QT_TR_NOOP( "Controls the distance of the convergence plane. This is the distance at which " "virtual objects will appear to be in front of the screen.<br><br>A higher value creates " "stronger out-of-screen effects while a lower value is more comfortable."); static const char TR_3D_SWAP_EYES_DESCRIPTION[] = QT_TR_NOOP( "Swaps the left and right eye. Most useful in side-by-side stereoscopy " "mode.<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"); static const char TR_3D_PER_EYE_RESOLUTION_DESCRIPTION[] = QT_TR_NOOP("Whether each eye gets full or half image resolution when using side-by-side " "or above-and-below 3D." "<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"); static const char TR_FORCE_24BIT_DESCRIPTION[] = QT_TR_NOOP( "Forces the game to render the RGB color channels in 24-bit, thereby increasing " "quality by reducing color banding.<br><br>Has no impact on performance and causes " "few graphical issues.<br><br><dolphin_emphasis>If unsure, leave this " "checked.</dolphin_emphasis>"); static const char TR_DISABLE_COPY_FILTER_DESCRIPTION[] = QT_TR_NOOP( "Disables the blending of adjacent rows when copying the EFB. This is known in " "some games as \"deflickering\" or \"smoothing\".<br><br>Disabling the filter has no " "effect on performance, but may result in a sharper image. Causes few " "graphical issues.<br><br><dolphin_emphasis>If unsure, leave this " "checked.</dolphin_emphasis>"); static const char TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION[] = QT_TR_NOOP( "Enables detection of arbitrary mipmaps, which some games use for special distance-based " "effects.<br><br>May have false positives that result in blurry textures at increased " "internal " "resolution, such as in games that use very low resolution mipmaps. Disabling this can also " "reduce stutter in games that frequently load new textures.<br><br>This setting is disabled " "when GPU Texture Decoding is enabled.<br><br><dolphin_emphasis>If unsure, leave this " "unchecked.</dolphin_emphasis>"); 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." "<br><br>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." "<br><br>Note that games still render in SDR internally." "<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"); m_ir_combo->SetTitle(tr("Internal Resolution")); m_ir_combo->SetDescription(tr(TR_INTERNAL_RESOLUTION_DESCRIPTION)); m_aa_combo->SetTitle(tr("Anti-Aliasing")); m_aa_combo->SetDescription(tr(TR_ANTIALIAS_DESCRIPTION)); m_texture_filtering_combo->SetTitle(tr("Texture Filtering")); m_texture_filtering_combo->SetDescription(tr(TR_FORCE_TEXTURE_FILTERING_DESCRIPTION)); m_output_resampling_combo->SetTitle(tr("Output Resampling")); m_output_resampling_combo->SetDescription(tr(TR_OUTPUT_RESAMPLING_DESCRIPTION)); m_configure_color_correction->SetTitle(tr("Color Correction")); m_configure_color_correction->SetDescription(tr(TR_COLOR_CORRECTION_DESCRIPTION)); m_pp_effect->SetTitle(tr("Post-Processing Effect")); m_pp_effect->SetDescription(tr(TR_POSTPROCESSING_DESCRIPTION)); m_scaled_efb_copy->SetDescription(tr(TR_SCALED_EFB_COPY_DESCRIPTION)); m_per_pixel_lighting->SetDescription(tr(TR_PER_PIXEL_LIGHTING_DESCRIPTION)); m_widescreen_hack->SetDescription(tr(TR_WIDESCREEN_HACK_DESCRIPTION)); m_disable_fog->SetDescription(tr(TR_REMOVE_FOG_DESCRIPTION)); m_force_24bit_color->SetDescription(tr(TR_FORCE_24BIT_DESCRIPTION)); m_disable_copy_filter->SetDescription(tr(TR_DISABLE_COPY_FILTER_DESCRIPTION)); 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)); m_3d_depth->SetTitle(tr("Depth")); m_3d_depth->SetDescription(tr(TR_3D_DEPTH_DESCRIPTION)); m_3d_convergence->SetTitle(tr("Convergence")); m_3d_convergence->SetDescription(tr(TR_3D_CONVERGENCE_DESCRIPTION)); m_3d_per_eye_resolution->SetDescription(tr(TR_3D_PER_EYE_RESOLUTION_DESCRIPTION)); m_3d_swap_eyes->SetDescription(tr(TR_3D_SWAP_EYES_DESCRIPTION)); } void EnhancementsWidget::ConfigureColorCorrection() { ColorCorrectionConfigWindow dialog(this); SetQWidgetWindowDecorations(&dialog); dialog.exec(); } void EnhancementsWidget::ConfigurePostProcessingShader() { const std::string shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER); PostProcessingConfigWindow dialog(this, shader); SetQWidgetWindowDecorations(&dialog); dialog.exec(); }