From 434988142e8879fae66155de1ffc6c6b06ddc887 Mon Sep 17 00:00:00 2001 From: praydog Date: Tue, 20 Jun 2023 16:11:13 -0700 Subject: [PATCH] Fix "Ghosting fix" on UE5 --- shared/sdk/FSceneView.hpp | 37 +++++++++++++++++++++++- shared/sdk/StereoStuff.hpp | 4 +++ src/mods/vr/FFakeStereoRenderingHook.cpp | 22 +++++++++----- src/mods/vr/FFakeStereoRenderingHook.hpp | 12 ++++++-- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/shared/sdk/FSceneView.hpp b/shared/sdk/FSceneView.hpp index 82c7e9ab..97702dd9 100644 --- a/shared/sdk/FSceneView.hpp +++ b/shared/sdk/FSceneView.hpp @@ -1,7 +1,42 @@ #pragma once +#include "Math.hpp" + namespace sdk { -struct FSceneViewInitOptions; +struct FSceneViewFamily; +struct FSceneViewStateInterface; + +template +struct FSceneViewProjectionDataT { + glm::vec<3, T> view_origin{}; + __declspec(align(16)) glm::mat<4, 4, T, glm::defaultp> view_rotation_matrix{}; + __declspec(align(16)) glm::mat<4, 4, T, glm::defaultp> projection_matrix{}; + + int32_t view_rect[4]; + int32_t constrained_view_rect[4]; +}; + +template +struct FSceneViewInitOptionsT : public FSceneViewProjectionDataT { + FSceneViewFamily* family{nullptr}; + FSceneViewStateInterface* scene_view_state{nullptr}; + void* actor{nullptr}; + int32_t player_index{}; + + void* view_element_drawer{}; + + // FLinearColor + float background_color[4]{}; + float overlay_color[4]{}; + float color_scale[4]{}; + + // EStereoscopicPass + uint32_t stereo_pass{}; +}; + +using FSceneViewInitOptions = FSceneViewInitOptionsT; +using FSceneViewInitOptionsUE4 = FSceneViewInitOptionsT; +using FSceneViewInitOptionsUE5 = FSceneViewInitOptionsT; struct FSceneView { void constructor(const FSceneViewInitOptions* initOptions); diff --git a/shared/sdk/StereoStuff.hpp b/shared/sdk/StereoStuff.hpp index 60b76610..d4789240 100644 --- a/shared/sdk/StereoStuff.hpp +++ b/shared/sdk/StereoStuff.hpp @@ -7,6 +7,10 @@ #include "FSceneView.hpp" +namespace sdk { +struct FSceneView; +} + enum ETextureCreateFlags : uint64_t { RenderTargetable = 1ull << 0, ResolveTargetable = 1ull << 1, ShaderResource = 1ull << 3, }; enum EStereoscopicPass { eSSP_FULL, eSSP_PRIMARY, eSSP_SECONDARY }; diff --git a/src/mods/vr/FFakeStereoRenderingHook.cpp b/src/mods/vr/FFakeStereoRenderingHook.cpp index 20869496..0be233a1 100644 --- a/src/mods/vr/FFakeStereoRenderingHook.cpp +++ b/src/mods/vr/FFakeStereoRenderingHook.cpp @@ -2484,20 +2484,24 @@ constexpr auto INIT_OPTION_SCENE_STATE_INTERFACE_OFFSET = 0xB8; constexpr auto INIT_OPTIONS_PROJECTION_MATRIX_OFFSET = 0x50; constexpr auto INIT_OPTIONS_STEREO_PASS_OFFSET = 0x108; +constexpr auto test = offsetof(sdk::FSceneViewInitOptions, scene_view_state); // FSceneView constructor hook -sdk::FSceneView* FFakeStereoRenderingHook::sceneview_constructor(sdk::FSceneView* view, sdk::FSceneViewInitOptions* init_options) { +sdk::FSceneView* FFakeStereoRenderingHook::sceneview_constructor(sdk::FSceneView* view, sdk::FSceneViewInitOptions* init_options, void* a3, void* a4) { SPDLOG_INFO_ONCE("Called FSceneView constructor for the first time"); auto& vr = VR::get(); if (!g_hook->is_in_viewport_client_draw() || !vr->is_hmd_active()) { - return g_hook->m_sceneview_data.constructor_hook.call(view, init_options); + return g_hook->m_sceneview_data.constructor_hook.call(view, init_options, a3, a4); } - auto& known_scene_states = g_hook->m_sceneview_data.known_scene_states; + std::scoped_lock _{g_hook->m_sceneview_data.mtx}; + + auto init_options_ue5 = (sdk::FSceneViewInitOptionsUE5*)init_options; - static uint32_t last_frame_count = 0; - static uint32_t last_index = 0; + auto& known_scene_states = g_hook->m_sceneview_data.known_scene_states; + auto& last_frame_count = g_hook->m_sceneview_data.last_frame_count; + auto& last_index = g_hook->m_sceneview_data.last_index; if (last_frame_count != g_frame_count || last_index > 1) { last_index = 0; @@ -2554,8 +2558,10 @@ sdk::FSceneView* FFakeStereoRenderingHook::sceneview_constructor(sdk::FSceneView //init_options_stereo_pass = 0; } - auto& init_options_scene_state = *(void**)((uintptr_t)init_options + INIT_OPTION_SCENE_STATE_INTERFACE_OFFSET); - auto& init_options_stereo_pass = *(uint8_t*)((uintptr_t)init_options + INIT_OPTIONS_STEREO_PASS_OFFSET); + const auto is_ue5 = g_hook->has_double_precision(); + + auto& init_options_scene_state = is_ue5 ? init_options_ue5->scene_view_state : init_options->scene_view_state; + auto& init_options_stereo_pass = is_ue5 ? init_options_ue5->stereo_pass : init_options->stereo_pass; if (init_options_scene_state != nullptr && !g_hook->m_sceneview_data.known_scene_states.contains(init_options_scene_state)) { SPDLOG_INFO("Inserting new scene state {:x}", (uintptr_t)init_options_scene_state); @@ -2579,7 +2585,7 @@ sdk::FSceneView* FFakeStereoRenderingHook::sceneview_constructor(sdk::FSceneView last_index++; - return g_hook->m_sceneview_data.constructor_hook.call(view, init_options); + return g_hook->m_sceneview_data.constructor_hook.call(view, init_options, a3, a4); } void FFakeStereoRenderingHook::setup_view_family(ISceneViewExtension* extension, FSceneViewFamily& view_family) { diff --git a/src/mods/vr/FFakeStereoRenderingHook.hpp b/src/mods/vr/FFakeStereoRenderingHook.hpp index e532cf1c..e5068073 100644 --- a/src/mods/vr/FFakeStereoRenderingHook.hpp +++ b/src/mods/vr/FFakeStereoRenderingHook.hpp @@ -23,6 +23,10 @@ struct UCanvas; struct IStereoLayers; struct FSceneViewFamily; +namespace sdk { +struct FSceneViewStateInterface; +} + // Injector-specific structure for VRRenderTargetManager that they will all secondarily inherit from // because different engine versions can have a different IStereoRenderTargetManager virtual table // so we need a unified way of storing data that can be used for all versions @@ -304,7 +308,7 @@ class FFakeStereoRenderingHook : public ModComponent { // Hooks // FSceneView - static sdk::FSceneView* sceneview_constructor(sdk::FSceneView* sceneview, sdk::FSceneViewInitOptions* init_options); + static sdk::FSceneView* sceneview_constructor(sdk::FSceneView* sceneview, sdk::FSceneViewInitOptions* init_options, void* a3, void* a4); // IStereoRendering static bool is_stereo_enabled(FFakeStereoRendering* stereo); @@ -341,9 +345,13 @@ class FFakeStereoRenderingHook : public ModComponent { std::unique_ptr> m_slate_thread_worker{std::make_unique>()}; struct { + std::recursive_mutex mtx{}; safetyhook::InlineHook constructor_hook{}; - std::unordered_set known_scene_states; + std::unordered_set known_scene_states; bool inside_post_init_properties{false}; + + uint32_t last_frame_count{}; + uint32_t last_index{}; } m_sceneview_data; safetyhook::InlineHook m_localplayer_get_viewpoint_hook{};