Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 29 additions & 42 deletions src/Client/Hook/Hooks/Render/DirectX/DX11/SwapchainHook_DX11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,36 +192,42 @@ void SwapchainHook::_DX11RenderUnderUI()
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

bool needsBuffer = FlarialGUI::inMenu;
if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;

FlarialGUI::needsBackBuffer = needsBuffer;
}

SaveBackbuffer(true);

/*
static UINT lastBufferWidth = 0, lastBufferHeight = 0;
// Ensure cachedDX11RTV exists and matches the current backbuffer dimensions.
// This was previously commented out, causing event->RTV to be null on the
// first frame and after any resize — breaking all UnderUI post-process modules.
{
static UINT lastUnderUIWidth = 0, lastUnderUIHeight = 0;

winrt::com_ptr<ID3D11Texture2D> backBuffer;
if (FAILED(swapchain->GetBuffer(0, IID_PPV_ARGS(backBuffer.put())))) {
return;/
}
winrt::com_ptr<ID3D11Texture2D> backBuffer;
if (FAILED(swapchain->GetBuffer(0, IID_PPV_ARGS(backBuffer.put())))) {
return;
}

D3D11_TEXTURE2D_DESC desc;
backBuffer->GetDesc(&desc);
D3D11_TEXTURE2D_DESC desc;
backBuffer->GetDesc(&desc);

if (!cachedDX11RTV.get() || desc.Width != lastBufferWidth || desc.Height != lastBufferHeight) {
cachedDX11RTV = nullptr;
if (FAILED(d3d11Device->CreateRenderTargetView(backBuffer.get(), nullptr, cachedDX11RTV.put()))) {
return;
if (!cachedDX11RTV.get() || desc.Width != lastUnderUIWidth || desc.Height != lastUnderUIHeight) {
cachedDX11RTV = nullptr;
if (FAILED(d3d11Device->CreateRenderTargetView(backBuffer.get(), nullptr, cachedDX11RTV.put()))) {
return;
}
lastUnderUIWidth = desc.Width;
lastUnderUIHeight = desc.Height;
}
lastBufferWidth = desc.Width;
lastBufferHeight = desc.Height;
}
*/

winrt::com_ptr<ID3D11RenderTargetView> originalRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
winrt::com_ptr<ID3D11DepthStencilView> originalDSV = nullptr;

Expand All @@ -235,37 +241,16 @@ void SwapchainHook::_DX11RenderUnderUI()
}
originalDSV.attach(dsv);


/*
D2D::context->BeginDraw();

ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::Begin("t", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoDecoration);

*/

auto event = nes::make_holder<RenderUnderUIEvent>();
event->RTV = cachedDX11RTV.get();
eventMgr.trigger(event);

/* At the moment, Flarial does not utilize ImGui under ui.
* Even if you uncomment the following lines, it won't work,
* Something special needs to be done.
D2D::context->EndDraw();

ImGui::End();
ImGui::EndFrame();
ImGui::Render();

ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
*/

// NOTE: ImGui is NOT available during RenderUnderUIEvent.
// Modules that need to render here must use raw D3D11 draw calls
// (like RealMotionBlurHelper, DepthOfFieldHelper, PaniniProjectionHelper).
// ImGui-based rendering (e.g. MotionBlur's ImageWithOpacity for Average/Ghost/V4
// blur types) will silently do nothing because there is no active ImGui frame.
// Starting an ImGui frame here would conflict with the one in _DX11Render().

ID3D11RenderTargetView* restoreRTVs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
for (UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) {
Expand All @@ -287,10 +272,12 @@ void SwapchainHook::DX11Blur() {
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

bool needsBuffer = FlarialGUI::inMenu;
if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;

FlarialGUI::needsBackBuffer = needsBuffer;
}
Expand Down
13 changes: 11 additions & 2 deletions src/Client/Hook/Hooks/Render/DirectX/DX12/SwapchainHook_DX12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,17 @@ void SwapchainHook::DX12Blur() {

/* Blur Stuff */
prepareBlur();
if (FlarialGUI::inMenu) FlarialGUI::needsBackBuffer = true;
else FlarialGUI::needsBackBuffer = false;
bool needsBuffer = FlarialGUI::inMenu;
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;
}
FlarialGUI::needsBackBuffer = needsBuffer;
/* Blur End */

}
Expand Down
20 changes: 6 additions & 14 deletions src/Client/Hook/Hooks/Render/DirectX/DXGI/UnderUIHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,10 @@ void UnderUIHooks::ClearDepthStencilViewCallbackDX12(
UINT NumRects,
const D3D12_RECT *pRects) {


index++;

if (ClearFlags == D3D12_CLEAR_FLAG_DEPTH && SwapchainHook::init){
if (ClearFlags == D3D12_CLEAR_FLAG_DEPTH && SwapchainHook::init) {
savedpDethStencilView = pDepthStencilView;
SwapchainHook::DX12Render(true);
}
funcOriginalDX12(cmdList, pDepthStencilView, ClearFlags, Depth, Stencil, NumRects, pRects);

Expand Down Expand Up @@ -201,17 +199,11 @@ void UnderUIHooks::enableHook() {

} else {

/* DX12 */

/*
void** vtable = *reinterpret_cast<void***>(SwapchainHook::DX12CommandLists);
const size_t INDEX_CLEAR_DEPTH_STENCIL_VIEW = 47;
Memory::hookFunc(
vtable[INDEX_CLEAR_DEPTH_STENCIL_VIEW],
ClearDepthStencilViewCallbackDX12,
(void**)&funcOriginalDX12,
"ClearDepthStencilViewDX12"
);*/
/* DX12 — ClearDepthStencilView hook is not viable mid-frame on DX12.
* D3D11On12 AcquireWrappedResources + ReleaseWrappedResources transitions
* the backbuffer state, and restoring it requires fence waits that stall
* the GPU pipeline and risk heap corruption on resize/fullscreen.
* RenderUnderUIEvent is DX11-only; DX12 modules fall back to RenderEvent. */

/* DX12 */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ void DepthOfFieldHelper::RenderDepthOfField(ID3D11RenderTargetView* pDstRenderTa
auto backbuffer = SwapchainHook::GetBackbuffer();
if (intensity <= 0 || !backbuffer || !pDepthMapSRV) return;

winrt::com_ptr<ID3D11ShaderResourceView> pOrigShaderResourceView = MotionBlur::BackbufferToSRVExtraMode();
// DepthOfField renders during RenderUnderUIEvent, so read from the underUI backbuffer pool
winrt::com_ptr<ID3D11ShaderResourceView> pOrigShaderResourceView = MotionBlur::BackbufferToSRVExtraMode(true);
if (!pOrigShaderResourceView) return;

winrt::com_ptr<ID3D11DeviceContext> pContext = SwapchainHook::context;
Expand Down
63 changes: 63 additions & 0 deletions src/Client/Module/Modules/FOVChanger/FOVChanger.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
#include "FOVChanger.hpp"
#include "PaniniProjectionHelper.hpp"
#include "../../../Hook/Hooks/Render/DirectX/DXGI/SwapchainHook.hpp"

void FOVChanger::onEnable() {
Listen(this, FOVEvent, &FOVChanger::onGetFOV)
ListenOrdered(this, RenderEvent, &FOVChanger::onRender, EventOrder::IMMEDIATE)
ListenOrdered(this, RenderUnderUIEvent, &FOVChanger::onRenderUnderUI, EventOrder::IMMEDIATE)
Module::onEnable();
}

void FOVChanger::onDisable() {
Deafen(this, FOVEvent, &FOVChanger::onGetFOV)
Deafen(this, RenderEvent, &FOVChanger::onRender)
Deafen(this, RenderUnderUIEvent, &FOVChanger::onRenderUnderUI)
Module::onDisable();
}

void FOVChanger::defaultConfig() {
Module::defaultConfig("core");
setDef("fovvalue", 60.00f);
setDef("fovaffectshand", false);
setDef("panini", false);
setDef("paniniStrength", 0.5f);
setDef("paniniCrop", 1.0f);
setDef("paniniUnderUI", false);
}

void FOVChanger::settingsRender(float settingsOffset) {
initSettingsPage();

addSlider("FOV Value", "", "fovvalue", 359.0f, 0, false);
addToggle("Affect Hand Size", "Keep normal hand size or not.", "fovaffectshand");
addHeader("Panini Projection");
addToggle("Enable Panini Projection",
"Reduces edge distortion at high FOV by using\ncylindrical perspective instead of rectilinear.",
"panini");

if (getOps<bool>("panini")) {
addSlider("Strength", "How much cylindrical compression to apply.\n0 = rectilinear, 1 = full Panini.", "paniniStrength", 1.0f, 0, false);
addSlider("Crop to Fit", "Zoom in to prevent black borders at edges.\n1 = no borders, 0 = no zoom.", "paniniCrop", 1.0f, 0, false);
addToggle("Render Under UI",
"Apply Panini before the game draws its UI, so hotbar\nand chat stay undistorted. DX11 only (requires Better Frames on DX12).",
"paniniUnderUI");
}

FlarialGUI::UnsetScrollView();

Expand Down Expand Up @@ -53,3 +76,43 @@ void FOVChanger::onGetFOV(FOVEvent &event) {
}
event.setFOV(fovSetting);
}

void FOVChanger::onRender(RenderEvent& event) {
// On DX12, RenderUnderUIEvent doesn't fire (mid-frame D3D12 resource state
// management is not viable), so always render at Present time.
if (getOps<bool>("paniniUnderUI") && !SwapchainHook::isDX12) return;
renderPanini(event.RTV);
}

void FOVChanger::onRenderUnderUI(RenderUnderUIEvent& event) {
if (!getOps<bool>("paniniUnderUI")) return;
renderPanini(event.RTV);
}

void FOVChanger::renderPanini(ID3D11RenderTargetView* rtv) {
if (!getOps<bool>("panini")) return;
if (!rtv) return;

float d = getOps<float>("paniniStrength");
if (d <= 0.001f) return;

if (!PaniniProjectionHelper::initialized) {
if (!PaniniProjectionHelper::Initialize())
return;
}

winrt::com_ptr<ID3D11Texture2D> backbuffer;
{
std::lock_guard<std::mutex> lock(SwapchainHook::backbufferMutex);
backbuffer = SwapchainHook::SavedD3D11BackBuffer;
}
if (!backbuffer) return;

auto* sceneSRV = PaniniProjectionHelper::CopyBackbufferToSRV(backbuffer.get());
if (!sceneSRV) return;

float fov = getOps<float>("fovvalue");
float cropToFit = getOps<float>("paniniCrop");

PaniniProjectionHelper::Render(rtv, sceneSRV, fov, d, cropToFit);
}
11 changes: 9 additions & 2 deletions src/Client/Module/Modules/FOVChanger/FOVChanger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

#include "../Module.hpp"
#include "../../../Client.hpp"

#include "Events/Render/RenderEvent.hpp"
#include "Events/Render/RenderUnderUIEvent.hpp"

#include "Assets/Assets.hpp"

Expand All @@ -24,5 +25,11 @@ class FOVChanger : public Module {
void settingsRender(float settingsOffset) override;

void onGetFOV(FOVEvent& event);
};

void onRender(RenderEvent& event);

void onRenderUnderUI(RenderUnderUIEvent& event);

private:
void renderPanini(ID3D11RenderTargetView* rtv);
};
Loading
Loading