diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 31df12c5f..35bfd2a47 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -155,7 +155,7 @@ bg_blue = bg_green = # Whether and how Stereoscopic 3D should be rendered -# 0 (default): Off, 1: Side by Side, 2: Anaglyph, 3: Interlaced, 4: Reverse Interlaced, 5: Cardboard VR +# 0 (default): Off, 1: Side by Side, 2: Full Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR render_3d = # Change 3D Intensity diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index be3c67948..2aa1d39b0 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -156,7 +156,7 @@ bg_blue = bg_green = # Whether and how Stereoscopic 3D should be rendered -# 0 (default): Off, 1: Side by Side, 2: Anaglyph, 3: Interlaced, 4: Reverse Interlaced +# 0 (default): Off, 1: Side by Side, 2: Full Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced render_3d = # Change 3D Intensity diff --git a/src/citra_qt/configuration/configure_enhancements.ui b/src/citra_qt/configuration/configure_enhancements.ui index a57d1cdbd..de43775d1 100644 --- a/src/citra_qt/configuration/configure_enhancements.ui +++ b/src/citra_qt/configuration/configure_enhancements.ui @@ -234,6 +234,11 @@ Side by Side + + + Full Side by Side + + Anaglyph diff --git a/src/common/settings.h b/src/common/settings.h index e463ba4d7..97627a5c5 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -54,10 +54,11 @@ enum class LayoutOption : u32 { enum class StereoRenderOption : u32 { Off = 0, SideBySide = 1, - Anaglyph = 2, - Interlaced = 3, - ReverseInterlaced = 4, - CardboardVR = 5 + FullSideBySide = 2, + Anaglyph = 3, + Interlaced = 4, + ReverseInterlaced = 5, + CardboardVR = 6 }; // Which eye to render when 3d is off. 800px wide mode could be added here in the future, when diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 11d2249ac..547e54fa0 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -172,14 +172,28 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool up bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; } + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::FullSideBySide && + !(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows && + swapped)) { + emulation_aspect_ratio /= 2; + } float window_aspect_ratio = static_cast(height) / width; if (window_aspect_ratio < emulation_aspect_ratio) { - top_screen = - top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2); - bot_screen = - bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2); + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::FullSideBySide && + !(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows && + swapped)) { + top_screen = + top_screen.TranslateX((screen_window_area.GetWidth() / 2 - top_screen.GetWidth()) / 2); + bot_screen = + bot_screen.TranslateX((screen_window_area.GetWidth() / 2 - bot_screen.GetWidth()) / 2); + } else { + top_screen = + top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2); + bot_screen = + bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2); + } } else { top_screen = top_screen.TranslateY((height - top_screen.GetHeight()) / 2); bot_screen = bot_screen.TranslateY((height - bot_screen.GetHeight()) / 2); @@ -230,6 +244,9 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr small_screen_aspect_ratio = BOT_SCREEN_ASPECT_RATIO; } } + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::FullSideBySide) { + emulation_aspect_ratio /= 2; + } Common::Rectangle screen_window_area{0, 0, width, height}; Common::Rectangle total_rect = MaxRectangle(screen_window_area, emulation_aspect_ratio); @@ -238,7 +255,11 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr Common::Rectangle small_screen = MaxRectangle(scaled_rect, small_screen_aspect_ratio); if (window_aspect_ratio < emulation_aspect_ratio) { - large_screen = large_screen.TranslateX((width - total_rect.GetWidth()) / 2); + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::FullSideBySide) { + large_screen = large_screen.TranslateX((width / 2 - total_rect.GetWidth()) / 2); + } else { + large_screen = large_screen.TranslateX((width - total_rect.GetWidth()) / 2); + } } else { large_screen = large_screen.TranslateY((height - total_rect.GetHeight()) / 2); } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index ce22270cf..100d2464a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -747,6 +747,15 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout, top_screen_top, top_screen_width / 2, top_screen_height, orientation); break; } + case Settings::StereoRenderOption::FullSideBySide: { + DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width, + top_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[1], + static_cast(top_screen_left + (layout.width / 2)), + top_screen_top, top_screen_width, top_screen_height, orientation); + break; + } case Settings::StereoRenderOption::CardboardVR: { DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width, top_screen_height, orientation); @@ -801,6 +810,17 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, } break; } + case Settings::StereoRenderOption::FullSideBySide: { + DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, + bottom_screen_width, bottom_screen_height, orientation); + if (Settings::values.layout_option.GetValue() != Settings::LayoutOption::SeparateWindows){ + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[2], static_cast(bottom_screen_left + (layout.width / 2)), + bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation); + } + break; + } case Settings::StereoRenderOption::CardboardVR: { DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index dd0776c0e..e6d358c4b 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -703,6 +703,14 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout, top_screen_top, top_screen_width / 2, top_screen_height, orientation); break; } + case Settings::StereoRenderOption::FullSideBySide: { + DrawSingleScreen(0, top_screen_left, top_screen_top, top_screen_width, + top_screen_height, orientation); + draw_info.layer = 1; + DrawSingleScreen(1, static_cast(top_screen_left + (layout.width / 2)), + top_screen_top, top_screen_width, top_screen_height, orientation); + break; + } case Settings::StereoRenderOption::CardboardVR: { DrawSingleScreen(0, top_screen_left, top_screen_top, top_screen_width, top_screen_height, orientation); @@ -756,6 +764,17 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, } break; } + case Settings::StereoRenderOption::FullSideBySide: { + DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, + bottom_screen_height, orientation); + if (Settings::values.layout_option.GetValue() != Settings::LayoutOption::SeparateWindows){ + draw_info.layer = 1; + DrawSingleScreen(2, static_cast(bottom_screen_left + (layout.width / 2)), + bottom_screen_top, bottom_screen_width, bottom_screen_height, + orientation); + } + break; + } case Settings::StereoRenderOption::CardboardVR: { DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation);