From 5b793a1ab672bbc5b8c6add6fc757ef4b5d13a4b Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Mon, 23 Feb 2026 12:02:01 -0500 Subject: Dof params and advance frame button Signed-off-by: Andrew Opalach --- .gitignore | 1 + Plugin.cs | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 229 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 4e0a4d8..7981742 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Archive/ ModSlots/slots.txt ModSlots/venv/ Research/temp/ +Research/video/ diff --git a/Plugin.cs b/Plugin.cs index 03c8c49..2997701 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -46,6 +46,7 @@ using SharpPluginLoader.Core.Configuration; // - Open Poses Menu // @TODO: +// - Attempt to document all test cases I can think of. // - Better hook for renderer params. // - Centralize all bindings to get a better idea of how to structure custom binds. // - Use GetRef<>. @@ -180,6 +181,28 @@ namespace MHWNewCamera public bool gBufferJitter; // +0xB440 }; + public struct DOFParameters { + public bool enabled; // +0x1DD + public bool newVersion; // +0x1DC + public float fNumber; // +0x1A0 + public float sensorSize; // +0x1A4 + public float focusDistance; // +0x1A8 + public float nearCoef; // +0x1CC + public float farCoef; // +0x1C8 + public bool nearEnable; // +0x1DE + public bool farEnable; // +0x1DF + public bool debugDraw; // +0x1E0 + public float radius; // +0x1D0 + public float depthScaleForeground; // +0x1D4 + public float aspect; // +0x1D8 + public bool vignettingEnabled; // +0x200 + public bool vignettingEllipse; // +0x201 + public float vignettingEllipticity; // +0x204 + public float vignettingOffset; // +0x1F8 + public float vignettingPow; // +0x1FC + public int vignettingColor; // +0x208 + }; + public enum ZoneState : int { Unknown = 0, Hub = 1, @@ -201,6 +224,8 @@ namespace MHWNewCamera private static readonly MtObject sMain = SingletonManager.GetSingleton("sMhMain")!; private static readonly MtObject sUmbra = SingletonManager.GetSingleton("sUmbra")!; private bool freezeGame = false; + private bool decoupleDtFromGameTime = false; + private int advanceFrame = 0; private float cameraSpeed; private float cameraSpeedModifier; @@ -349,6 +374,14 @@ namespace MHWNewCamera private delegate void MotionBlurDelegate(nint unknownPtr, nint unknownPtr2); private Hook? motionBlurHook; + private bool dofDisabled = false; + private DOFParameters dofParams; + private bool fillOutDofParams = true; + private bool applyVignettingParams = false; + private bool fillOutVignettingParams = true; + private delegate void DofUpdateDelegate(nint unknownPtr); + private Hook? dofHook; + private delegate void CameraEffectDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3); private Hook? cameraEffectHook; @@ -383,7 +416,6 @@ namespace MHWNewCamera private bool uiToggled = false; private Patch jmpOverUi; - private bool dofDisabled = false; private Patch jmpOverDof; private bool disableCharacterFade = false; @@ -829,6 +861,8 @@ namespace MHWNewCamera motionBlurHook = Hook.Create(0x1424CADF0, MotionBlurHook); // nint, nint + dofHook = Hook.Create(0x1412BA6A0, DofHook); // nint + cameraEffectHook = Hook.Create(0x141AB6AE0, CameraEffectHook); // nint, nint, nint unchecked @@ -1294,6 +1328,17 @@ namespace MHWNewCamera } freeCameraFallback = true; + ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); + if (freezeGame && gameSpeed != 0.0f) + { + gameSpeed = 0.0f; + } + else if (freezeGame && advanceFrame > 0) + { + gameSpeed = 1.0f; + advanceFrame--; + } + if (hideWeapon) { Player? player = Player.MainPlayer; @@ -1488,7 +1533,7 @@ namespace MHWNewCamera private void updateFreeCamera(Camera camera) { float deltaTime; - if (freezeGame) + if (decoupleDtFromGameTime) { deltaTime = 60.0f / MemoryUtil.Read(sMain.Instance + 0x68); } @@ -2706,6 +2751,8 @@ namespace MHWNewCamera if (buttonWasPressed(Button.Circle)) { + dofParams.nearEnable = !dofParams.nearEnable; + /* dofDisabled = !dofDisabled; if (dofDisabled) { @@ -2715,6 +2762,7 @@ namespace MHWNewCamera { jmpOverDof.Disable(); } + */ } } else if (freeCameraFromViewMode && !unlockInputForMenu && buttonWasPressed(Button.Circle)) @@ -2876,10 +2924,12 @@ namespace MHWNewCamera { motionBlurWasDisabled = motionBlurDisabled; motionBlurDisabled = true; + decoupleDtFromGameTime = true; } else { motionBlurDisabled = motionBlurWasDisabled; + decoupleDtFromGameTime = false; } MemoryUtil.WriteBytes(sMain.Instance + 0xA4, BitConverter.GetBytes(freezeGame ? 0.0f : 1.0f)); } @@ -2904,6 +2954,100 @@ namespace MHWNewCamera motionBlurHook!.Original(unknownPtr, unknownPtr2); } + private void DofHook(nint unknownPtr) + { + dofHook!.Original(unknownPtr); + + if (disableMod) + { + return; + } + +#if HOOK_ORDER_ASSERTS + debugLog($"DofHook({unknownPtr:x}) @ {frameTick}"); +#endif + + nint unknownObj = MemoryUtil.Read(unknownPtr + 0x230); + nint dofFilter = MemoryUtil.Read(unknownObj + 0x58); + if (dofFilter != 0x0) + { + ref byte dofEnabled = ref MemoryUtil.GetRef(dofFilter + 0x1DD); + ref byte newVersion = ref MemoryUtil.GetRef(dofFilter + 0x1DC); + ref float fNumber = ref MemoryUtil.GetRef(dofFilter + 0x1A0); + ref float sensorSize = ref MemoryUtil.GetRef(dofFilter + 0x1A4); + ref float focusDistance = ref MemoryUtil.GetRef(dofFilter + 0x1A8); + ref float nearCoef = ref MemoryUtil.GetRef(dofFilter + 0x1CC); + ref float farCoef = ref MemoryUtil.GetRef(dofFilter + 0x1C8); + ref byte nearEnable = ref MemoryUtil.GetRef(dofFilter + 0x1DE); + ref byte farEnable = ref MemoryUtil.GetRef(dofFilter + 0x1DF); + ref byte debugDraw = ref MemoryUtil.GetRef(dofFilter + 0x1E0); + ref float radius = ref MemoryUtil.GetRef(dofFilter + 0x1D0); + ref float depthScaleForeground = ref MemoryUtil.GetRef(dofFilter + 0x1D4); + ref float aspect = ref MemoryUtil.GetRef(dofFilter + 0x1D8); + ref byte vignettingEnabled = ref MemoryUtil.GetRef(dofFilter + 0x200); + ref byte vignettingEllipse = ref MemoryUtil.GetRef(dofFilter + 0x201); + ref float vignettingEllipticity = ref MemoryUtil.GetRef(dofFilter + 0x204); + ref float vignettingOffset = ref MemoryUtil.GetRef(dofFilter + 0x1F8); + ref float vignettingPow = ref MemoryUtil.GetRef(dofFilter + 0x1FC); + ref int vignettingColor = ref MemoryUtil.GetRef(dofFilter + 0x208); + if (fillOutDofParams) + { + dofParams.enabled = dofEnabled == 0x1; + dofParams.newVersion = newVersion == 0x1; + dofParams.fNumber = fNumber; + dofParams.sensorSize = sensorSize; + dofParams.focusDistance = focusDistance; + dofParams.nearCoef = nearCoef; + dofParams.farCoef = farCoef; + dofParams.nearEnable = nearEnable == 0x1; + dofParams.farEnable = farEnable == 0x1; + dofParams.debugDraw = debugDraw == 0x1; + dofParams.radius = radius; + dofParams.depthScaleForeground = depthScaleForeground; + dofParams.aspect = aspect; + fillOutDofParams = false; + } + if (fillOutVignettingParams) + { + dofParams.vignettingEnabled = vignettingEnabled == 0x1; + dofParams.vignettingEllipse = vignettingEllipse == 0x1; + dofParams.vignettingEllipticity = vignettingEllipticity; + dofParams.vignettingOffset = vignettingOffset; + dofParams.vignettingPow = vignettingPow; + dofParams.vignettingColor = vignettingColor; + fillOutVignettingParams = false; + } + /* + if ((dofEnabled == 0x0) != dofDisabled) + { + dofEnabled = byteFlag(!dofDisabled); + } + */ + dofEnabled = byteFlag(dofParams.enabled); + newVersion = byteFlag(dofParams.newVersion); + fNumber = dofParams.fNumber; + sensorSize = dofParams.sensorSize; + focusDistance = dofParams.focusDistance; + nearCoef = dofParams.nearCoef; + farCoef = dofParams.farCoef; + nearEnable = byteFlag(dofParams.nearEnable); + farEnable = byteFlag(dofParams.farEnable); + debugDraw = byteFlag(dofParams.debugDraw); + radius = dofParams.radius; + depthScaleForeground = dofParams.depthScaleForeground; + aspect = dofParams.aspect; + if (applyVignettingParams) + { + vignettingEnabled = byteFlag(dofParams.vignettingEnabled); + vignettingEllipse = byteFlag(dofParams.vignettingEllipse); + vignettingEllipticity = dofParams.vignettingEllipticity; + vignettingOffset = dofParams.vignettingOffset; + vignettingPow = dofParams.vignettingPow; + vignettingColor = dofParams.vignettingColor; + } + } + } + private void UnderwaterCheckHook(nint unknownPtr) { underwaterCheckHook!.Original(unknownPtr); @@ -3448,15 +3592,20 @@ namespace MHWNewCamera } #if SHADER_FEATURES + private bool shadersLoadedOnce = false; public unsafe void OnCreateShader(ShaderInfo *info) { + if (shadersLoadedOnce) + { + return; + } string hash = new string(info->DxbcHash); if (hash == "2e4e18fd-6ea5eeae-2de3d65c-26ab36dd") { byte[] shaderData; try { - shaderData = System.IO.File.ReadAllBytes("./volume_upsample.shdr"); + shaderData = System.IO.File.ReadAllBytes("./volume_upsample_edit.shdr"); } catch (Exception) { @@ -3465,13 +3614,14 @@ namespace MHWNewCamera info->NewSourceType = SourceType.BINARY; info->NewSourceLength = shaderData.Length; info->NewSource = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(shaderData, 0); + Log.Info("Replaced volume upsample shader 1."); } else if (hash == "e2c8c13e-45bc99b2-4c3d7699-3d66188e") { byte[] shaderData; try { - shaderData = System.IO.File.ReadAllBytes("./volume_upsample2.shdr"); + shaderData = System.IO.File.ReadAllBytes("./volume_upsample2_edit.shdr"); } catch (Exception) { @@ -3480,6 +3630,9 @@ namespace MHWNewCamera info->NewSourceType = SourceType.BINARY; info->NewSourceLength = shaderData.Length; info->NewSource = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(shaderData, 0); + Log.Info("Replaced volume upsample shader 2."); + // This interestingly allows us to A/B using the volume rendering value 2 switch. + shadersLoadedOnce = true; } } #endif @@ -4640,17 +4793,31 @@ namespace MHWNewCamera } ImGui.PushItemWidth(width * 0.125f); - float gameSpeed = MemoryUtil.Read(sMain.Instance + 0xA4); + ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); if (ImGui.DragFloat("Game Speed", ref gameSpeed, 0.005f, 0.0f, Single.MaxValue)) { - MemoryUtil.WriteBytes(sMain.Instance + 0xA4, BitConverter.GetBytes(gameSpeed)); + if (gameSpeed == 1.0f) + { + decoupleDtFromGameTime = false; + } } ImGui.SameLine(); if (ImGui.Button("Toggle Freeze Game")) { toggleFreezeGame(); } + ImGui.SameLine(); + if (ImGui.Button("Advance Frame")) + { + advanceFrame++; + } ImGui.PopItemWidth(); + ImGui.Checkbox("Decouple Camera Speed from Game Speed", ref decoupleDtFromGameTime); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Enable this to move in free camera at a normal speed when game speed is not 1.0."); + ImGui.EndTooltip(); + } if (ImGui.Checkbox("Override View Mode", ref overrideViewMode)) { @@ -4973,13 +5140,58 @@ namespace MHWNewCamera ImGui.EndTooltip(); } + if (ImGui.CollapsingHeader("Depth of Field Parameters")) + { + ImGui.Checkbox("Enabled", ref dofParams.enabled); + ImGui.Checkbox("New Version", ref dofParams.newVersion); + ImGui.DragFloat("FNumber", ref dofParams.fNumber, 0.001f, 0.0f, 0.0f, "%.5f"); + ImGui.DragFloat("Sensor Size", ref dofParams.sensorSize, 0.001f, 0.0f, 0.0f, "%.5f"); + ImGui.DragFloat("Focus Distance", ref dofParams.focusDistance, 0.2f); + ImGui.DragFloat("Near Coef", ref dofParams.nearCoef, 0.001f, 0.0f, 0.0f, "%.5f"); + ImGui.DragFloat("Far Coef", ref dofParams.farCoef, 0.001f, 0.0f, 0.0f, "%.5f"); + ImGui.Checkbox("Near Enabled", ref dofParams.nearEnable); + ImGui.Checkbox("Far Enabled", ref dofParams.farEnable); + ImGui.Checkbox("Debug Draw", ref dofParams.debugDraw); + if (!dofParams.newVersion) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + ImGui.Text("New Version Parameters:"); + ImGui.DragFloat("Radius", ref dofParams.radius, 0.001f, 0.0f, 0.0f, "%.6f"); + ImGui.DragFloat("Depth Scale Foreground", ref dofParams.depthScaleForeground, 0.0001f, 0.0f, 0.0f, "%.6f"); + ImGui.DragFloat("Aspect", ref dofParams.aspect, 0.001f, 0.0f, 0.0f, "%.6f"); + if (!dofParams.newVersion) + { + ImGui.PopStyleVar(); + } + if (ImGui.Button("Reset Per-frame Parameters")) + { + fillOutDofParams = true; + } + } + + if (ImGui.CollapsingHeader("Vignetting Parameters")) + { + ImGui.Checkbox("Apply Adjustments", ref applyVignettingParams); + ImGui.Checkbox("Enabled", ref dofParams.vignettingEnabled); + ImGui.Checkbox("Ellipse", ref dofParams.vignettingEllipse); + ImGui.DragFloat("Ellipticity", ref dofParams.vignettingEllipticity, 0.05f); + ImGui.DragFloat("Offset", ref dofParams.vignettingOffset, 0.05f); + ImGui.DragFloat("Power", ref dofParams.vignettingPow, 0.05f); + ImGui.InputInt("Color", ref dofParams.vignettingColor, 0, 0, ImGuiInputTextFlags.CharsHexadecimal); + if (ImGui.Button("Reset Per-frame Parameters")) + { + fillOutVignettingParams = true; + } + } + if (ImGui.CollapsingHeader("Shadow Distance Parameters")) { ImGui.PushItemWidth(width * 0.2f); ImGui.Text($"sUmbra: {sUmbra.Instance:x}"); nint obj = MemoryUtil.Read(sUmbra.Instance + 0x00149740); ImGui.Text($"Object Address: {obj:x}"); - ImGui.Checkbox("Apply Adjust", ref applyShadowAdjust); + ImGui.Checkbox("Apply Adjustments", ref applyShadowAdjust); ImGui.InputFloat("Shadow Backforward Distance", ref shadowBackforwardDistance); if (ImGui.BeginItemTooltip()) { @@ -5190,9 +5402,15 @@ namespace MHWNewCamera } ImGui.Text("Graphics:"); - // Names and locations taken from MHW-DTI-Dumps/wip_dump_15_20_00.h. - ImGui.Text($"Max Fps: {MemoryUtil.Read(sMain.Instance + 0x5C)}"); - ImGui.Text($"Fps: {MemoryUtil.Read(sMain.Instance + 0x68)}"); + // Locations taken from MHW-DTI-Dumps/wip_dump_15_20_00.h. + ImGui.InputFloat("Simulation Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x58)); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("This does not apply to jiggle physics."); + ImGui.EndTooltip(); + } + ImGui.InputFloat("Max Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x5C)); + ImGui.InputFloat("Fps", ref MemoryUtil.GetRef(sMain.Instance + 0x68)); ImGui.Text($"Delta Time: {MemoryUtil.Read(sMain.Instance + 0x94)}"); ImGui.Text($"prevFoliageLODBias: {prevFoliageLODBias}"); -- cgit v1.2.3-101-g0448