From c513bb5309b9e608230caf5d77ed4c323046d007 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 1 May 2019 21:47:50 -0500 Subject: [PATCH] VideoCommon: Implement passive stereoscopic 3D --- Data/Sys/Shaders/Passive/horizontal.glsl | 7 ++++ Source/Core/Common/CommonPaths.h | 1 + .../Config/Graphics/EnhancementsWidget.cpp | 33 ++++++++++++------- Source/Core/VideoCommon/PostProcessing.cpp | 27 +++++++++++++-- Source/Core/VideoCommon/PostProcessing.h | 1 + Source/Core/VideoCommon/VideoConfig.h | 3 +- 6 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 Data/Sys/Shaders/Passive/horizontal.glsl diff --git a/Data/Sys/Shaders/Passive/horizontal.glsl b/Data/Sys/Shaders/Passive/horizontal.glsl new file mode 100644 index 0000000000..7b2535bbf0 --- /dev/null +++ b/Data/Sys/Shaders/Passive/horizontal.glsl @@ -0,0 +1,7 @@ +// Passive (horizontal rows) shader + +void main() +{ + float screen_row = GetWindowResolution().y * GetCoordinates().y; + SetOutput(SampleLayer(int(screen_row) % 2)); +} diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index 97213f6448..8ef696f741 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -62,6 +62,7 @@ #define THEMES_DIR "Themes" #define STYLES_DIR "Styles" #define ANAGLYPH_DIR "Anaglyph" +#define PASSIVE_DIR "Passive" #define PIPES_DIR "Pipes" #define WFSROOT_DIR "WFS" #define BACKUP_DIR "Backup" diff --git a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp index 950d647f3c..1166214e39 100644 --- a/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp @@ -109,9 +109,9 @@ void EnhancementsWidget::CreateWidgets() auto* stereoscopy_layout = new QGridLayout(); stereoscopy_box->setLayout(stereoscopy_layout); - m_3d_mode = new GraphicsChoice( - {tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"), tr("HDMI 3D")}, - Config::GFX_STEREO_MODE); + m_3d_mode = new GraphicsChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), + tr("Anaglyph"), tr("HDMI 3D"), tr("Passive")}, + Config::GFX_STEREO_MODE); m_3d_depth = new GraphicsSlider(0, 100, Config::GFX_STEREO_DEPTH); m_3d_convergence = new GraphicsSlider(0, 200, Config::GFX_STEREO_CONVERGENCE, 100); m_3d_swap_eyes = new GraphicsBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES); @@ -151,14 +151,19 @@ void EnhancementsWidget::ConnectWidgets() void EnhancementsWidget::LoadPPShaders() { - const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph; - std::vector shaders = anaglyph ? - VideoCommon::PostProcessing::GetAnaglyphShaderList() : - VideoCommon::PostProcessing::GetShaderList(); + std::vector shaders = VideoCommon::PostProcessing::GetShaderList(); + if (g_Config.stereo_mode == StereoMode::Anaglyph) + { + shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList(); + } + else if (g_Config.stereo_mode == StereoMode::Passive) + { + shaders = VideoCommon::PostProcessing::GetPassiveShaderList(); + } m_pp_effect->clear(); - if (!anaglyph) + if (g_Config.stereo_mode != StereoMode::Anaglyph && g_Config.stereo_mode != StereoMode::Passive) m_pp_effect->addItem(tr("(off)")); auto selected_shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER); @@ -175,8 +180,10 @@ void EnhancementsWidget::LoadPPShaders() } } - if (anaglyph && !found) + if (g_Config.stereo_mode == StereoMode::Anaglyph && !found) m_pp_effect->setCurrentIndex(m_pp_effect->findText(QStringLiteral("dubois"))); + else if (g_Config.stereo_mode == StereoMode::Passive && !found) + m_pp_effect->setCurrentIndex(m_pp_effect->findText(QStringLiteral("horizontal"))); const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing; m_pp_effect->setEnabled(supports_postprocessing); @@ -221,7 +228,7 @@ void EnhancementsWidget::LoadSettings() bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders; bool supports_3dvision = g_Config.backend_info.bSupports3DVision; - bool has_3dvision = m_3d_mode->count() == 6; + bool has_3dvision = m_3d_mode->count() == 7; if (has_3dvision && !supports_3dvision) m_3d_mode->removeItem(5); @@ -260,8 +267,9 @@ void EnhancementsWidget::SaveSettings() Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa); const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph; + const bool passive = g_Config.stereo_mode == StereoMode::Passive; Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, - (!anaglyph && m_pp_effect->currentIndex() == 0) ? + (!anaglyph && !passive && m_pp_effect->currentIndex() == 0) ? "(off)" : m_pp_effect->currentText().toStdString()); @@ -324,7 +332,8 @@ void EnhancementsWidget::AddDescriptions() "Selects the stereoscopic 3D mode. Stereoscopy allows a better feeling " "of depth if the necessary hardware is present.\n\nSide-by-Side and Top-and-Bottom are " "used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHDMI 3D is " - "used when the monitor supports 3D display resolutions.\n\nHeavily decreases " + "used when the monitor supports 3D display resolutions.\nPassive is another type of 3D " + "used by some TVs.\n\nHeavily decreases " "emulation speed and sometimes causes issues.\n\nIf unsure, select Off."); static const char TR_3D_DEPTH_DESCRIPTION[] = QT_TR_NOOP( "Controls the separation distance between the virtual cameras. \n\nA higher " diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp index 1f42bd52ca..d6d2b62625 100644 --- a/Source/Core/VideoCommon/PostProcessing.cpp +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -44,8 +44,16 @@ void PostProcessingConfiguration::LoadShader(const std::string& shader) return; } - const std::string sub_dir = - (g_Config.stereo_mode == StereoMode::Anaglyph) ? ANAGLYPH_DIR DIR_SEP : ""; + std::string sub_dir = ""; + + if (g_Config.stereo_mode == StereoMode::Anaglyph) + { + sub_dir = ANAGLYPH_DIR DIR_SEP; + } + else if (g_Config.stereo_mode == StereoMode::Passive) + { + sub_dir = PASSIVE_DIR DIR_SEP; + } // loading shader code std::string code; @@ -364,6 +372,11 @@ std::vector PostProcessing::GetAnaglyphShaderList() return GetShaders(ANAGLYPH_DIR DIR_SEP); } +std::vector PostProcessing::GetPassiveShaderList() +{ + return GetShaders(PASSIVE_DIR DIR_SEP); +} + bool PostProcessing::Initialize(AbstractTextureFormat format) { m_framebuffer_format = format; @@ -425,6 +438,7 @@ std::string PostProcessing::GetUniformBufferHeader() const // Builtin uniforms ss << " float4 resolution;\n"; + ss << " float4 window_resolution;\n"; ss << " float4 src_rect;\n"; ss << " uint time;\n"; ss << " int layer;\n"; @@ -508,6 +522,11 @@ float4 SampleLocation(float2 location) { return texture(samp0, float3(location, float4 SampleLayer(int layer) { return texture(samp0, float3(v_tex0.xy, float(layer))); } #define SampleOffset(offset) textureOffset(samp0, float3(v_tex0.xy, float(layer)), offset) +float2 GetWindowResolution() +{ + return window_resolution.xy; +} + float2 GetResolution() { return resolution.xy; @@ -599,6 +618,7 @@ bool PostProcessing::CompileVertexShader() struct BuiltinUniforms { float resolution[4]; + float window_resolution[4]; float src_rect[4]; s32 time; u32 layer; @@ -614,11 +634,14 @@ size_t PostProcessing::CalculateUniformsSize() const void PostProcessing::FillUniformBuffer(const MathUtil::Rectangle& src, const AbstractTexture* src_tex, int src_layer) { + const auto& window_rect = g_renderer->GetTargetRectangle(); const float rcp_src_width = 1.0f / src_tex->GetWidth(); const float rcp_src_height = 1.0f / src_tex->GetHeight(); BuiltinUniforms builtin_uniforms = { {static_cast(src_tex->GetWidth()), static_cast(src_tex->GetHeight()), rcp_src_width, rcp_src_height}, + {static_cast(window_rect.GetWidth()), static_cast(window_rect.GetHeight()), + 0.0f, 0.0f}, {static_cast(src.left) * rcp_src_width, static_cast(src.top) * rcp_src_height, static_cast(src.GetWidth()) * rcp_src_width, static_cast(src.GetHeight()) * rcp_src_height}, diff --git a/Source/Core/VideoCommon/PostProcessing.h b/Source/Core/VideoCommon/PostProcessing.h index ede8adaf6e..55ff1c7c5d 100644 --- a/Source/Core/VideoCommon/PostProcessing.h +++ b/Source/Core/VideoCommon/PostProcessing.h @@ -94,6 +94,7 @@ public: virtual ~PostProcessing(); static std::vector GetShaderList(); + static std::vector GetPassiveShaderList(); static std::vector GetAnaglyphShaderList(); PostProcessingConfiguration* GetConfig() { return &m_config; } diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index b77ee1c584..674dfa8530 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -39,7 +39,8 @@ enum class StereoMode : int TAB, Anaglyph, QuadBuffer, - Nvidia3DVision + Passive, + Nvidia3DVision, }; enum class ShaderCompilationMode : int