From a48105792af48490f76eeb6e22ffd682fdbcb404 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 5 Feb 2026 23:29:03 +0000 Subject: [PATCH] Unify flat screen/overlay rendering through OverlayComponent Move all overlay quad generation logic into OverlayComponent so both OpenXR and OpenVR runtimes use a single code path for flat screen display. - Add generate_slate_quad() to OverlayComponent::OpenXR for flat screen game display, replacing the inline quad code in OpenXR::end_frame() - Add update_slate_openvr() for OpenVR flat screen overlay support using the existing m_slate_overlay_handle - Wire D3D11/D3D12 components to pass slate quad layers from OverlayComponent - Remove OpenVR early-return from showFlatScreenDisplay() to enable support - Remove m_flat_screen_distance from VRRuntime and VR module (now owned by OverlayComponent's m_slate_distance with full UI controls) - Restore slate overlay UI controls (distance, size, XY offset, follows view) and re-enable wrist UI option for OpenVR https://claude.ai/code/session_01Ae7bwDrEvmhydD5MPCRKin --- src/ModSettings.cpp | 7 - src/mods/VR.cpp | 7 - src/mods/VR.hpp | 1 - src/mods/vr/D3D11Component.cpp | 7 + src/mods/vr/D3D12Component.cpp | 8 + src/mods/vr/OverlayComponent.cpp | 331 +++++++++++++++++++---------- src/mods/vr/OverlayComponent.hpp | 4 +- src/mods/vr/runtimes/OpenXR.cpp | 44 +--- src/mods/vr/runtimes/VRRuntime.hpp | 1 - 9 files changed, 240 insertions(+), 170 deletions(-) diff --git a/src/ModSettings.cpp b/src/ModSettings.cpp index ab7eebe..240e793 100644 --- a/src/ModSettings.cpp +++ b/src/ModSettings.cpp @@ -1,17 +1,10 @@ #include "ModSettings.h" -#include "mods/VR.hpp" - namespace ModSettings { InternalSettings g_internalSettings; bool showFlatScreenDisplay() { - static auto vr = VR::get(); - //TODO fix for openvr - if (vr->is_hmd_active() && vr->get_runtime()->is_openvr()) { - return false; - } return g_internalSettings.forceFlatScreen || g_internalSettings.showQuadDisplay; } } diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index 82f5dac..797b07c 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -1172,12 +1172,6 @@ void VR::on_draw_ui() { m_openxr->resolution_scale = m_resolution_scale->value(); } - m_flat_screen_distance->draw("Flat Screen Distance"); - if (ImGui::IsItemDeactivatedAfterEdit()) - { - get_runtime()->m_flat_screen_distance = m_flat_screen_distance->value(); - } - m_horizontal_fov_scale->draw("Horizontal FOV Scale"); if (ImGui::IsItemDeactivatedAfterEdit()) { get_runtime()->m_horizontal_fov_scale = m_horizontal_fov_scale->value(); @@ -1316,7 +1310,6 @@ void VR::on_config_load(const utility::Config& cfg, bool set_defaults) { get_runtime()->m_horizontal_fov_scale = m_horizontal_fov_scale->value(); get_runtime()->m_vertical_fov_scale = m_vertical_fov_scale->value(); get_runtime()->m_extended_fov_range = m_extended_fov_rage->value(); - get_runtime()->m_flat_screen_distance = m_flat_screen_distance->value(); } m_overlay_component.on_config_load(cfg, set_defaults); diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index f70a4df..c941d56 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -619,7 +619,6 @@ class VR : public Mod { const ModSlider::Ptr m_horizontal_fov_scale{ ModSlider::create(generate_name("HorizontalFOVScale"), 0.0f, 1.0f, 1.0f) }; const ModSlider::Ptr m_vertical_fov_scale{ ModSlider::create(generate_name("VerticalFOVScale"), 0.0f, 1.0f, 1.0f) }; const ModToggle::Ptr m_extended_fov_rage{ ModToggle::create(generate_name("ExtendedScaleFovRange"), false) }; - const ModSlider::Ptr m_flat_screen_distance{ ModSlider::create(generate_name("FlatSCreenDistance"), 0.0f, 2.0f, 1.5f) }; const ModToggle::Ptr m_force_fps_settings{ ModToggle::create(generate_name("ForceFPS"), true) }; const ModToggle::Ptr m_force_aa_settings{ ModToggle::create(generate_name("ForceAntiAliasing"), true) }; diff --git a/src/mods/vr/D3D11Component.cpp b/src/mods/vr/D3D11Component.cpp index bbbee7d..de2431f 100644 --- a/src/mods/vr/D3D11Component.cpp +++ b/src/mods/vr/D3D11Component.cpp @@ -437,6 +437,13 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) { auto& openxr_overlay = vr->get_overlay_component().get_openxr(); + if (ModSettings::showFlatScreenDisplay()) { + const auto slate_quad = openxr_overlay.generate_slate_quad(); + if (slate_quad) { + quad_layers.push_back((XrCompositionLayerBaseHeader*)&slate_quad->get()); + } + } + if (m_openxr.ever_acquired((uint32_t)runtimes::OpenXR::SwapchainIndex::FRAMEWORK_UI)) { const auto framework_quad = openxr_overlay.generate_framework_ui_quad(); diff --git a/src/mods/vr/D3D12Component.cpp b/src/mods/vr/D3D12Component.cpp index 5ec7dea..134c473 100644 --- a/src/mods/vr/D3D12Component.cpp +++ b/src/mods/vr/D3D12Component.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "mods/VR.hpp" @@ -234,6 +235,13 @@ vr::EVRCompositorError D3D12Component::on_frame(VR* vr) { auto& openxr_overlay = vr->get_overlay_component().get_openxr(); + if (ModSettings::showFlatScreenDisplay()) { + const auto slate_quad = openxr_overlay.generate_slate_quad(); + if (slate_quad) { + quad_layers.push_back((XrCompositionLayerBaseHeader*)&slate_quad->get()); + } + } + if (m_openxr.ever_acquired((uint32_t)runtimes::OpenXR::SwapchainIndex::FRAMEWORK_UI)) { const auto framework_quad = openxr_overlay.generate_framework_ui_quad(); if (framework_quad) { diff --git a/src/mods/vr/OverlayComponent.cpp b/src/mods/vr/OverlayComponent.cpp index ce41a84..eef933a 100644 --- a/src/mods/vr/OverlayComponent.cpp +++ b/src/mods/vr/OverlayComponent.cpp @@ -3,6 +3,7 @@ #include "../VR.hpp" #include "Framework.hpp" +#include "ModSettings.h" #include "utility/ImGui.hpp" #include "OverlayComponent.hpp" @@ -175,7 +176,7 @@ void OverlayComponent::update_input_mouse_emulation() { void OverlayComponent::on_post_compositor_submit() { this->update_overlay_openvr(); -// this->update_slate_openvr(); + this->update_slate_openvr(); } @@ -194,36 +195,36 @@ void OverlayComponent::on_config_load(const utility::Config& cfg, bool set_defau void OverlayComponent::on_draw_ui() { ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::TreeNode("Overlay Options")) { -// if (VR::get()->get_runtime()->is_cylinder_layer_allowed()) { -// m_slate_overlay_type->draw("Overlay Type"); -// -// if ((OverlayType)m_slate_overlay_type->value() == OverlayType::CYLINDER) { -// m_slate_cylinder_angle->draw("UI Cylinder Angle"); -// } -// } -// -// float ui_offset[] { m_slate_x_offset->value(), m_slate_y_offset->value(), m_slate_distance->value() }; -// -// if (ImGui::SliderFloat3("UI Offset", ui_offset, -10.0f, 10.0f)) { -// m_slate_x_offset->value() = ui_offset[0]; -// m_slate_y_offset->value() = ui_offset[1]; -// m_slate_distance->value() = ui_offset[2]; -// } - -// m_slate_distance->draw("UI Distance"); -// m_slate_size->draw("UI Size"); -// m_ui_follows_view->draw("UI Follows View"); -// ImGui::SameLine(); -// m_ui_invert_alpha->draw("UI Invert Alpha"); - - m_framework_distance->draw("Framework Distance"); - m_framework_size->draw("Framework Size"); - m_framework_ui_follows_view->draw("Framework Follows View"); -// if (VR::get()->get_runtime()->is_openvr()) { -// ImGui::SameLine(); -// m_framework_wrist_ui->draw("Framework Wrist UI"); -// } - m_framework_mouse_emulation->draw("Framework Mouse Emulation"); + if (ModSettings::showFlatScreenDisplay()) { + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode("Flat Screen Display")) { + m_slate_distance->draw("Distance"); + m_slate_size->draw("Size"); + + float ui_offset[]{m_slate_x_offset->value(), m_slate_y_offset->value()}; + if (ImGui::SliderFloat2("XY Offset", ui_offset, -10.0f, 10.0f)) { + m_slate_x_offset->value() = ui_offset[0]; + m_slate_y_offset->value() = ui_offset[1]; + } + + m_ui_follows_view->draw("Follows View"); + ImGui::TreePop(); + } + } + + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode("Framework UI")) { + m_framework_distance->draw("Distance"); + m_framework_size->draw("Size"); + m_framework_ui_follows_view->draw("Follows View"); + if (VR::get()->get_runtime()->is_openvr()) { + ImGui::SameLine(); + m_framework_wrist_ui->draw("Wrist UI"); + } + m_framework_mouse_emulation->draw("Mouse Emulation"); + ImGui::TreePop(); + } + ImGui::TreePop(); } } @@ -305,89 +306,107 @@ void OverlayComponent::update_input_openvr() { } } -//void OverlayComponent::update_slate_openvr() { -// auto vr = VR::get(); -// -// if (!vr->get_runtime()->is_openvr()) { -// return; -// } -// -// if (!vr->is_gui_enabled()) { -// vr::VROverlay()->ClearOverlayTexture(m_slate_overlay_handle); -// return; -// } -// -// const auto is_d3d11 = g_framework->get_renderer_type() == GOWVR::RendererType::D3D11; -// -// // TODO: do the sizing / scaling calculations below need to take into account non-standard VRTextureBounds_t -// // when we force a symmetrical eye projection matrix? -// vr::VRTextureBounds_t bounds{}; -// bounds.uMin = 0.0f; -// bounds.uMax = 1.0f; -// bounds.vMin = 0.0f; -// bounds.vMax = 1.0f; -// -// vr::VROverlay()->SetOverlayTextureBounds(m_slate_overlay_handle, &bounds); -// -// vr::TrackedDevicePose_t pose{}; -// vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, &pose, 1); -// -// auto rotation_offset = glm::inverse(vr->get_rotation_offset()); -// -//// if (vr->is_decoupled_pitch_enabled() && vr->is_decoupled_pitch_ui_adjust_enabled()) { -//// const auto pre_flat_rotation = vr->get_pre_flattened_rotation(); -//// const auto pre_flat_pitch = utility::math::pitch_only(pre_flat_rotation); -//// -//// // Add the inverse of the pitch rotation to the rotation offset -//// rotation_offset = glm::normalize(glm::inverse(pre_flat_pitch * vr->get_rotation_offset())); -//// } -// -// //auto glm_matrix = glm::rowMajor4(Matrix4x4f{*(Matrix3x4f*)&pose.mDeviceToAbsoluteTracking}); -// auto glm_matrix = Matrix4x4f{rotation_offset}; -// if (m_ui_follows_view->value()) { -// const auto mat = glm::rowMajor4(Matrix4x4f{*(Matrix3x4f*)&pose.mDeviceToAbsoluteTracking}); -// glm_matrix = glm::extractMatrixRotation(mat); -// glm_matrix[3] += mat[3]; -// } else { -// glm_matrix[3] += vr->get_standing_origin(); -// } -// -// glm_matrix[3] -= glm_matrix[2] * m_slate_distance->value(); -// glm_matrix[3] += m_slate_x_offset->value() * glm_matrix[0]; -// glm_matrix[3] += m_slate_y_offset->value() * glm_matrix[1]; -// glm_matrix[3].w = 1.0f; -// -// const auto steamvr_matrix = Matrix3x4f{glm::rowMajor4(glm_matrix)}; -// vr::VROverlay()->SetOverlayTransformAbsolute(m_slate_overlay_handle, vr::TrackingUniverseStanding, (vr::HmdMatrix34_t*)&steamvr_matrix); -// -// const auto is_d3d12 = g_framework->get_renderer_type() == GOWVR::RendererType::D3D12; -// const auto size = is_d3d12 ? g_framework->get_d3d12_rt_size() : g_framework->get_d3d11_rt_size(); -// const auto aspect = size.x / size.y; -// const auto width_meters = m_slate_size->value() * aspect; -// vr::VROverlay()->SetOverlayWidthInMeters(m_slate_overlay_handle, width_meters); -// -// if (is_d3d11) { -// if (vr->m_d3d11.get_ui_tex().Get() == nullptr) { -// return; -// } -// -// vr::Texture_t ui_tex{(void*)vr->m_d3d11.get_ui_tex().Get(), vr::TextureType_DirectX, vr::ColorSpace_Auto}; -// vr::VROverlay()->SetOverlayTexture(m_slate_overlay_handle, &ui_tex); -// } else { -// if (vr->m_d3d12.get_openvr_ui_tex().texture.Get() == nullptr) { -// return; -// } -// -// vr::D3D12TextureData_t overlay_tex { -// vr->m_d3d12.get_openvr_ui_tex().texture.Get(), -// g_framework->get_d3d12_hook()->get_command_queue(), -// 0 -// }; -// -// vr::Texture_t ui_tex{(void*)&overlay_tex, vr::TextureType_DirectX12, vr::ColorSpace_Auto}; -// vr::VROverlay()->SetOverlayTexture(m_slate_overlay_handle, &ui_tex); -// } -//} +void OverlayComponent::update_slate_openvr() { + if (!VR::get()->get_runtime()->is_openvr()) { + return; + } + + if (!ModSettings::showFlatScreenDisplay()) { + vr::VROverlay()->ClearOverlayTexture(m_slate_overlay_handle); + vr::VROverlay()->HideOverlay(m_slate_overlay_handle); + return; + } + + auto& vr = VR::get(); + + vr::VROverlay()->ShowOverlay(m_slate_overlay_handle); + + vr::VRTextureBounds_t bounds{}; + bounds.uMin = 0.0f; + bounds.uMax = 1.0f; + bounds.vMin = 0.0f; + bounds.vMax = 1.0f; + vr::VROverlay()->SetOverlayTextureBounds(m_slate_overlay_handle, &bounds); + + auto glm_matrix = glm::inverse(vr->get_transform_offset()); + + if (m_ui_follows_view->value()) { + vr::TrackedDevicePose_t pose{}; + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, &pose, 1); + const auto mat = glm::rowMajor4(Matrix4x4f{*(Matrix3x4f*)&pose.mDeviceToAbsoluteTracking}); + glm_matrix = glm::extractMatrixRotation(mat); + glm_matrix[3] += mat[3]; + } + + glm_matrix[3] -= glm_matrix[2] * m_slate_distance->value(); + glm_matrix[3] += m_slate_x_offset->value() * glm_matrix[0]; + glm_matrix[3] += m_slate_y_offset->value() * glm_matrix[1]; + glm_matrix[3].w = 1.0f; + + const auto steamvr_matrix = Matrix3x4f{glm::rowMajor4(glm_matrix)}; + vr::VROverlay()->SetOverlayTransformAbsolute(m_slate_overlay_handle, vr::TrackingUniverseStanding, (vr::HmdMatrix34_t*)&steamvr_matrix); + + const auto is_d3d11 = g_framework->get_renderer_type() == Framework::RendererType::D3D11; + const auto is_d3d12 = g_framework->get_renderer_type() == Framework::RendererType::D3D12; + const auto size = is_d3d12 ? g_framework->get_d3d12_rt_size() : g_framework->get_d3d11_rt_size(); + const auto aspect = size.x / size.y; + const auto width_meters = m_slate_size->value() * aspect; + vr::VROverlay()->SetOverlayWidthInMeters(m_slate_overlay_handle, width_meters); + + if (is_d3d11) { + vr::Texture_t slate_tex{(void*)g_framework->get_rendertarget_d3d11().Get(), vr::TextureType_DirectX, vr::ColorSpace_Auto}; + vr::VROverlay()->SetOverlayTexture(m_slate_overlay_handle, &slate_tex); + } else if (is_d3d12) { + auto& hook = g_framework->get_d3d12_hook(); + + vr::D3D12TextureData_t texture_data{ + g_framework->get_rendertarget_d3d12().Get(), + hook->get_command_queue(), + 0 + }; + + vr::Texture_t slate_tex{(void*)&texture_data, vr::TextureType_DirectX12, vr::ColorSpace_Auto}; + vr::VROverlay()->SetOverlayTexture(m_slate_overlay_handle, &slate_tex); + } + + if (vr->is_using_controllers()) { + const auto controller_index = !vr->m_swap_controllers->value() ? vr->get_right_controller_index() : vr->get_left_controller_index(); + const auto right_controller_rot = glm::quat{vr->get_rotation(controller_index)}; + const auto right_controller_pos = glm::vec3{vr->get_position(controller_index)}; + + const auto start = right_controller_pos; + auto fwd = (right_controller_rot * glm::vec3{0.0f, 0.0f, -1.0f}); + + const auto plane_pos = glm::vec3{glm_matrix[3]}; + const auto height_meters = m_slate_size->value(); + + float intersection_distance = 0.0f; + + if (glm::intersectRayPlane(start, fwd, plane_pos, glm::normalize(glm::vec3{glm_matrix[2]}), intersection_distance)) { + const auto intersection_point = start + (fwd * intersection_distance); + const auto local_point = glm::inverse(glm_matrix) * glm::vec4{intersection_point, 1.0f}; + + const auto w_half = width_meters / 2.0f; + const auto h_half = height_meters / 2.0f; + + if (local_point.x >= -w_half && local_point.x <= w_half && local_point.y >= -h_half && local_point.y <= h_half) { + const auto x = (local_point.x + w_half) / width_meters; + const auto y = (height_meters - (local_point.y + h_half)) / height_meters; + + m_intersect_state.quad_intersection_point = {x, y}; + m_intersect_state.intersecting = true; + + const auto client_x = (int32_t)(size.x * x); + const auto client_y = (int32_t)(size.y * y); + m_intersect_state.swapchain_intersection_point = {client_x, client_y}; + } else { + m_intersect_state.intersecting = false; + } + } + } else { + m_intersect_state.intersecting = false; + } +} bool OverlayComponent::update_wrist_overlay_openvr() { if (!VR::get()->get_runtime()->is_openvr()) { @@ -883,4 +902,88 @@ std::optional> OverlayComponent:: return layer; } + +std::optional> OverlayComponent::OpenXR::generate_slate_quad() { + if (!ModSettings::showFlatScreenDisplay()) { + m_parent->m_intersect_state.intersecting = false; + return std::nullopt; + } + + auto& vr = VR::get(); + + auto& layer = this->m_slate_layer; + + const auto& swapchain = vr->m_openxr->swapchains[(uint32_t)runtimes::OpenXR::SwapchainIndex::AFR_LEFT_EYE]; + + layer.type = XR_TYPE_COMPOSITION_LAYER_QUAD; + layer.subImage.swapchain = swapchain.handle; + layer.subImage.imageRect.offset = {0, 0}; + layer.subImage.imageRect.extent = {swapchain.width, swapchain.height}; + layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; + layer.eyeVisibility = XrEyeVisibility::XR_EYE_VISIBILITY_BOTH; + + auto glm_matrix = glm::identity(); + + if (m_parent->m_ui_follows_view->value()) { + layer.space = vr->m_openxr->view_space; + } else { + glm_matrix = glm::inverse(vr->get_transform_offset()); + layer.space = vr->m_openxr->stage_space; + } + + const auto size_meters = m_parent->m_slate_size->value(); + const float aspect_ratio = (float)swapchain.width / (float)swapchain.height; + const auto meters_w = size_meters * aspect_ratio; + const auto meters_h = size_meters; + + layer.size = {meters_w, meters_h}; + + glm_matrix[3] -= glm_matrix[2] * m_parent->m_slate_distance->value(); + glm_matrix[3] += m_parent->m_slate_x_offset->value() * glm_matrix[0]; + glm_matrix[3] += m_parent->m_slate_y_offset->value() * glm_matrix[1]; + glm_matrix[3].w = 1.0f; + + layer.pose.orientation = runtimes::OpenXR::to_openxr(glm::quat_cast(glm_matrix)); + layer.pose.position = runtimes::OpenXR::to_openxr(glm_matrix[3]); + + if (vr->is_using_controllers()) { + const auto controller_index = !vr->m_swap_controllers->value() ? vr->get_right_controller_index() : vr->get_left_controller_index(); + const auto right_controller_rot = glm::quat{vr->get_rotation(controller_index)}; + const auto right_controller_pos = glm::vec3{vr->get_position(controller_index)}; + + const auto start = right_controller_pos; + auto fwd = (right_controller_rot * glm::vec3{0.0f, 0.0f, -1.0f}); + + const auto plane_pos = glm::vec3{glm_matrix[3]}; + + float intersection_distance = 0.0f; + if (glm::intersectRayPlane(start, fwd, plane_pos, glm::normalize(glm::vec3{glm_matrix[2]}), intersection_distance)) { + const auto intersection_point = start + (fwd * intersection_distance); + const auto local_point = glm::inverse(glm_matrix) * glm::vec4{intersection_point, 1.0f}; + + const auto w_half = meters_w / 2.0f; + const auto h_half = meters_h / 2.0f; + + if (local_point.x >= -w_half && local_point.x <= w_half && local_point.y >= -h_half && local_point.y <= h_half) { + const auto x = (local_point.x + w_half) / meters_w; + const auto y = (meters_h - (local_point.y + h_half)) / meters_h; + + m_parent->m_intersect_state.quad_intersection_point = {x, y}; + m_parent->m_intersect_state.intersecting = true; + + if (swapchain.handle) { + const auto client_x = (int32_t)((float)swapchain.width * x); + const auto client_y = (int32_t)((float)swapchain.height * y); + m_parent->m_intersect_state.swapchain_intersection_point = {client_x, client_y}; + } + } else { + m_parent->m_intersect_state.intersecting = false; + } + } + } else { + m_parent->m_intersect_state.intersecting = false; + } + + return layer; +} } \ No newline at end of file diff --git a/src/mods/vr/OverlayComponent.hpp b/src/mods/vr/OverlayComponent.hpp index 0da736c..52d508c 100644 --- a/src/mods/vr/OverlayComponent.hpp +++ b/src/mods/vr/OverlayComponent.hpp @@ -145,7 +145,8 @@ class OverlayComponent : public ModComponent { } std::optional> generate_framework_ui_quad(); - + std::optional> generate_slate_quad(); + private: XrCompositionLayerQuad m_slate_layer{}; XrCompositionLayerQuad m_slate_layer_right{}; @@ -161,5 +162,6 @@ class OverlayComponent : public ModComponent { void update_input_openvr(); void update_input_mouse_emulation(); void update_overlay_openvr(); + void update_slate_openvr(); bool update_wrist_overlay_openvr(); };} \ No newline at end of file diff --git a/src/mods/vr/runtimes/OpenXR.cpp b/src/mods/vr/runtimes/OpenXR.cpp index 7c29e1d..1121aac 100644 --- a/src/mods/vr/runtimes/OpenXR.cpp +++ b/src/mods/vr/runtimes/OpenXR.cpp @@ -1405,7 +1405,6 @@ XrResult OpenXR::end_frame(const std::vector& qua std::vector layers{}; std::vector projection_layer_views{}; - std::vector l_quad_layers{}; // we CANT push the layers every time, it cause some layer error @@ -1416,8 +1415,8 @@ XrResult OpenXR::end_frame(const std::vector& qua auto r_frame = frame % 2 == 0 ? frame - 1 : frame; if (current_pipeline->frame_state.shouldRender == XR_TRUE) { - projection_layer_views.resize(current_pipeline->stage_views.size(), {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW}); if (!ModSettings::showFlatScreenDisplay()) { + projection_layer_views.resize(current_pipeline->stage_views.size(), {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW}); for (auto i = 0; i < projection_layer_views.size(); ++i) { const auto& swapchain = this->swapchains[i]; int actual_frame = i == 0 ? l_frame : r_frame; @@ -1428,10 +1427,10 @@ XrResult OpenXR::end_frame(const std::vector& qua projection_layer_views[i].subImage.swapchain = swapchain.handle; int32_t offset_x = 0, offset_y = 0, extent_x = 0, extent_y = 0; int texture_area_width = swapchain.width; - + offset_x = (int32_t)(view_bounds[i][0] * (float)texture_area_width); extent_x = (int32_t)(view_bounds[i][1] * (float)texture_area_width) - offset_x; - + offset_y = (int32_t)(view_bounds[i][2] * (float)swapchain.height); extent_y = (int32_t)(view_bounds[i][3] * (float)swapchain.height) - offset_y; if(m_horizontal_fov_scale < 1.0f || m_vertical_fov_scale < 1.0f) { @@ -1443,48 +1442,15 @@ XrResult OpenXR::end_frame(const std::vector& qua projection_layer_views[i].subImage.imageRect.offset = {offset_x, offset_y}; projection_layer_views[i].subImage.imageRect.extent = {extent_x, extent_y}; } - } XrCompositionLayerProjection layer{XR_TYPE_COMPOSITION_LAYER_PROJECTION}; layer.space = this->stage_space; layer.viewCount = (uint32_t)projection_layer_views.size(); layer.views = projection_layer_views.data(); layers.push_back((XrCompositionLayerBaseHeader*)&layer); - - } else { - l_quad_layers.resize(1); - // Initialize quad layers for each eye - for (size_t i = 0; i < 1; ++i) { - const auto& swapchain = this->swapchains[i]; - - l_quad_layers[i] = {XR_TYPE_COMPOSITION_LAYER_QUAD}; - l_quad_layers[i].next = nullptr; - l_quad_layers[i].layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT; - l_quad_layers[i].space = this->stage_space; - l_quad_layers[i].eyeVisibility = XR_EYE_VISIBILITY_BOTH; - - // Configure swapchain - l_quad_layers[i].subImage.swapchain = swapchain.handle; - l_quad_layers[i].subImage.imageRect.offset = {0, 0}; - l_quad_layers[i].subImage.imageRect.extent = {(int32_t)swapchain.width, (int32_t)swapchain.height}; - - { - auto flat_screen = glm::mat4(1.0f); - flat_screen[3][2] = -m_flat_screen_distance; - flat_screen = m_center_stage * flat_screen; - auto rotation = glm::normalize(glm::quat_cast(flat_screen)); - l_quad_layers[i].pose.orientation = to_openxr(rotation); - l_quad_layers[i].pose.position = {flat_screen[3][0], flat_screen[3][1], flat_screen[3][2]}; - } - - // Set size (2m wide, maintain aspect ratio) - float aspect_ratio = (float)swapchain.width / (float)swapchain.height; - l_quad_layers[i].size = {2.0f, 2.0f / aspect_ratio}; - - layers.push_back(reinterpret_cast(&l_quad_layers[i])); - } } - for(auto layer : quad_layers) { + + for (auto layer : quad_layers) { layers.push_back(layer); } } diff --git a/src/mods/vr/runtimes/VRRuntime.hpp b/src/mods/vr/runtimes/VRRuntime.hpp index c2592dc..f6662cf 100644 --- a/src/mods/vr/runtimes/VRRuntime.hpp +++ b/src/mods/vr/runtimes/VRRuntime.hpp @@ -161,7 +161,6 @@ struct VRRuntime { float m_vertical_fov_scale = 1.f; bool m_extended_fov_range = false; Matrix4x4f m_center_stage = Matrix4x4f{1.0f}; - float m_flat_screen_distance = 1.5f; SynchronizeStage custom_stage{SynchronizeStage::EARLY}; }; \ No newline at end of file