From 3154a5fac1b4ab84904f343b99158f9fac2d5354 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 7 Aug 2024 09:25:12 +0200 Subject: [PATCH] OpenXR - VR camera features on any platform --- Common/VR/PPSSPPVR.cpp | 22 +++++++---- Core/Config.cpp | 1 + Core/Config.h | 1 + GPU/Common/VertexShaderGenerator.cpp | 2 +- GPU/GLES/GPU_GLES.cpp | 3 +- GPU/GLES/ShaderManagerGLES.cpp | 2 +- UI/GameSettingsScreen.cpp | 58 +++++++++++++++++----------- UI/NativeApp.cpp | 4 +- 8 files changed, 59 insertions(+), 34 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index fe4f12086126..22f139d05d4e 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -648,7 +648,6 @@ bool StartVRRender() { fov.angleDown += vrView[eye].fov.angleDown / 2.0f; } float nearZ = 0.01f; - float fovHack = g_Config.fFieldOfViewPercentage / 200.0f; float tanAngleLeft = tanf(fov.angleLeft); float tanAngleRight = tanf(fov.angleRight); float tanAngleDown = tanf(fov.angleDown); @@ -659,7 +658,7 @@ bool StartVRRender() { M[8] = (tanAngleRight + tanAngleLeft) / (tanAngleRight - tanAngleLeft); M[9] = (tanAngleUp + tanAngleDown) / (tanAngleUp - tanAngleDown); M[10] = -1; - M[11] = -(fovHack + fovHack); + M[11] = -1; M[14] = -(nearZ + nearZ); if (g_Config.bEnableImmersiveVR) { M[0] /= 2.0f; @@ -724,6 +723,9 @@ bool IsFlatVRGame() { } bool IsFlatVRScene() { + if (g_Config.bForceVR && (!vrFlatForced || !g_Config.bManualForceVR)) { + return false; + } int vrMode = VR_GetConfig(VR_CONFIG_MODE); return (vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN); } @@ -804,7 +806,9 @@ void UpdateVRParams(float* projMatrix) { void UpdateVRProjection(float* projMatrix, float* output) { for (int i = 0; i < 16; i++) { - if (PSP_CoreParameter().compat.vrCompat().ProjectionHack && ((i == 8) || (i == 9))) { + if (!IsVREnabled()) { + output[i] = projMatrix[i]; + } else if (PSP_CoreParameter().compat.vrCompat().ProjectionHack && ((i == 8) || (i == 9))) { output[i] = 0; } else if (fabs(projMatrix[i]) > 0) { output[i] = vrMatrix[VR_PROJECTION_MATRIX][i]; @@ -815,6 +819,7 @@ void UpdateVRProjection(float* projMatrix, float* output) { output[i] = 0; } } + output[11] *= g_Config.fFieldOfViewPercentage / 100.0f; } void UpdateVRView(float* leftEye, float* rightEye) { @@ -850,8 +855,11 @@ void UpdateVRViewMatrices() { } // Get input + XrPosef invView = XrPosef_Identity(); + if (IsVREnabled()) { + invView = vrView[0].pose; + } bool flatScreen = false; - XrPosef invView = vrView[0].pose; int vrMode = VR_GetConfig(VR_CONFIG_MODE); if ((vrMode == VR_MODE_MONO_SCREEN) || (vrMode == VR_MODE_STEREO_SCREEN)) { invView = XrPosef_Identity(); @@ -895,7 +903,7 @@ void UpdateVRViewMatrices() { XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mRoll); invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw)); if (!VR_GetConfig(VR_CONFIG_REPROJECTION)) { - float axis = vrMirroring[VR_MIRRORING_PITCH] ? -1.0f : 1.0f; + float axis = vrMirroring[VR_MIRRORING_PITCH] ? -1.0f : 1.0f; invView.orientation = XrQuaternionf_CreateFromVectorAngle({axis, 0, 0}, ToRadians(g_Config.fCameraPitch)); } @@ -903,7 +911,7 @@ void UpdateVRViewMatrices() { XrQuaternionf_ToMatrix4f(&invView.orientation, M); // Apply 6Dof head movement - if (g_Config.bEnable6DoF && !g_Config.bHeadRotationEnabled) { + if (g_Config.bEnable6DoF && !g_Config.bHeadRotationEnabled && IsVREnabled()) { M[3] -= vrView[0].pose.position.x * (vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f) * scale; M[7] -= vrView[0].pose.position.y * (vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f) * scale; M[11] -= vrView[0].pose.position.z * (vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f) * scale; @@ -940,7 +948,7 @@ void UpdateVRViewMatrices() { // Stereoscopy bool vrStereo = !PSP_CoreParameter().compat.vrCompat().ForceMono && g_Config.bEnableStereo; - if (vrStereo) { + if (vrStereo && IsVREnabled()) { bool mirrored = vrMirroring[VR_MIRRORING_AXIS_Z] ^ (matrix == VR_VIEW_MATRIX_RIGHT_EYE); float dx = fabs(vrView[1].pose.position.x - vrView[0].pose.position.x); float dy = fabs(vrView[1].pose.position.y - vrView[0].pose.position.y); diff --git a/Core/Config.cpp b/Core/Config.cpp index 72c0ea17b520..b17f741ee8ad 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -958,6 +958,7 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VREnableStereo", &g_Config.bEnableStereo, false, CfgFlag::PER_GAME), ConfigSetting("VREnableMotions", &g_Config.bEnableMotions, true, CfgFlag::PER_GAME), ConfigSetting("VRForce72Hz", &g_Config.bForce72Hz, true, CfgFlag::PER_GAME), + ConfigSetting("VRForce", &g_Config.bForceVR, false, CfgFlag::DEFAULT), ConfigSetting("VRImmersiveMode", &g_Config.bEnableImmersiveVR, true, CfgFlag::PER_GAME), ConfigSetting("VRManualForceVR", &g_Config.bManualForceVR, false, CfgFlag::PER_GAME), ConfigSetting("VRPassthrough", &g_Config.bPassthrough, false, CfgFlag::PER_GAME), diff --git a/Core/Config.h b/Core/Config.h index bb100ff88591..061647e08c24 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -484,6 +484,7 @@ struct Config { bool bEnableMotions; bool bEnableImmersiveVR; bool bForce72Hz; + bool bForceVR; bool bManualForceVR; bool bPassthrough; bool bRescaleHUD; diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 57a24718008e..84f9ab122afd 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -1307,7 +1307,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, " }\n"); } - if (vertexRangeCulling && !gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { + if (vertexRangeCulling) { WRITE(p, " vec3 projPos = outPos.xyz / outPos.w;\n"); WRITE(p, " float projZ = (projPos.z - u_depthRange.z) * u_depthRange.w;\n"); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 092bcf872d06..b70d429c1c62 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -169,8 +169,9 @@ u32 GPU_GLES::CheckGPUFeatures() const { if ((gl_extensions.IsGLES && !gl_extensions.GLES3) || (!gl_extensions.IsGLES && !gl_extensions.VersionGEThan(1, 3))) features &= ~GPU_USE_LIGHT_UBERSHADER; - if (IsVREnabled()) { + if (IsVREnabled() || g_Config.bForceVR) { features |= GPU_USE_VIRTUAL_REALITY; + features &= ~GPU_USE_VS_RANGE_CULLING; } if (!gl_extensions.GLES3) { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 71fbf31a7536..e4c7993fc153 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -482,7 +482,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin } if (dirty & DIRTY_FOGCOLOR) { SetColorUniform3(render_, &u_fogcolor, gstate.fogcolor); - if (IsVREnabled()) { + if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) { SetVRCompat(VR_COMPAT_FOG_COLOR, gstate.fogcolor); } } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index e70b5f4d4462..fa53d70b50be 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -254,7 +254,7 @@ void GameSettingsScreen::CreateTabs() { CreateSystemSettings(systemSettings); int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); - if (deviceType == DEVICE_TYPE_VR) { + if ((deviceType == DEVICE_TYPE_VR) || g_Config.bForceVR) { LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR")); CreateVRSettings(vrSettings); } @@ -617,7 +617,7 @@ void GameSettingsScreen::CreateAudioSettings(UI::ViewGroup *audioSettings) { auto ms = GetI18NCategory(I18NCat::MAINSETTINGS); audioSettings->Add(new ItemHeader(ms->T("Audio"))); - CheckBox *enableSound = audioSettings->Add(new CheckBox(&g_Config.bEnableSound,a->T("Enable Sound"))); + CheckBox *enableSound = audioSettings->Add(new CheckBox(&g_Config.bEnableSound,a->T("Enable Sound"))); #if PPSSPP_PLATFORM(IOS) CheckBox *respectSilentMode = audioSettings->Add(new CheckBox(&g_Config.bAudioRespectSilentMode, a->T("Respect silent mode"))); @@ -1280,35 +1280,42 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { using namespace UI; auto vr = GetI18NCategory(I18NCat::VR); + int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); - vrSettings->Add(new ItemHeader(vr->T("Virtual reality"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality"))); - vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)"))); - vrSettings->Add(new CheckBox(&g_Config.bEnableImmersiveVR, vr->T("Enable immersive mode"))); - if (IsPassthroughSupported()) { - vrSettings->Add(new CheckBox(&g_Config.bPassthrough, vr->T("Enable passthrough"))); + if (deviceType == DEVICE_TYPE_VR) { + vrSettings->Add(new ItemHeader(vr->T("Virtual reality"))); + vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality"))); + vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement"))); + vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)"))); + vrSettings->Add(new CheckBox(&g_Config.bEnableImmersiveVR, vr->T("Enable immersive mode"))); + if (IsPassthroughSupported()) { + vrSettings->Add(new CheckBox(&g_Config.bPassthrough, vr->T("Enable passthrough"))); + } + vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update"))); } - vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update"))); vrSettings->Add(new ItemHeader(vr->T("VR camera"))); - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); + if (deviceType == DEVICE_TYPE_VR) { + vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); + vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); + } vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, 100.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV"))); vrSettings->Add(new CheckBox(&g_Config.bRescaleHUD, vr->T("Heads-up display detection"))); PopupSliderChoiceFloat* vrHudScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, 0.3f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); vrHudScale->SetEnabledPtr(&g_Config.bRescaleHUD); vrSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); - vrSettings->Add(new ItemHeader(vr->T("Experts only"))); - vrSettings->Add(new CheckBox(&g_Config.bHeadRotationEnabled, vr->T("Map HMD rotations on keys instead of VR camera"))); - PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, 5.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°")); - vrHeadRotationScale->SetEnabledPtr(&g_Config.bHeadRotationEnabled); - CheckBox *vrHeadRotationSmoothing = vrSettings->Add(new CheckBox(&g_Config.bHeadRotationSmoothing, vr->T("Game camera uses rotation smoothing"))); - vrHeadRotationSmoothing->SetEnabledPtr(&g_Config.bHeadRotationEnabled); - vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys"))); - PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, 0.5f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m"))); - vrMotions->SetEnabledPtr(&g_Config.bEnableMotions); + if (deviceType == DEVICE_TYPE_VR) { + vrSettings->Add(new ItemHeader(vr->T("Experts only"))); + vrSettings->Add(new CheckBox(&g_Config.bHeadRotationEnabled, vr->T("Map HMD rotations on keys instead of VR camera"))); + PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, 5.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°")); + vrHeadRotationScale->SetEnabledPtr(&g_Config.bHeadRotationEnabled); + CheckBox *vrHeadRotationSmoothing = vrSettings->Add(new CheckBox(&g_Config.bHeadRotationSmoothing, vr->T("Game camera uses rotation smoothing"))); + vrHeadRotationSmoothing->SetEnabledPtr(&g_Config.bHeadRotationEnabled); + vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys"))); + PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, 0.5f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m"))); + vrMotions->SetEnabledPtr(&g_Config.bEnableMotions); + } } UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) { @@ -1907,6 +1914,13 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new CheckBox(&g_Config.bUberShaderFragment, dev->T("Fragment"))); } + // Experimental, allow some VR features without OpenXR + if (GetGPUBackend() == GPUBackend::OPENGL) { + auto vr = GetI18NCategory(I18NCat::VR); + list->Add(new ItemHeader(gr->T("Virtual reality"))); + list->Add(new CheckBox(&g_Config.bForceVR, vr->T("VR camera"))); + } + // Experimental, will move to main graphics settings later. bool multiViewSupported = draw->GetDeviceCaps().multiViewSupported; @@ -2223,7 +2237,7 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) { UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) { auto n = GetI18NCategory(I18NCat::NETWORKING); System_InputBoxGetString(GetRequesterToken(), n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) { - addrView_->SetText(value); + addrView_->SetText(value); }); return UI::EVENT_DONE; } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 0c379ee373f9..89dbef915ffd 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1322,7 +1322,7 @@ bool NativeKey(const KeyInput &key) { double now = time_now_d(); // VR actions - if (IsVREnabled() && !UpdateVRKeys(key)) { + if ((IsVREnabled() || g_Config.bForceVR) && !UpdateVRKeys(key)) { return false; } @@ -1372,7 +1372,7 @@ bool NativeKey(const KeyInput &key) { void NativeAxis(const AxisInput *axes, size_t count) { // VR actions - if (IsVREnabled() && !UpdateVRAxis(axes, count)) { + if ((IsVREnabled() || g_Config.bForceVR) && !UpdateVRAxis(axes, count)) { return; }