From 9203b238684a9d825bcc059b8eb4037746573ea4 Mon Sep 17 00:00:00 2001 From: OpenSauce Date: Mon, 24 Mar 2025 21:26:14 +0000 Subject: [PATCH] Stereoscopic 3D Enhancements (#602) * Stereoscopic 3D Enhancements - Increase maximum 3D depth to 255% - Fix touch screen to only render 2D when separate window layout is used - Cleanup some 3D option localizations * qt: Added warning label below depth slider for values over 100% * Fixed broken rendering for Interlaced, Reverse Interlaced and Anaglyph options when using 3D with seperate windows * android: Added warning label below depth slider for values over 100% * Fixed a bracket and break statement being incorrectly positioned --------- Co-authored-by: oneup03 --- .../settings/ui/SettingsFragmentPresenter.kt | 2 +- src/android/app/src/main/jni/default_ini.h | 2 +- .../app/src/main/res/values/strings.xml | 2 +- src/citra_qt/citra_qt.cpp | 2 +- .../configuration/configure_enhancements.ui | 9 ++++- src/core/frontend/emu_window.cpp | 32 ++++++++++++----- .../renderer_opengl/renderer_opengl.cpp | 23 +++++++++---- .../renderer_vulkan/renderer_vulkan.cpp | 34 ++++++++++++++----- 8 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index d4f927e35..9810a5e02 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -868,7 +868,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) R.string.factor3d, R.string.factor3d_description, 0, - 100, + 255, "%", IntSetting.STEREOSCOPIC_3D_DEPTH.key, IntSetting.STEREOSCOPIC_3D_DEPTH.defaultValue.toFloat() diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index 3f9c818de..be294ea93 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -162,7 +162,7 @@ bg_green = render_3d = # Change 3D Intensity -# 0 - 100: Intensity. 0 (default) +# 0 - 255: Intensity. 0 (default) factor_3d = # The name of the post processing shader to apply. diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 8afbc7d7e..572a36422 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -254,7 +254,7 @@ Stereoscopy Stereoscopic 3D Mode Depth - Specifies the value of the 3D slider. This should be set to higher than 0% when Stereoscopic 3D is enabled. + Specifies the value of the 3D slider. This should be set to higher than 0% when Stereoscopic 3D is enabled.\nNote: Depth values over 100% are not possible on real hardware and may cause graphical issues Cardboard VR Cardboard Screen Size Scales the screen to a percentage of its original size. diff --git a/src/citra_qt/citra_qt.cpp b/src/citra_qt/citra_qt.cpp index 9f0a0ea6b..8dfb2dae7 100644 --- a/src/citra_qt/citra_qt.cpp +++ b/src/citra_qt/citra_qt.cpp @@ -836,7 +836,7 @@ void GMainWindow::InitializeHotkeys() { }); connect_shortcut(QStringLiteral("Increase 3D Factor"), [this] { const auto factor_3d = Settings::values.factor_3d.GetValue(); - if (factor_3d < 100) { + if (factor_3d < 255) { if (factor_3d % FACTOR_3D_STEP != 0) { Settings::values.factor_3d = factor_3d + FACTOR_3D_STEP - (factor_3d % FACTOR_3D_STEP); diff --git a/src/citra_qt/configuration/configure_enhancements.ui b/src/citra_qt/configuration/configure_enhancements.ui index a496d35f5..b69676d02 100644 --- a/src/citra_qt/configuration/configure_enhancements.ui +++ b/src/citra_qt/configuration/configure_enhancements.ui @@ -276,7 +276,7 @@ 0 - 100 + 255 0 @@ -285,6 +285,13 @@ + + + + Note: Depth values over 100% are not possible on real hardware and may cause graphical issues + + + diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 6c2811cf0..8a979cbdd 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -94,17 +94,24 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns std::tuple EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue(); + bool separate_win = false; +#ifndef ANDROID + separate_win = + (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); +#endif if (new_x >= framebuffer_layout.width / 2) { - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) + if ((render_3d_mode == Settings::StereoRenderOption::SideBySide || + render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) && + !separate_win) new_x -= framebuffer_layout.width / 2; else if (render_3d_mode == Settings::StereoRenderOption::CardboardVR) new_x -= (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); } - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) { + if ((render_3d_mode == Settings::StereoRenderOption::SideBySide || + render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) && + !separate_win) { new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); } else { @@ -130,21 +137,28 @@ void EmuWindow::CreateTouchState() { bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue(); + bool separate_win = false; +#ifndef ANDROID + separate_win = + (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); +#endif if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) return false; if (framebuffer_x >= framebuffer_layout.width / 2) { - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) + if ((render_3d_mode == Settings::StereoRenderOption::SideBySide || + render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) && + !separate_win) framebuffer_x -= framebuffer_layout.width / 2; else if (render_3d_mode == Settings::StereoRenderOption::CardboardVR) framebuffer_x -= (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); } std::scoped_lock guard(touch_state->mutex); - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) { + if ((render_3d_mode == Settings::StereoRenderOption::SideBySide || + render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) && + !separate_win) { touch_state->touch_x = static_cast(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / (framebuffer_layout.bottom_screen.right / 2 - diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 07cbd3b23..2d70f51ba 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -793,6 +793,12 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape : Layout::DisplayOrientation::Portrait; + bool separate_win = false; +#ifndef ANDROID + separate_win = + (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); +#endif + switch (Settings::values.render_3d.GetValue()) { case Settings::StereoRenderOption::Off: { DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, @@ -801,12 +807,17 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, } case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides case Settings::StereoRenderOption::ReverseSideBySide: { - DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, - bottom_screen_width / 2, bottom_screen_height, orientation); - glUniform1i(uniform_layer, 1); - DrawSingleScreen( - screen_infos[2], static_cast((bottom_screen_left / 2) + (layout.width / 2)), - bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); + if (separate_win) { + DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, + bottom_screen_width, bottom_screen_height, orientation); + } else { + DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, + bottom_screen_width / 2, bottom_screen_height, orientation); + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[2], static_cast((bottom_screen_left / 2) + (layout.width / 2)), + bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); + } break; } case Settings::StereoRenderOption::CardboardVR: { diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6c95a22b7..fb5251892 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -1,4 +1,4 @@ -// Copyright Citra Emulator Project / Lime3DS Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -739,6 +739,12 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape : Layout::DisplayOrientation::Portrait; + bool separate_win = false; +#ifndef ANDROID + separate_win = + (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows); +#endif + switch (Settings::values.render_3d.GetValue()) { case Settings::StereoRenderOption::Off: { DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, @@ -747,12 +753,17 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, } case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides case Settings::StereoRenderOption::ReverseSideBySide: { - DrawSingleScreen(2, bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2, - bottom_screen_height, orientation); - draw_info.layer = 1; - DrawSingleScreen(2, static_cast((bottom_screen_left / 2) + (layout.width / 2)), - bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, - orientation); + if (separate_win) { + DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, + bottom_screen_height, orientation); + } else { + DrawSingleScreen(2, bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2, + bottom_screen_height, orientation); + draw_info.layer = 1; + DrawSingleScreen(2, static_cast((bottom_screen_left / 2) + (layout.width / 2)), + bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, + orientation); + } break; } case Settings::StereoRenderOption::CardboardVR: { @@ -767,8 +778,13 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, case Settings::StereoRenderOption::Anaglyph: case Settings::StereoRenderOption::Interlaced: case Settings::StereoRenderOption::ReverseInterlaced: { - DrawSingleScreenStereo(2, 2, bottom_screen_left, bottom_screen_top, bottom_screen_width, - bottom_screen_height, orientation); + if (separate_win) { + DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, + bottom_screen_height, orientation); + } else { + DrawSingleScreenStereo(2, 2, bottom_screen_left, bottom_screen_top, bottom_screen_width, + bottom_screen_height, orientation); + } break; } }