diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index 4dfe819beb..cd916c6864 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -163,6 +163,8 @@ const Info GFX_CC_HDR_PAPER_WHITE_NITS{{System::GFX, "ColorCorrection", " // Graphics.Stereoscopy const Info GFX_STEREO_MODE{{System::GFX, "Stereoscopy", "StereoMode"}, StereoMode::Off}; +const Info GFX_STEREO_PER_EYE_RESOLUTION_FULL{ + {System::GFX, "Stereoscopy", "StereoPerEyeResolutionFull"}, false}; const Info GFX_STEREO_DEPTH{{System::GFX, "Stereoscopy", "StereoDepth"}, 20}; const Info GFX_STEREO_CONVERGENCE_PERCENTAGE{ {System::GFX, "Stereoscopy", "StereoConvergencePercentage"}, 100}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index bccc5ae293..7bad7fefbb 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -10,6 +10,7 @@ enum class AspectMode : int; enum class ShaderCompilationMode : int; enum class StereoMode : int; +enum class StereoPerEyeResolution : int; enum class TextureFilteringMode : int; enum class OutputResamplingMode : int; enum class ColorCorrectionRegion : int; @@ -139,6 +140,7 @@ extern const Info GFX_CC_HDR_PAPER_WHITE_NITS; // Graphics.Stereoscopy extern const Info GFX_STEREO_MODE; +extern const Info GFX_STEREO_PER_EYE_RESOLUTION_FULL; extern const Info GFX_STEREO_DEPTH; extern const Info GFX_STEREO_CONVERGENCE_PERCENTAGE; extern const Info GFX_STEREO_SWAP_EYES; diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 5a5118932b..cc74b4d8af 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -385,6 +385,8 @@ void DolphinAnalytics::MakePerGameBuilder() builder.AddData("cfg-gfx-internal-resolution", g_Config.iEFBScale); builder.AddData("cfg-gfx-tc-samples", g_Config.iSafeTextureCache_ColorSamples); builder.AddData("cfg-gfx-stereo-mode", static_cast(g_Config.stereo_mode)); + builder.AddData("cfg-gfx-stereo-per-eye-resolution-full", + g_Config.stereo_per_eye_resolution_full); builder.AddData("cfg-gfx-hdr", static_cast(g_Config.bHDR)); builder.AddData("cfg-gfx-per-pixel-lighting", g_Config.bEnablePixelLighting); builder.AddData("cfg-gfx-shader-compilation-mode", GetShaderCompilationMode(g_Config)); diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index f70b01ef6a..897eea6be6 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -213,8 +213,12 @@ void EnhancementsWidget::CreateWidgets() m_3d_depth = new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH); m_3d_convergence = new ConfigSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM, Config::GFX_STEREO_CONVERGENCE, 100); + m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES); + m_3d_per_eye_resolution = + new ConfigBool(tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL); + stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0); stereoscopy_layout->addWidget(m_3d_mode, 0, 1); stereoscopy_layout->addWidget(new QLabel(tr("Depth:")), 1, 0); @@ -222,6 +226,11 @@ void EnhancementsWidget::CreateWidgets() stereoscopy_layout->addWidget(new QLabel(tr("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 = Config::Get(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); @@ -241,9 +250,16 @@ void EnhancementsWidget::ConnectWidgets() connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] { m_block_save = true; m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing); - LoadPPShaders(static_cast(m_3d_mode->currentIndex())); - m_block_save = false; + auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE); + LoadPPShaders(current_stereo_mode); + + if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB) + m_3d_per_eye_resolution->show(); + else + m_3d_per_eye_resolution->hide(); + + m_block_save = false; SaveSettings(); }); connect(m_configure_color_correction, &QPushButton::clicked, this, @@ -609,6 +625,10 @@ void EnhancementsWidget::AddDescriptions() 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.

If unsure, leave this unchecked."); + 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." + "

If unsure, leave this unchecked."); 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.

Has no impact on performance and causes " @@ -679,6 +699,8 @@ void EnhancementsWidget::AddDescriptions() 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)); } diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h index 7c4c193fb4..9e64d5400f 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h @@ -58,6 +58,7 @@ private: ConfigSlider* m_3d_depth; ConfigSlider* m_3d_convergence; ConfigBool* m_3d_swap_eyes; + ConfigBool* m_3d_per_eye_resolution; int m_msaa_modes; bool m_block_save; diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp index 66d377acd7..c7ae018bbc 100644 --- a/Source/Core/VideoCommon/Present.cpp +++ b/Source/Core/VideoCommon/Present.cpp @@ -398,40 +398,68 @@ Presenter::ConvertStereoRectangle(const MathUtil::Rectangle& rc) const float Presenter::CalculateDrawAspectRatio(bool allow_stretch) const { auto aspect_mode = g_ActiveConfig.aspect_mode; + float resulting_aspect_ratio; if (!allow_stretch && aspect_mode == AspectMode::Stretch) aspect_mode = AspectMode::Auto; // If stretch is enabled, we prefer the aspect ratio of the window. if (aspect_mode == AspectMode::Stretch) - return (static_cast(m_backbuffer_width) / static_cast(m_backbuffer_height)); + { + resulting_aspect_ratio = + (static_cast(m_backbuffer_width) / static_cast(m_backbuffer_height)); + } + else + { + // The actual aspect ratio of the XFB texture is irrelevant, the VI one is the one that matters + const auto& vi = Core::System::GetInstance().GetVideoInterface(); + const float source_aspect_ratio = vi.GetAspectRatio(); - // The actual aspect ratio of the XFB texture is irrelevant, the VI one is the one that matters - const auto& vi = Core::System::GetInstance().GetVideoInterface(); - const float source_aspect_ratio = vi.GetAspectRatio(); - - // This will scale up the source ~4:3 resolution to its equivalent ~16:9 resolution - if (aspect_mode == AspectMode::ForceWide || - (aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen())) - { - return SourceAspectRatioToWidescreen(source_aspect_ratio); - } - else if (aspect_mode == AspectMode::Custom) - { - return source_aspect_ratio * (g_ActiveConfig.GetCustomAspectRatio() / (4.0f / 3.0f)); - } - // For the "custom stretch" mode, we force the exact target aspect ratio, without - // acknowleding the difference between the source aspect ratio and 4:3. - else if (aspect_mode == AspectMode::CustomStretch) - { - return g_ActiveConfig.GetCustomAspectRatio(); - } - else if (aspect_mode == AspectMode::Raw) - { - return m_xfb_entry ? (static_cast(m_last_xfb_width) / m_last_xfb_height) : 1.f; + // This will scale up the source ~4:3 resolution to its equivalent ~16:9 resolution + if (aspect_mode == AspectMode::ForceWide || + (aspect_mode == AspectMode::Auto && g_widescreen->IsGameWidescreen())) + { + resulting_aspect_ratio = SourceAspectRatioToWidescreen(source_aspect_ratio); + } + else if (aspect_mode == AspectMode::Custom) + { + resulting_aspect_ratio = + source_aspect_ratio * (g_ActiveConfig.GetCustomAspectRatio() / (4.0f / 3.0f)); + } + // For the "custom stretch" mode, we force the exact target aspect ratio, without + // acknowledging the difference between the source aspect ratio and 4:3. + else if (aspect_mode == AspectMode::CustomStretch) + { + resulting_aspect_ratio = g_ActiveConfig.GetCustomAspectRatio(); + } + else if (aspect_mode == AspectMode::Raw) + { + resulting_aspect_ratio = + m_xfb_entry ? (static_cast(m_last_xfb_width) / m_last_xfb_height) : 1.f; + } + else + { + resulting_aspect_ratio = source_aspect_ratio; + } } - return source_aspect_ratio; + if (g_ActiveConfig.stereo_per_eye_resolution_full) + { + if (g_ActiveConfig.stereo_mode == StereoMode::SBS) + { + // Render twice as wide if using side-by-side 3D, since the 3D will halve the horizontal + // resolution + resulting_aspect_ratio *= 2.0; + } + else if (g_ActiveConfig.stereo_mode == StereoMode::TAB) + { + // Render twice as tall if using top-and-bottom 3D, since the 3D will halve the vertical + // resolution + resulting_aspect_ratio /= 2.0; + } + } + + return resulting_aspect_ratio; } void Presenter::AdjustRectanglesToFitBounds(MathUtil::Rectangle* target_rect, diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index efa159795c..8ca1f4ec63 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -171,6 +171,7 @@ void VideoConfig::Refresh() color_correction.fHDRPaperWhiteNits = Config::Get(Config::GFX_CC_HDR_PAPER_WHITE_NITS); stereo_mode = Config::Get(Config::GFX_STEREO_MODE); + stereo_per_eye_resolution_full = Config::Get(Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL); iStereoDepth = Config::Get(Config::GFX_STEREO_DEPTH); iStereoConvergencePercentage = Config::Get(Config::GFX_STEREO_CONVERGENCE_PERCENTAGE); bStereoSwapEyes = Config::Get(Config::GFX_STEREO_SWAP_EYES); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 1e5f03d0e5..5cce23bfd2 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -241,6 +241,7 @@ struct VideoConfig final // Stereoscopy StereoMode stereo_mode{}; + bool stereo_per_eye_resolution_full = false; int iStereoDepth = 0; int iStereoConvergence = 0; int iStereoConvergencePercentage = 0;