mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Add Cardboard VR
Based on hrydgard/ppsspp/pull/12449
This commit is contained in:
		
							parent
							
								
									da3a9bfc96
								
							
						
					
					
						commit
						60235827c5
					
				
					 5 changed files with 174 additions and 6 deletions
				
			
		|  | @ -73,6 +73,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | ||||||
|                   framebuffer_x < layout.bottom_screen.right / 2) || |                   framebuffer_x < layout.bottom_screen.right / 2) || | ||||||
|                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && |                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && | ||||||
|                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); |                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); | ||||||
|  |     } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|  |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|  |                 ((framebuffer_x >= layout.bottom_screen.left && | ||||||
|  |                   framebuffer_x < layout.bottom_screen.right) || | ||||||
|  |                  (framebuffer_x >= layout.cardboard.bottom_screen_right_eye + (layout.width / 2) && | ||||||
|  |                   framebuffer_x < layout.cardboard.bottom_screen_right_eye + | ||||||
|  |                                       layout.bottom_screen.GetWidth() + (layout.width / 2)))); | ||||||
|     } else { |     } else { | ||||||
|         return (framebuffer_y >= layout.bottom_screen.top && |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|                 framebuffer_y < layout.bottom_screen.bottom && |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|  | @ -82,9 +90,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (new_x >= framebuffer_layout.width / 2) { | ||||||
|         if (new_x >= framebuffer_layout.width / 2) |         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||||
|             new_x -= framebuffer_layout.width / 2; |             new_x -= framebuffer_layout.width / 2; | ||||||
|  |         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||||
|  |             new_x -= | ||||||
|  |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|  |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||||
|         new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); |         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); |         new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); | ||||||
|     } else { |     } else { | ||||||
|  | @ -102,9 +115,13 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | ||||||
|     if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) |     if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide && |     if (framebuffer_x >= framebuffer_layout.width / 2) { | ||||||
|         framebuffer_x >= framebuffer_layout.width / 2) |         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||||
|         framebuffer_x -= framebuffer_layout.width / 2; |             framebuffer_x -= framebuffer_layout.width / 2; | ||||||
|  |         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||||
|  |             framebuffer_x -= | ||||||
|  |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|  |     } | ||||||
|     std::lock_guard guard(touch_state->mutex); |     std::lock_guard guard(touch_state->mutex); | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||||
|         touch_state->touch_x = |         touch_state->touch_x = | ||||||
|  | @ -191,6 +208,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | ||||||
|         } |         } | ||||||
|         UpdateMinimumWindowSize(min_size); |         UpdateMinimumWindowSize(min_size); | ||||||
|     } |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         layout = Layout::GetCardboardSettings(layout); | ||||||
|  |     } | ||||||
|     NotifyFramebufferLayoutChanged(layout); |     NotifyFramebufferLayoutChanged(layout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -452,9 +452,92 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         layout = Layout::GetCardboardSettings(layout); | ||||||
|  |     } | ||||||
|     return layout; |     return layout; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | ||||||
|  |     FramebufferLayout newLayout = layout; | ||||||
|  |     float top_screen_left = 0; | ||||||
|  |     float top_screen_top = 0; | ||||||
|  |     float bottom_screen_left = 0; | ||||||
|  |     float bottom_screen_top = 0; | ||||||
|  | 
 | ||||||
|  |     float cardboardScreenScale = Settings::values.cardboard_screen_size / 100.0f; | ||||||
|  |     float top_screen_width = layout.top_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|  |     float top_screen_height = layout.top_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|  |     float bottom_screen_width = layout.bottom_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|  |     float bottom_screen_height = layout.bottom_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|  |     bool is_swapped = Settings::values.swap_screen; | ||||||
|  |     bool is_portrait = layout.height > layout.width; | ||||||
|  | 
 | ||||||
|  |     float cardboardScreenWidth; | ||||||
|  |     float cardboardScreenHeight; | ||||||
|  |     switch (Settings::values.layout_option) { | ||||||
|  |     case Settings::LayoutOption::MobileLandscape: | ||||||
|  |     case Settings::LayoutOption::SideScreen: | ||||||
|  |         // If orientation is portrait, only use MobilePortrait
 | ||||||
|  |         if (!is_portrait) { | ||||||
|  |             cardboardScreenWidth = top_screen_width + bottom_screen_width; | ||||||
|  |             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||||
|  |             if (is_swapped) | ||||||
|  |                 top_screen_left += bottom_screen_width; | ||||||
|  |             else | ||||||
|  |                 bottom_screen_left += top_screen_width; | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             [[fallthrough]]; | ||||||
|  |         } | ||||||
|  |     case Settings::LayoutOption::SingleScreen: | ||||||
|  |     default: | ||||||
|  |         if (!is_portrait) { | ||||||
|  |             // Default values when using LayoutOption::SingleScreen
 | ||||||
|  |             cardboardScreenWidth = is_swapped ? bottom_screen_width : top_screen_width; | ||||||
|  |             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             [[fallthrough]]; | ||||||
|  |         } | ||||||
|  |     case Settings::LayoutOption::MobilePortrait: | ||||||
|  |         cardboardScreenWidth = top_screen_width; | ||||||
|  |         cardboardScreenHeight = top_screen_height + bottom_screen_height; | ||||||
|  |         bottom_screen_left += (top_screen_width - bottom_screen_width) / 2.0f; | ||||||
|  |         if (is_swapped) | ||||||
|  |             top_screen_top += bottom_screen_height; | ||||||
|  |         else | ||||||
|  |             bottom_screen_top += top_screen_height; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     float cardboardMaxXShift = (layout.width / 2.0f - cardboardScreenWidth) / 2.0f; | ||||||
|  |     float cardboardUserXShift = (Settings::values.cardboard_x_shift / 100.0f) * cardboardMaxXShift; | ||||||
|  |     float cardboardMaxYShift = ((float)layout.height - cardboardScreenHeight) / 2.0f; | ||||||
|  |     float cardboardUserYShift = (Settings::values.cardboard_y_shift / 100.0f) * cardboardMaxYShift; | ||||||
|  | 
 | ||||||
|  |     // Center the screens and apply user Y shift
 | ||||||
|  |     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; | ||||||
|  |     newLayout.top_screen.top = top_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||||
|  |     newLayout.bottom_screen.left = bottom_screen_left + cardboardMaxXShift; | ||||||
|  |     newLayout.bottom_screen.top = bottom_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||||
|  | 
 | ||||||
|  |     // Set the X coordinates for the right eye and apply user X shift
 | ||||||
|  |     newLayout.cardboard.top_screen_right_eye = newLayout.top_screen.left - cardboardUserXShift; | ||||||
|  |     newLayout.top_screen.left += cardboardUserXShift; | ||||||
|  |     newLayout.cardboard.bottom_screen_right_eye = | ||||||
|  |         newLayout.bottom_screen.left - cardboardUserXShift; | ||||||
|  |     newLayout.bottom_screen.left += cardboardUserXShift; | ||||||
|  |     newLayout.cardboard.user_x_shift = cardboardUserXShift; | ||||||
|  | 
 | ||||||
|  |     // Update right/bottom instead of passing new variables for width/height
 | ||||||
|  |     newLayout.top_screen.right = newLayout.top_screen.left + top_screen_width; | ||||||
|  |     newLayout.top_screen.bottom = newLayout.top_screen.top + top_screen_height; | ||||||
|  |     newLayout.bottom_screen.right = newLayout.bottom_screen.left + bottom_screen_width; | ||||||
|  |     newLayout.bottom_screen.bottom = newLayout.bottom_screen.top + bottom_screen_height; | ||||||
|  | 
 | ||||||
|  |     return newLayout; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||||
|                                                        bool upright_screen) { |                                                        bool upright_screen) { | ||||||
|     unsigned min_width, min_height; |     unsigned min_width, min_height; | ||||||
|  |  | ||||||
|  | @ -9,6 +9,13 @@ | ||||||
| 
 | 
 | ||||||
| namespace Layout { | namespace Layout { | ||||||
| 
 | 
 | ||||||
|  | /// Describes the horizontal coordinates for the right eye screen when using Cardboard VR
 | ||||||
|  | struct CardboardSettings { | ||||||
|  |     float top_screen_right_eye; | ||||||
|  |     float bottom_screen_right_eye; | ||||||
|  |     float user_x_shift; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /// Describes the layout of the window framebuffer (size and top/bottom screen positions)
 | /// Describes the layout of the window framebuffer (size and top/bottom screen positions)
 | ||||||
| struct FramebufferLayout { | struct FramebufferLayout { | ||||||
|     u32 width; |     u32 width; | ||||||
|  | @ -19,6 +26,8 @@ struct FramebufferLayout { | ||||||
|     Common::Rectangle<u32> bottom_screen; |     Common::Rectangle<u32> bottom_screen; | ||||||
|     bool is_rotated = true; |     bool is_rotated = true; | ||||||
| 
 | 
 | ||||||
|  |     CardboardSettings cardboard; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS |      * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS | ||||||
|      * screen. |      * screen. | ||||||
|  | @ -104,6 +113,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height); | ||||||
|  */ |  */ | ||||||
| FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Convenience method for transforming a frame layout when using Cardboard VR | ||||||
|  |  * @param layout frame layout to transform | ||||||
|  |  * @return layout transformed with the user cardboard settings | ||||||
|  |  */ | ||||||
|  | FramebufferLayout GetCardboardSettings(FramebufferLayout layout); | ||||||
|  | 
 | ||||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||||
|                                                        bool upright_screen); |                                                        bool upright_screen); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,7 +40,14 @@ enum class MicInputType { | ||||||
|     Static, |     Static, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class StereoRenderOption { Off, SideBySide, Anaglyph, Interlaced, ReverseInterlaced }; | enum class StereoRenderOption { | ||||||
|  |     Off, | ||||||
|  |     SideBySide, | ||||||
|  |     Anaglyph, | ||||||
|  |     Interlaced, | ||||||
|  |     ReverseInterlaced, | ||||||
|  |     CardboardVR | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| namespace NativeButton { | namespace NativeButton { | ||||||
| enum Values { | enum Values { | ||||||
|  | @ -190,6 +197,10 @@ struct Values { | ||||||
|     StereoRenderOption render_3d; |     StereoRenderOption render_3d; | ||||||
|     std::atomic<u8> factor_3d; |     std::atomic<u8> factor_3d; | ||||||
| 
 | 
 | ||||||
|  |     int cardboard_screen_size; | ||||||
|  |     int cardboard_x_shift; | ||||||
|  |     int cardboard_y_shift; | ||||||
|  | 
 | ||||||
|     bool filter_mode; |     bool filter_mode; | ||||||
|     std::string pp_shader_name; |     std::string pp_shader_name; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1016,6 +1016,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                         ((float)top_screen.left / 2) + ((float)layout.width / 2), |                                         ((float)top_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, |                                         (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||||
|                                         (float)top_screen.GetHeight()); |                                         (float)top_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |                 DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, | ||||||
|  |                                         layout.top_screen.top, layout.top_screen.GetWidth(), | ||||||
|  |                                         layout.top_screen.GetHeight()); | ||||||
|  |                 glUniform1i(uniform_layer, 1); | ||||||
|  |                 DrawSingleScreenRotated(screen_infos[1], | ||||||
|  |                                         layout.cardboard.top_screen_right_eye + | ||||||
|  |                                             ((float)layout.width / 2), | ||||||
|  |                                         layout.top_screen.top, layout.top_screen.GetWidth(), | ||||||
|  |                                         layout.top_screen.GetHeight()); | ||||||
|             } else if (stereo_single_screen) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereoRotated( |                 DrawSingleScreenStereoRotated( | ||||||
|                     screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, |                     screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, | ||||||
|  | @ -1033,6 +1043,14 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((float)top_screen.left / 2) + ((float)layout.width / 2), |                                  ((float)top_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                  (float)top_screen.top, (float)top_screen.GetWidth() / 2, |                                  (float)top_screen.top, (float)top_screen.GetWidth() / 2, | ||||||
|                                  (float)top_screen.GetHeight()); |                                  (float)top_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |                 DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, | ||||||
|  |                                  layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); | ||||||
|  |                 glUniform1i(uniform_layer, 1); | ||||||
|  |                 DrawSingleScreen(screen_infos[1], | ||||||
|  |                                  layout.cardboard.top_screen_right_eye + ((float)layout.width / 2), | ||||||
|  |                                  layout.top_screen.top, layout.top_screen.GetWidth(), | ||||||
|  |                                  layout.top_screen.GetHeight()); | ||||||
|             } else if (stereo_single_screen) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, |                 DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, | ||||||
|                                        (float)top_screen.top, (float)top_screen.GetWidth(), |                                        (float)top_screen.top, (float)top_screen.GetWidth(), | ||||||
|  | @ -1056,6 +1074,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                     (float)bottom_screen.GetHeight()); |                     (float)bottom_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |                 DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, | ||||||
|  |                                         layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|  |                                         layout.bottom_screen.GetHeight()); | ||||||
|  |                 glUniform1i(uniform_layer, 1); | ||||||
|  |                 DrawSingleScreenRotated(screen_infos[2], | ||||||
|  |                                         layout.cardboard.bottom_screen_right_eye + | ||||||
|  |                                             ((float)layout.width / 2), | ||||||
|  |                                         layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|  |                                         layout.bottom_screen.GetHeight()); | ||||||
|             } else if (stereo_single_screen) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], |                 DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], | ||||||
|                                               (float)bottom_screen.left, (float)bottom_screen.top, |                                               (float)bottom_screen.left, (float)bottom_screen.top, | ||||||
|  | @ -1076,6 +1104,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                                  (float)bottom_screen.GetHeight()); |                                  (float)bottom_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |                 DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, | ||||||
|  |                                  layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|  |                                  layout.bottom_screen.GetHeight()); | ||||||
|  |                 glUniform1i(uniform_layer, 1); | ||||||
|  |                 DrawSingleScreen(screen_infos[2], | ||||||
|  |                                  layout.cardboard.bottom_screen_right_eye + | ||||||
|  |                                      ((float)layout.width / 2), | ||||||
|  |                                  layout.bottom_screen.top, layout.bottom_screen.GetWidth(), | ||||||
|  |                                  layout.bottom_screen.GetHeight()); | ||||||
|             } else if (stereo_single_screen) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, |                 DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, | ||||||
|                                        (float)bottom_screen.top, (float)bottom_screen.GetWidth(), |                                        (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue