diff options
| -rw-r--r-- | Config.cs | 63 | ||||
| -rw-r--r-- | LUT.cs | 106 | ||||
| -rw-r--r-- | Lights.cs | 216 | ||||
| -rw-r--r-- | Plugin.cs | 1181 | ||||
| -rw-r--r-- | Shaders/color_grading_add_uchimura.diff | 41 |
5 files changed, 1009 insertions, 598 deletions
@@ -51,7 +51,7 @@ namespace WorldTuningTool public class Config : IConfig { public String Name => "WorldTuningTool"; - public String Version => "0.9.4"; + public String Version => "1.0"; public static string StageToString(StageExt stage) { @@ -183,15 +183,76 @@ namespace WorldTuningTool { #if SHADER_FEATURES public bool FullResolutionSSLR { get; set; } = false; + public bool VolumeUpsampleNoLinear { get; set; } = false; + public bool FXAAMaxQualityPreset { get; set; } = false; + public bool SkinAllowNegativeWetness { get; set; } = false; #endif public bool FullResolutionVolumeBlur { get; set; } = false; public bool HigherThanHighestVolumeRendering { get; set; } = false; public bool DisableLODLimits { get; set; } = false; + public bool CharacterCreatorFaceRendering { get; set; } = false; public bool LargerFoliageSwayRange { get; set; } = false; public bool DisableReducedRateAnimations { get; set; } = false; public PatchConfig() {} } + public static Dictionary<string, string> OldParameterNames = new Dictionary<string, string>() + { + { "Sunlight Group", "Primary Light Group" }, + { "Sunlight Direction", "Primary Light Direction" }, + { "Sunlight Color", "Primary Light Color" }, + { "Sunlight Intensity", "Primary Light Intensity" }, + { "Sunlight Is Primary", "Primary Light Is Primary" }, + { "Projection Scale", "Primary Light Projection Scale" }, + { "Projection Offset Speed", "Primary Light Projection Offset Speed" }, + { "Projection Up", "Primary Light Projection Up" }, + { "Do Volumetric", "Primary Light Do Volumetric" }, + { "Shadow Cast", "Primary Shadow Cast" }, + { "Shadow Map Size", "Primary Shadow Map Size" }, + { "Shadow Near Clip Distance", "Primary Shadow Near Clip Distance" }, + { "Shadow Cascade Mode", "Primary Shadow Cascade Mode" }, + { "Shadow Cascade 2Way Bias", "Primary Shadow Cascade 2Way Bias" }, + { "Shadow Distance", "Primary Shadow Cascade Distance" }, + { "Shadow Backforward Distance", "Primary Shadow Cascade Backforward Distance" }, + { "Shadow Is Fixed Fov Mode", "Primary Shadow Is Fixed Fov Mode" }, + { "Shadow Fov", "Primary Shadow Fov" }, + { "Shadow Is Discretization Fov Mode", "Primary Shadow Is Discretization Fov Mode" }, + { "Shadow Discretization Angle", "Primary Shadow Discretization Angle" }, + { "Shadow Distribution", "Primary Shadow Cascade Distribution" }, + { "Cascade Manual Split", "Primary Shadow Cascade Manual Split" }, + { "Cascade Manual Split Distance[0]", "Primary Shadow Cascade Manual Split Distance[0]" }, + { "Cascade Manual Split Distance[1]", "Primary Shadow Cascade Manual Split Distance[1]" }, + { "Cascade Manual Split Distance[2]", "Primary Shadow Cascade Manual Split Distance[2]" }, + { "Shadow Sloped Depth Bias", "Primary Shadow Sloped Depth Bias" }, + { "Shadow Depth Bias", "Primary Shadow Depth Bias" }, + { "Shadow Max Depth Bias", "Primary Shadow Max Depth Bias" }, + { "Cascade Individual Shadow Bias", "Primary Shadow Cascade Individual Shadow Bias" }, + { "Cascade Depth Bias[0]", "Primary Shadow Cascade Depth Bias[0]" }, + { "Cascade Sloped Depth Bias[0]", "Primary Shadow Cascade Sloped Depth Bias[0]" }, + { "Cascade Max Depth Bias[0]", "Primary Shadow Cascade Max Depth Bias[0]" }, + { "Cascade Depth Bias[1]", "Primary Shadow Cascade Depth Bias[1]" }, + { "Cascade Sloped Depth Bias[1]", "Primary Shadow Cascade Sloped Depth Bias[1]" }, + { "Cascade Max Depth Bias[1]", "Primary Shadow Cascade Max Depth Bias[1]" }, + { "Cascade Depth Bias[2]", "Primary Shadow Cascade Depth Bias[2]" }, + { "Cascade Sloped Depth Bias[2]", "Primary Shadow Cascade Sloped Depth Bias[2]" }, + { "Cascade Max Depth Bias[2]", "Primary Shadow Cascade Max Depth Bias[2]" }, + { "Light Tone Map Type", "Tone Map Type" }, + { "Light Compute Luminance", "Tone Map Compute Luminance" }, + { "Light Luminance Version", "Tone Map Luminance Version" }, + { "Light Shoulder Strength", "Tone Map Shoulder Strength" }, + { "Light Linear Strength", "Tone Map Linear Strength" }, + { "Light Linear Angle", "Tone Map Linear Angle" }, + { "Light Toe Strength", "Tone Map Toe Strength" }, + { "Light Toe Num", "Tone Map Toe Num" }, + { "Light Toe Denum", "Tone Map Toe Denum" }, + { "Light White Point", "Tone Map White Point" }, + { "Light LUT Blend", "Color Grading LUT Blend" }, + { "Light Vfx LUT Blend", "Color Grading Vfx LUT Blend" }, + { "Light Enable Color Grading", "Color Grading Enable" }, + { "Light Is Linear To PQ", "Color Grading Is Linear To PQ" }, + { "Light Is PQ To Linear", "Color Grading Is PQ To Linear" } + }; + public bool DisableLightsFeature { get; set; } = false; public PatchConfig Patches { get; set; } = new PatchConfig(); @@ -6,47 +6,57 @@ using System.Runtime.InteropServices; using ImGuiNET; using SharpPluginLoader.Core.Memory; +using SharpPluginLoader.Core.IO; #if TEXTURE_FEATURE using SharpPluginLoader.Core.Resources; -using SharpPluginLoader.Core.IO; #endif namespace WorldTuningTool { using static Plugin; - public class LUT + public static class WorldLUTs { private const string addPath = "nativePC/plugins/CSharp/LUT"; - public LUT() { } + private static string[] builtinList = { + "native:\\light\\LUT\\CC_effect_type00_LUTM.tex", + "native:\\light\\LUT\\CC_event_A_type00_LUTM.tex", + "native:\\light\\LUT\\CC_event_B_type00_LUTM.tex", + "native:\\light\\LUT\\CC_event_darkB_type10_LUTM.tex", + "native:\\light\\LUT\\CC_event_darkG_type10_LUTM.tex", + "native:\\light\\LUT\\CC_event_darkR_type10_LUTM.tex", + "native:\\light\\LUT\\CC_event_dark_type00_LUTM.tex", + "native:\\light\\LUT\\CC_event_dark_type10_LUTM.tex", + "native:\\light\\LUT\\CC_event_evc0001_type00_LUTM.tex", + "native:\\light\\LUT\\CC_globalbase_LUTM.tex", + "native:\\light\\LUT\\CC_globalbaseSATU_LUTM.tex", + "native:\\light\\LUT\\CC_globalbase_stage_LUTM.tex", + "native:\\light\\LUT\\CC_st101day_global_type00_LUTM.tex", + "native:\\light\\LUT\\CC_st101day_global_type10_LUTM.tex", + "native:\\light\\LUT\\CC_st104day_global_type00_LUTM.tex", + "native:\\light\\LUT\\CC_st105day_global_type00_LUTM.tex", + "native:\\light\\LUT\\CC_title_st101d_type00_LUTM.tex", + "native:\\light\\LUT\\CC_title_st102d_type00_LUTM.tex", + "native:\\light\\LUT\\CC_title_st103d_type00_LUTM.tex", + "native:\\light\\LUT\\CC_title_st104d_type00_LUTM.tex", + "native:\\light\\LUT\\CC_title_st105d_type00_LUTM.tex" + }; // https://github.com/AsteriskAmpersand/CrappyLUTStudio--CLUTS-/blob/5af10daaa5f295b106cc5db09530a6fe5a4320d4/LUT.py#L35 - private byte[]? parseWorldLUT(BinaryReader reader) + private static byte[]? parseWorldLUT(BinaryReader reader) { byte[] signature = reader.ReadBytes(4); - if (!(signature[0] == 0x54 && signature[1] == 0x45 && - (signature[2] == 0x58 && signature[3] == 0x0))) + if (!(signature[0] == 0x54 && signature[1] == 0x45 && signature[2] == 0x58 && signature[3] == 0x0)) { return null; } - ulong version = reader.ReadUInt64(); - uint datablock = reader.ReadUInt32(); - uint format = reader.ReadUInt32(); - uint mipCount = reader.ReadUInt32(); + byte[] skip = reader.ReadBytes(20); uint width = reader.ReadUInt32(); uint height = reader.ReadUInt32(); - uint mipListCount = reader.ReadUInt32(); - uint typeData = reader.ReadUInt32(); + skip = reader.ReadBytes(8); uint depth = reader.ReadUInt32(); - byte[] NULL0 = reader.ReadBytes(12); - int NEG0 = reader.ReadInt32(); - byte[] NULL1 = reader.ReadBytes(8); - int Special = reader.ReadInt32(); - byte[] NULL2 = reader.ReadBytes(16); - byte[] NEG1 = reader.ReadBytes(32); - byte[] flags = reader.ReadBytes(32); - byte[] NULLX = reader.ReadBytes(32); + skip = reader.ReadBytes(140); reader.BaseStream.Position = (long)reader.ReadUInt64(); if (!(width == 32 && height == 32 && depth == 32)) { @@ -57,7 +67,7 @@ namespace WorldTuningTool // https://drive.google.com/file/d/143Eh08ZYncCAMwJ1q4gWxVOqR_OSWYvs/view // When does DOMAIN_MIN/MAX apply? - private byte[]? parseCubeLUT(StreamReader reader) + private static byte[]? parseCubeLUT(StreamReader reader) { string? line; Vector3[]? parsed = null; @@ -118,7 +128,7 @@ namespace WorldTuningTool return data; } - private unsafe bool overwriteFromStream(nint texture, Stream stream, bool cube = false) + private static unsafe bool overwriteFromStream(nint texture, Stream stream, bool cube = false) { byte[]? data = null; if (cube) @@ -150,7 +160,7 @@ namespace WorldTuningTool #endif } - private unsafe bool overwriteFromFile(nint texture, string path) + private static unsafe bool overwriteFromFile(nint texture, string path) { string ext = path.Split('.').Last().ToLower(); using (FileStream stream = File.Open(path, FileMode.Open)) @@ -159,17 +169,29 @@ namespace WorldTuningTool } } - private void reloadBlendLUT(nint lightingObject) + private static unsafe bool overwriteFromMtFile(nint texture, string path) + { + MtFileStream? file = MtFileStream.FromPath(path, OpenMode.Read, false); + bool success = false; + if (file != null) + { + success = overwriteFromStream(texture, new MemoryStream(file.Read(file.Length))); + file.Close(); + } + return success; + } + + private static void reloadBlendLUT(nint lightingObject) { MemoryUtil.GetRef<float>(lightingObject + 0x1D4) = MemoryUtil.GetRef<float>(lightingObject + 0x1D0) + 1.0f; } - private string[] fileList = []; + private static string[] fileList = []; private static string[] selectedFile = [ "", "" ]; private static bool[] selectionStarted = [ false, false ]; private static bool[] selectedInvalid = [ false, false ]; - public void DrawUI(nint texture, nint lightingObject, int i, float width) + public static void DrawUI(nint texture, nint lightingObject, int i, float width) { ImGui.PushID(i); string lutPath = Marshal.PtrToStringAnsi(texture + 0xC)!; @@ -177,14 +199,9 @@ namespace WorldTuningTool #if TEXTURE_FEATURE if (ImGui.Button("Reset")) { - MtFileStream? file = MtFileStream.FromPath($"native:\\{lutPath}.tex", OpenMode.Read, false); - if (file != null) + if (overwriteFromMtFile(texture, $"native:\\{lutPath}.tex")) { - if (overwriteFromStream(texture, new MemoryStream(file.Read(file.Length)))) - { - reloadBlendLUT(lightingObject); - } - file.Close(); + reloadBlendLUT(lightingObject); } selectedFile[i] = ""; selectedInvalid[i] = false; @@ -196,11 +213,24 @@ namespace WorldTuningTool { ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF); } - if (ImGui.BeginCombo("##LUT Files", selectedFile[i], ImGuiComboFlags.HeightLarge)) + bool beginCombo = ImGui.BeginCombo("##LUT Files", selectedFile[i], ImGuiComboFlags.HeightLarge); + if (prevWasInvalid) { - if (prevWasInvalid) + ImGui.PopStyleColor(); + } + if (beginCombo) + { + foreach (string nativePath in builtinList) { - ImGui.PopStyleColor(); + bool isSelected = selectedFile[i] == nativePath; + if (ImGui.Selectable(nativePath, isSelected)) + { + selectedFile[i] = nativePath; + if (overwriteFromMtFile(texture, nativePath)) + { + reloadBlendLUT(lightingObject); + } + } } if (!selectionStarted[i]) { @@ -224,10 +254,6 @@ namespace WorldTuningTool } else { - if (prevWasInvalid) - { - ImGui.PopStyleColor(); - } selectionStarted[i] = false; } #endif @@ -11,10 +11,8 @@ namespace WorldTuningTool { using static Plugin; - public class Lights + public static class Lights { - public Lights() { } - private class BaseLight { public nint Object = 0x0; @@ -497,89 +495,66 @@ namespace WorldTuningTool private delegate nint CreateMhObjectLight(); private delegate nint CreateMhObjectLight2(nint unknownPtr); private delegate nint DestroyMhObjectLight(nint mhObjectLightInternal, int unknownInt); - private Hook<CreateMhObjectLight>? createMhObjectLight; - private Hook<CreateMhObjectLight2>? createMhObjectLight2; - private Hook<DestroyMhObjectLight>? destroyMhObjectLight; + private static Hook<CreateMhObjectLight>? createMhObjectLight; + private static Hook<CreateMhObjectLight2>? createMhObjectLight2; + private static Hook<DestroyMhObjectLight>? destroyMhObjectLight; private delegate nint CreateLlkObjectLight(); private delegate nint CreateLlkObjectLight2(nint unknownPtr); private delegate nint DestroyLlkObjectLight(nint llkObjectLightInternal, int unknownInt); - private Hook<CreateLlkObjectLight>? createLlkObjectLight; - private Hook<CreateLlkObjectLight2>? createLlkObjectLight2; - private Hook<DestroyLlkObjectLight>? destroyLlkObjectLight; + private static Hook<CreateLlkObjectLight>? createLlkObjectLight; + private static Hook<CreateLlkObjectLight2>? createLlkObjectLight2; + private static Hook<DestroyLlkObjectLight>? destroyLlkObjectLight; #endif private delegate nint CreateLightObject(nint lightObject); private delegate nint DestroyLightObject(nint lightObjectInternal, int unknownInt); - private Hook<CreateLightObject>? createLightObject; - private static Dictionary<nint, Func<nint, uLight>> lightTypes = new Dictionary<nint, Func<nint, uLight>>() + private static Hook<CreateLightObject>? createLightObject; + private static Dictionary<long, Func<nint, uLight>> lightTypes = new Dictionary<long, Func<nint, uLight>>() { - { lton(0x143514168), (x) => new uLight(x) }, - { lton(0x143514288), (x) => new uInfiniteLight(x) }, - { lton(0x1434994D0), (x) => new uMhInfiniteLight(x) }, - { lton(0x1434954F0), (x) => new uMhActorInfiniteLight(x) }, - { lton(0x143494150), (x) => new uLlkInfiniteLight(x) }, - { lton(0x1434936A0), (x) => new uLlkActorInfiniteLight(x) }, - { lton(0x143493E30), (x) => new uLlkFollowCameraInfiniteLight(x) }, - { lton(0x1435143A8), (x) => new uPointLight(x) }, - { lton(0x14349A6C8), (x) => new uMhPointLight(x) }, - { lton(0x1434952B0), (x) => new uMhActorPointLight(x) }, - { lton(0x1434944E8), (x) => new uLlkPointLight(x) }, - { lton(0x143493460), (x) => new uLlkActorPointLight(x) }, - { lton(0x143493BF0), (x) => new uLlkFollowCameraPointLight(x) }, - { lton(0x1435144C8), (x) => new uSpotLight(x) }, - { lton(0x14349E280), (x) => new uMhSpotLight(x) }, - { lton(0x1434953D0), (x) => new uMhActorSpotLight(x) }, - { lton(0x143494888), (x) => new uLlkSpotLight(x) }, - { lton(0x143493580), (x) => new uLlkActorSpotLight(x) }, - { lton(0x1434937C0), (x) => new uLlkNullAngleSpotLight(x) }, - { lton(0x143493D10), (x) => new uLlkFollowCameraSpotLight(x) }, - { lton(0x1435145E8), (x) => new uHemiSphereLight(x) }, - { lton(0x143499378), (x) => new uMhHemiSphereLight(x) }, - { lton(0x143493F98), (x) => new uLlkHemiSphereLight(x) } - + { 0x143514168, (x) => new uLight(x) }, + { 0x143514288, (x) => new uInfiniteLight(x) }, + { 0x1434994D0, (x) => new uMhInfiniteLight(x) }, + { 0x1434954F0, (x) => new uMhActorInfiniteLight(x) }, + { 0x143494150, (x) => new uLlkInfiniteLight(x) }, + { 0x1434936A0, (x) => new uLlkActorInfiniteLight(x) }, + { 0x143493E30, (x) => new uLlkFollowCameraInfiniteLight(x) }, + { 0x1435143A8, (x) => new uPointLight(x) }, + { 0x14349A6C8, (x) => new uMhPointLight(x) }, + { 0x1434952B0, (x) => new uMhActorPointLight(x) }, + { 0x1434944E8, (x) => new uLlkPointLight(x) }, + { 0x143493460, (x) => new uLlkActorPointLight(x) }, + { 0x143493BF0, (x) => new uLlkFollowCameraPointLight(x) }, + { 0x1435144C8, (x) => new uSpotLight(x) }, + { 0x14349E280, (x) => new uMhSpotLight(x) }, + { 0x1434953D0, (x) => new uMhActorSpotLight(x) }, + { 0x143494888, (x) => new uLlkSpotLight(x) }, + { 0x143493580, (x) => new uLlkActorSpotLight(x) }, + { 0x1434937C0, (x) => new uLlkNullAngleSpotLight(x) }, + { 0x143493D10, (x) => new uLlkFollowCameraSpotLight(x) }, + { 0x1435145E8, (x) => new uHemiSphereLight(x) }, + { 0x143499378, (x) => new uMhHemiSphereLight(x) }, + { 0x143493F98, (x) => new uLlkHemiSphereLight(x) } }; - private static nint[] lightObjectDestructors = { - lton(0x142311FF0), // # uLight - lton(0x142311F40), // # uInfiniteLight - lton(0x141FB8F50), // # uMhInfiniteLight - lton(0x141F91DE0), // # uMhActorInfiniteLight - lton(0x141F855A0), // # uLlkInfiniteLight - lton(0x141F81940), // # uLlkActorInfiniteLight - lton(0x141F83B00), // # uLlkFollowCameraInfiniteLight - lton(0x142312070), // # uPointLight - lton(0x141FC0950), // # uMhPointLight - lton(0x141F91E80), // # uMhActorPointLight - lton(0x141F87D90), // # uLlkPointLight - lton(0x141F819B0), // # uLlkActorPointLight - lton(0x141F83B70), // # uLlkFollowCameraPointLight - lton(0x1423120F0), // # uSpotLight - lton(0x141FDE0D0), // # uMhSpotLight - lton(0x141F91F20), // # uMhActorSpotLight - lton(0x141F8B390), // # uLlkSpotLight - lton(0x141F81A20), // # uLlkActorSpotLight - lton(0x141F81A90), // # uLlkNullAngleSpotLight - lton(0x141F83BE0), // # uLlkFollowCameraSpotLight - lton(0x142311EC0), // # uHemiSphereLight - lton(0x141FB8C20), // # uMhHemiSphereLight - lton(0x141F84A40) // # uLlkHemiSphereLight - }; - private Hook<DestroyLightObject>[] lightObjectDestructorHooks = new Hook<DestroyLightObject>[lightObjectDestructors.Length]; + private static Hook<DestroyLightObject>[] lightObjectDestructorHooks = new Hook<DestroyLightObject>[lightTypes.Count()]; - private List<uLight> newLights = new List<uLight>(); - private List<uLight> sceneLights = new List<uLight>(); - private bool sortByDistanceToPlayerPoint = false; - private bool sortByDistanceToPlayerSpot = false; + private static List<uLight> newLights = new List<uLight>(); + private static List<uLight> sceneLights = new List<uLight>(); + private static bool sortByDistanceToPlayerPoint = false; + private static bool sortByDistanceToPlayerSpot = false; - private NativeAction<nint, int, nint, int> addToScene; - private NativeAction<nint> removeFromScene; - private List<uLight> ourLights = new List<uLight>(); + private static NativeFunction<nint> newPointLight; + private static NativeFunction<nint> newSpotLight; + private static NativeFunction<nint> newHemiSphereLight; + private static NativeAction<nint, int, nint, int> addToScene; + private static NativeAction<nint> removeFromScene; + private static List<uLight> ourLights = new List<uLight>(); #if HOOK_OBJECT_LIGHTS - private List<BaseLight> objectLights = new List<BaseLight>(); + private static List<BaseLight> objectLights = new List<BaseLight>(); #endif - public void Initialize() + public static void Initialize() { createLightObject = Hook.Create<CreateLightObject>(0x142311420, CreateLightObjectHook); DestroyLightObject[] destructorHookFuncs = { @@ -607,26 +582,29 @@ namespace WorldTuningTool DestroyLightObjectHook21, DestroyLightObjectHook22 }; - for (int i = 0; i < lightObjectDestructors.Length; i++) + for (int i = 0; i < lightTypes.Count(); i++) // Not ordered. { - lightObjectDestructorHooks[i] = Hook.Create<DestroyLightObject>(lightObjectDestructors[i], destructorHookFuncs[i]); + nint destructor = MemoryUtil.Read<nint>(lightTypes.Keys.ElementAt(i)); + lightObjectDestructorHooks[i] = Hook.Create<DestroyLightObject>(destructor, destructorHookFuncs[i]); } #if HOOK_OBJECT_LIGHTS createMhObjectLight = Hook.Create<CreateMhObjectLight>(0x141FBF290, CreateMhObjectLightHook); createMhObjectLight2 = Hook.Create<CreateMhObjectLight2>(0x141FBF500, CreateMhObjectLight2Hook); destroyMhObjectLight = Hook.Create<DestroyMhObjectLight>(0x141FBF6B0, DestroyMhObjectLightHook); - createLlkObjectLight = Hook.Create<CreateLlkObjectLight>(0x141F85DF0, CreateLlkObjectLightHook); createLlkObjectLight2 = Hook.Create<CreateLlkObjectLight2>(0x141F86090, CreateLlkObjectLight2Hook); destroyLlkObjectLight = Hook.Create<DestroyLlkObjectLight>(0x141F86270, DestroyLlkObjectLightHook); #endif + newPointLight = new NativeFunction<nint>(0x141FC0780); + newSpotLight = new NativeFunction<nint>(0x141FDDF00); + newHemiSphereLight = new NativeFunction<nint>(0x141FB8A50); addToScene = new NativeAction<nint, int, nint, int>(0x142219070); removeFromScene = new NativeAction<nint>(0x142228F10); } - public void PostUpdateLightLinker() + public static void PostUpdateLightLinker() { foreach (uLight light in sceneLights) { @@ -637,8 +615,10 @@ namespace WorldTuningTool } } - public void OnUpdate() + public static void OnUpdate() { + // @TODO: Safe to check newLights.Count > 0? + // Apparently that read would be guaranteed atomic in c#. lock (newLights) { for (int i = newLights.Count - 1; i >= 0; i--) @@ -648,7 +628,7 @@ namespace WorldTuningTool nint vTable = MemoryUtil.Read<nint>(light.Object); if (lightTypes.ContainsKey(vTable)) { - if (vTable == lton(0x143514168)) + if (vTable == 0x143514168) { Log.Error("Light is still uLight OnUpdate()."); } @@ -662,7 +642,7 @@ namespace WorldTuningTool } } - private nint CreateLightObjectHook(nint lightObject) + private static nint CreateLightObjectHook(nint lightObject) { lightObject = createLightObject!.Original(lightObject); uLight light = new uLight(lightObject); @@ -673,7 +653,7 @@ namespace WorldTuningTool return lightObject; } - private void cleanupCommon(nint lightObject) + private static void cleanupCommon(nint lightObject) { for (int i = 0; i < sceneLights.Count; i++) { @@ -707,138 +687,138 @@ namespace WorldTuningTool } } - private nint DestroyLightObjectHook0(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook0(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[0]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook1(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook1(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[1]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook2(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook2(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[2]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook3(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook3(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[3]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook4(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook4(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[4]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook5(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook5(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[5]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook6(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook6(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[6]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook7(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook7(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[7]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook8(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook8(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[8]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook9(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook9(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[9]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook10(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook10(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[10]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook11(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook11(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[11]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook12(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook12(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[12]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook13(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook13(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[13]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook14(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook14(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[14]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook15(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook15(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[15]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook16(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook16(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[16]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook17(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook17(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[17]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook18(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook18(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[18]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook19(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook19(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[19]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook20(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook20(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[20]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook21(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook21(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[21]!.Original(lightObject, unknownInt); } - private nint DestroyLightObjectHook22(nint lightObject, int unknownInt) + private static nint DestroyLightObjectHook22(nint lightObject, int unknownInt) { Assert(unknownInt == 1); cleanupCommon(lightObject); return lightObjectDestructorHooks[22]!.Original(lightObject, unknownInt); } #if HOOK_OBJECT_LIGHTS - private nint CreateMhObjectLightHook() + private static nint CreateMhObjectLightHook() { nint objectLight = createMhObjectLight!.Original(); objectLights.Add(new uMhObjectLight(objectLight)); return objectLight; } - private nint CreateMhObjectLight2Hook(nint unknownPtr) + private static nint CreateMhObjectLight2Hook(nint unknownPtr) { nint objectLight = createMhObjectLight2!.Original(unknownPtr); objectLights.Add(new uMhObjectLight(objectLight)); return objectLight; } - private nint DestroyMhObjectLightHook(nint mhObjectLightInternal, int unknownInt) + private static nint DestroyMhObjectLightHook(nint mhObjectLightInternal, int unknownInt) { Assert(unknownInt == 1); for (int i = 0; i < objectLights.Count; i++) @@ -853,21 +833,21 @@ namespace WorldTuningTool return destroyMhObjectLight!.Original(mhObjectLightInternal, unknownInt); } - private nint CreateLlkObjectLightHook() + private static nint CreateLlkObjectLightHook() { nint objectLight = createLlkObjectLight!.Original(); objectLights.Add(new uLlkObjectLight(objectLight)); return objectLight; } - private nint CreateLlkObjectLight2Hook(nint unknownPtr) + private static nint CreateLlkObjectLight2Hook(nint unknownPtr) { nint objectLight = createLlkObjectLight2!.Original(unknownPtr); objectLights.Add(new uLlkObjectLight(objectLight)); return objectLight; } - private nint DestroyLlkObjectLightHook(nint llkObjectLightInternal, int unknownInt) + private static nint DestroyLlkObjectLightHook(nint llkObjectLightInternal, int unknownInt) { Assert(unknownInt == 1); for (int i = 0; i < objectLights.Count; i++) @@ -883,7 +863,7 @@ namespace WorldTuningTool } #endif - private void DrawLights(IEnumerable<BaseLight> lights, float width) + private static void DrawLights(IEnumerable<BaseLight> lights, float width) { bool disableAll = ImGui.Button("Disable All"); if (ImGui.BeginItemTooltip()) @@ -964,26 +944,26 @@ namespace WorldTuningTool } } - public unsafe void DrawUI(float width) + public static unsafe void DrawUI(float width) { int lightType = -1; nint lightObject = 0x0; if (ImGui.Button("New Point Light")) { lightType = 2; - lightObject = new NativeFunction<nint>(0x141FC0780).Invoke(); + lightObject = newPointLight.Invoke(); } ImGui.SameLine(); if (ImGui.Button("New Spot Light")) { lightType = 3; - lightObject = new NativeFunction<nint>(0x141FDDF00).Invoke(); + lightObject = newSpotLight.Invoke(); } ImGui.SameLine(); if (ImGui.Button("New Hemi Sphere Light")) { lightType = 4; - lightObject = new NativeFunction<nint>(0x141FB8A50).Invoke(); + lightObject = newHemiSphereLight.Invoke(); } bool lightTook = false; lock (newLights) @@ -1051,7 +1031,7 @@ namespace WorldTuningTool ImGui.PushID("Infinite"); if (ImGui.CollapsingHeader("Infinite")) { - DrawLights(sceneLights.Where(x => (x.Type == 1)), width); + DrawLights(sceneLights.Where((x) => x.Type == 1), width); ImGui.Separator(); } ImGui.PopID(); @@ -1065,7 +1045,7 @@ namespace WorldTuningTool Vector3 pos = default; Player? player = Player.MainPlayer; if (player != null) pos = player.Position; - DrawLights(Enumerable.OrderBy<uLight, uLight>(sceneLights.Where(x => (x.Type == 2)), x => x, Comparer<uLight>.Create((x, y) => + DrawLights(Enumerable.OrderBy<uLight, uLight>(sceneLights.Where((x) => x.Type == 2), (x) => x, Comparer<uLight>.Create((x, y) => { Vector3 xPos = ((uPointLight)x).Position; if (((uPointLight)x).Parent != 0x0) @@ -1086,7 +1066,7 @@ namespace WorldTuningTool } else { - DrawLights(sceneLights.Where(x => (x.Type == 2)), width); + DrawLights(sceneLights.Where((x) => x.Type == 2), width); } ImGui.Separator(); } @@ -1101,7 +1081,7 @@ namespace WorldTuningTool Vector3 pos = default; Player? player = Player.MainPlayer; if (player != null) pos = player.Position; - DrawLights(Enumerable.OrderBy<uLight, uLight>(sceneLights.Where(x => (x.Type == 3)), x => x, Comparer<uLight>.Create((x, y) => + DrawLights(Enumerable.OrderBy<uLight, uLight>(sceneLights.Where((x) => x.Type == 3), (x) => x, Comparer<uLight>.Create((x, y) => { Vector3 xPos = ((uSpotLight)x).Position; if (((uSpotLight)x).Parent != 0x0) @@ -1122,7 +1102,7 @@ namespace WorldTuningTool } else { - DrawLights(sceneLights.Where(x => (x.Type == 3)), width); + DrawLights(sceneLights.Where((x) => x.Type == 3), width); } ImGui.Separator(); } @@ -1130,7 +1110,7 @@ namespace WorldTuningTool ImGui.PushID("HemiSphere"); if (ImGui.CollapsingHeader("Hemi Sphere")) { - DrawLights(sceneLights.Where(x => (x.Type == 4)), width); + DrawLights(sceneLights.Where((x) => x.Type == 4), width); ImGui.Separator(); } ImGui.PopID(); @@ -26,9 +26,8 @@ using SharpPluginLoader.Core.Resources; // @TODO: // - https://dev.epicgames.com/community/learning/tutorials/34xz/unreal-engine-ocio-3d-luts-applying-3d-luts-when-using-ocio -// - Add built-in LUT list. -// - Configurable Broad Area Shadow Resolution. // - Hook sMhScene constructor to set hqMode. +// - Configurable Broad Area Shadow Resolution. // - Optimized update logic. // - Only update non-override values when UI is shown. // - Descriptions. @@ -36,7 +35,6 @@ using SharpPluginLoader.Core.Resources; // - Lights iterop. // - SPL Patches: // - No crash on empty config. -// - Style change // - Hotload nukes config? // // Areas that need Shadow Distance retuning: @@ -79,8 +77,6 @@ namespace WorldTuningTool #endif } - public static nint lton(long l) { unchecked { return (nint)l; } } - private static byte ByteFlag(bool f) { return f ? (byte)0x1 : (byte)0x0; } private static int BitIndex(int mask) @@ -119,7 +115,7 @@ namespace WorldTuningTool public static Vector2 StringToVector2(string s, char delim = ',') { if (String.IsNullOrEmpty(s)) throw new FormatException(); - string[] sp = s.Split(delim).Select(v => v.Trim()).ToArray(); + string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray(); if (sp.Length != 2) throw new FormatException(); return new Vector2(StringToSingle(sp[0]), StringToSingle(sp[1])); } @@ -127,7 +123,7 @@ namespace WorldTuningTool public static Vector3 StringToVector3(string s, char delim = ',') { if (String.IsNullOrEmpty(s)) throw new FormatException(); - string[] sp = s.Split(delim).Select(v => v.Trim()).ToArray(); + string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray(); if (sp.Length != 3) throw new FormatException(); return new Vector3(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2])); } @@ -135,7 +131,7 @@ namespace WorldTuningTool public static Vector4 StringToVector4(string s, char delim = ',') { if (String.IsNullOrEmpty(s)) throw new FormatException(); - string[] sp = s.Split(delim).Select(v => v.Trim()).ToArray(); + string[] sp = s.Split(delim).Select((v) => v.Trim()).ToArray(); if (sp.Length != 4) throw new FormatException(); return new Vector4(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]), StringToSingle(sp[3])); } @@ -174,6 +170,12 @@ namespace WorldTuningTool SHADOW_RESOLUTION } + private const float defaultParamWidth = 0.21f; + private const float fadeAlphaFactor = 0.7f; + private const float disableAlphaFactor = 0.6f; + + private static bool ignoreMinMax = false; + private static IPlugin? Instance = null; private static Config getConfig() @@ -181,6 +183,11 @@ namespace WorldTuningTool return ConfigManager.GetConfig<Config>(Instance!); } + private static bool editMode = false; + private static int configState = 0; + private const int SelectedNotSaved = 1; + private const int SetNotSaved = (1 << 1); + private static void rebuildConfig(Config config, List<Override> overrides) { List<Override> selectedGlobals = config.Globals[selectedGlobal]; @@ -191,10 +198,6 @@ namespace WorldTuningTool } } - private static int configState = 0; - private const int SelectedNotSaved = 1; - private const int SetNotSaved = (1 << 1); - private static void saveConfig(Config config) { List<Override> tmpOverrides = config.Overrides[globalStage]; @@ -204,23 +207,15 @@ namespace WorldTuningTool configState = 0; } - private const float defaultParamWidth = 0.21f; - private const float fadeAlphaFactor = 0.7f; - private const float disableAlphaFactor = 0.6f; - - private static bool ignoreMinMax = false; - - private static bool editMode = false; - private const StageExt globalStage = StageExt.Global; private static StageExt currentStage => (StageExt)Area.CurrentStage; private static List<Override>? maybeGetStageOverrides(Config config) { - if (!config.Overrides.ContainsKey(currentStage)) + if (currentStage != StageExt.Global && config.Overrides.TryGetValue(currentStage, out List<Override>? stageOverrides)) { - return null; + return stageOverrides; } - return (currentStage != StageExt.Global) ? config.Overrides[currentStage] : null; + return null; } private static StageExt selectedStage = globalStage; @@ -925,7 +920,7 @@ namespace WorldTuningTool if (Type == ParameterType.COLOR_FACTOR) { Vector3 v3Color = v3; - // Only scale the color vector if max is unbound. Otherwise, assume that intensity and color are combined. + // Only scale the color vector if max is unbound. Otherwise, assume that intensity and color are seperate. if (maxf == Single.MaxValue) { float v3Max = MathF.Max(Math.Abs(v3.X), MathF.Max(Math.Abs(v3.Y), Math.Abs(v3.Z))); @@ -1265,6 +1260,11 @@ namespace WorldTuningTool return new Parameter<T>(name, offset, 0, type, m.min, m.max, m.step, 0); } + public static Parameter<T> P<T>(string name, long offset, ParameterType type, (T? min, T? max, T? step) m = default) where T : unmanaged + { + return new Parameter<T>(name, (nint)offset, 0, type, m.min, m.max, m.step, 0); + } + public static Parameter<T> V<T>(string name, nint offset, ParameterType type, (T? min, T? max, T? step) m = default) where T : unmanaged { return new Parameter<T>(name, offset, 0, type, m.min, m.max, m.step, ParameterFlags.ViewOnly); @@ -1277,6 +1277,11 @@ namespace WorldTuningTool private static Parameter? getParameterByName(string name) { + if (OldParameterNames.TryGetValue(name, out string? newName)) + { + Log.Warn($"Paramter '{name}' renamed to {newName}."); + name = newName; + } foreach (Parameter param in allParameters) { if (param.Name == name) @@ -1579,7 +1584,7 @@ namespace WorldTuningTool } hasStatus = true; } - else if (valueDiffers) + else if (valueDiffers || superseded) { ImGui.SameLine(); string byLine = ""; @@ -1616,8 +1621,8 @@ namespace WorldTuningTool private delegate void UpdateSSLRParams(nint stackOffset); private Hook<UpdateSSLRParams>? updateSSLRParams; - private delegate void UpdateLightingParams(nint stackOffset, nint lightingObjectInternal); - private Hook<UpdateLightingParams>? updateLightingParams; + private delegate void UpdateToneMapParams(nint stackOffset, nint toneMapObjectInternal); + private Hook<UpdateToneMapParams>? updateToneMapParams; private static bool InTransition = false; private static List<Parameter> DirtyParams = new List<Parameter>(); @@ -1645,9 +1650,9 @@ namespace WorldTuningTool private static MtObject? sLightLinker = null; private static bool disableLightsFeature = false; - private static Lights lights = new Lights(); private static Parameter hqMode = P<bool>("HQ Mode", 0xE9A3, ParameterType.BOOL); + private static Patch defaultHqMode; private static bool setWeatherMode = false; private static int requestWeatherMode = 1; @@ -1661,16 +1666,25 @@ namespace WorldTuningTool P<float>("LOD Bias 1", 0x21C, ParameterType.FLOAT, pMin(0.0f)), P<float>("LOD Bias 2", 0x220, ParameterType.FLOAT, pMin(0.0f)), P<float>("LOD Caster Bias", 0x1E4, ParameterType.FLOAT, pMin(0.0f)), - // If platform is PS4/Xbox/PC it appears [2] is PC. - P<float>("LOD Length Platform Bias[2]", 0x22C + (4 * 2), ParameterType.FLOAT, pMin(0.0f)), - P<float>("LOD Pixel Size Platform Bias[2]", 0x244 + (4 * 2), ParameterType.FLOAT, pMin(0.0f)), P<int>("LOD Limit", 0xE898, ParameterType.INT, pStep(1)), P<float>("LOD Passthrough Culling Rate", 0x1F0, ParameterType.FLOAT, pMin(0.0f)), P<float>("LOD Far Culling Fade Length Max", 0x20C, ParameterType.FLOAT, pMin(0.0f)), P<float>("LOD Far Culling Fade Pixel Max", 0x210, ParameterType.FLOAT, pMin(0.0f)), P<float>("Speed Tree LOD Billboard Fade Range", 0x214, ParameterType.FLOAT, pMin(0.0f)), P<float>("LOD Culling Length Bias", 0x224, ParameterType.FLOAT, pMin(0.0f)), - P<float>("LOD Culling Pixel Bias", 0x228, ParameterType.FLOAT, pMin(0.0f)) + P<float>("LOD Culling Pixel Bias", 0x228, ParameterType.FLOAT, pMin(0.0f)), + // Length/Pixel Size bias only apply when Bias 1/2 are 0. + // MonsterHunterWorld.exe+1B19AA1 - comiss xmm0,xmm1 + P<float>("LOD Length Bias", 0x1F4, ParameterType.FLOAT, pMin(0.0f)), + P<float>("LOD Length Bias (HQ)", 0x1FC, ParameterType.FLOAT, pMin(0.0f)), + // MonsterHunterWorld.exe+1B19B95 - comiss xmm1,xmm0 + P<float>("LOD Pixel Size Bias", 0x200, ParameterType.FLOAT, pMin(0.0f)), + P<float>("LOD Pixel Size Bias (HQ)", 0x208, ParameterType.FLOAT, pMin(0.0f)), + // Factor applied to the result of LOD Bias 1/2 or Length/Pixel Size Bias. + // MonsterHunterWorld.exe+222F7C4 - mulss xmm4,xmm6 + // If platform is PS4/Xbox/PC it appears [2] is PC. + P<float>("LOD Length Platform Bias[2]", 0x22C + (4 * 2), ParameterType.FLOAT, pMin(0.0f)), + P<float>("LOD Pixel Size Platform Bias[2]", 0x244 + (4 * 2), ParameterType.FLOAT, pMin(0.0f)) }; private static Parameter[] snowParameters = { @@ -1687,6 +1701,7 @@ namespace WorldTuningTool P<float>("Passthrough Correct", 0xE950, ParameterType.FLOAT) }; + private static Parameter shadowResParameter = P<int>("Shadow Resolution Multiplier", 0, ParameterType.SHADOW_RESOLUTION, pStep(1)); private static Parameter[] shadowCascadeParameters = { P<bool>("Primary Shadow HQ", 0xE5C0, ParameterType.BOOL), P<bool>("Primary Shadow HQ (HQ)", 0xE5C2, ParameterType.BOOL), @@ -1704,11 +1719,87 @@ namespace WorldTuningTool P<int>("Broad Area Shadow Precision", 0x5518, ParameterType.INT, pMinMaxStep(0, 2, 1)) }; + private delegate void UpdatePrimaryLightParams(nint primaryLightParams, nint stackOffset); + private delegate void StaticPrimaryLightParams(nint primaryLightParamsStatic, nint primaryLightObjectInternal); + private Hook<UpdatePrimaryLightParams>? updatePrimaryLightParams; + private Hook<StaticPrimaryLightParams>? staticPrimaryLightParams; + // "Min Roughness" is +0xFC in params but never read. + private static Parameter[] primaryLightParameters = { + M<int>("Primary Light Group", 0x14, ParameterType.BITS, 0x7), + P<byte>("Primary Light Priority", 0x1A, ParameterType.BYTE), + P<float>("Primary Light Direction", 0x110, ParameterType.VECTOR3, pStep(0.00025f)), + P<float>("Primary Light Color", 0xE0, ParameterType.COLOR_FACTOR, pMaxStep(1.0f, 0.001f)), + P<float>("Primary Light Intensity", 0xF4, ParameterType.FLOAT, pStep(0.005f)), + P<bool>("Primary Light Is Primary", 0x1D, ParameterType.BOOL), + P<float>("Primary Light Projection Scale", 0x134, ParameterType.VECTOR2), + P<float>("Primary Light Projection Offset Speed", 0x144, ParameterType.VECTOR2), + P<float>("Primary Light Projection Up", 0x160, ParameterType.VECTOR3), + P<bool>("Primary Light Do Volumetric", 0x1F, ParameterType.BOOL), + P<bool>("Primary Shadow Cast", 0x23, ParameterType.BOOL), + P<int>("Primary Shadow Map Size", 0x30, ParameterType.ALIGNED_INT, pMinStep(0, 128)), // 0 = 64x64 no multiplier @TODO: Verify in the code. + P<float>("Primary Shadow Near Clip Distance", 0x28, ParameterType.FLOAT), + P<bool>("Primary Shadow Is Fixed Fov Mode", 0x1F9, ParameterType.BOOL), + P<float>("Primary Shadow Fov", 0x1F4, ParameterType.FLOAT, pStep(0.0001f)), + P<bool>("Primary Shadow Is Discretization Fov Mode", 0x205, ParameterType.BOOL), + P<float>("Primary Shadow Discretization Angle", 0x200, ParameterType.FLOAT, pStep(0.0001f)), + P<int>("Primary Shadow Cascade Mode", 0x174, ParameterType.INT, pMinMaxStep(0, 3, 1)), + P<float>("Primary Shadow Cascade 2Way Bias", 0x17C, ParameterType.FLOAT), + P<float>("Primary Shadow Cascade Distance", 0x6C, ParameterType.FLOAT, pStep(5.0f)), + P<float>("Primary Shadow Cascade Backforward Distance", 0x7C, ParameterType.FLOAT, pStep(5.0f)), + P<float>("Primary Shadow Cascade Distribution", 0x74, ParameterType.FLOAT, pStep(0.001f)), + P<bool>("Primary Shadow Cascade Manual Split", 0x4D, ParameterType.BOOL), + P<float>("Primary Shadow Cascade Manual Split Distance[0]", 0x54, ParameterType.FLOAT), + P<float>("Primary Shadow Cascade Manual Split Distance[1]", 0x5C, ParameterType.FLOAT), + P<float>("Primary Shadow Cascade Manual Split Distance[2]", 0x64, ParameterType.FLOAT), + P<float>("Primary Shadow Sloped Depth Bias", 0x40, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Depth Bias", 0x38, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Max Depth Bias", 0x48, ParameterType.FLOAT, pStep(0.00001f)), + P<bool>("Primary Shadow Cascade Individual Shadow Bias", 0x81, ParameterType.BOOL), + P<float>("Primary Shadow Cascade Depth Bias[0]", 0x88, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Sloped Depth Bias[0]", 0xA0, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Max Depth Bias[0]", 0xB8, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Depth Bias[1]", 0x90, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Sloped Depth Bias[1]", 0xA8, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Max Depth Bias[1]", 0xC0, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Depth Bias[2]", 0x98, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Sloped Depth Bias[2]", 0xB0, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Primary Shadow Cascade Max Depth Bias[2]", 0xC8, ParameterType.FLOAT, pStep(0.00001f)), + }; + private static Parameter[] primaryShadowParameters = { + P<int>("Primary Shadow Sample Num", 0x1DC, ParameterType.INT, pStep(1)), + P<float>("Primary Shadow Radius", 0x1EC, ParameterType.FLOAT, pStep(0.0001f)) + }; + private static Parameter[] primaryBroadAreaParameters = { + P<float>("Broad Area Shadow Depth Bias", 0x1C4, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Broad Area Shadow Sloped Depth Bias", 0x1CC, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Broad Area Shadow Max Depth Bias", 0x1D4, ParameterType.FLOAT, pStep(0.00001f)), + }; + + private static MtObject? sLightProbes = null; + private static Parameter[] sLightProbesParameters = { + P<int>("Light Probes Probe Color", 0x38, ParameterType.COLOR), + P<float>("Light Probes Probe Intensity", 0x3C, ParameterType.FLOAT), + P<int>("Light Probes Top Color", 0x44, ParameterType.COLOR), + P<float>("Light Probes Top Intensity", 0x48, ParameterType.FLOAT), + P<int>("Light Probes Bottom Color", 0x4C, ParameterType.COLOR), + P<float>("Light Probes Bottom Intensity", 0x50, ParameterType.FLOAT), + P<float>("Light Probes Direction", 0x60, ParameterType.VECTOR3), + P<int>("Light Probes Shadow Top Color", 0x70, ParameterType.COLOR), + P<float>("Light Probes Shadow Top Intensity", 0x74, ParameterType.FLOAT), + P<int>("Light Probes Shadow Bottom Color", 0x78, ParameterType.COLOR), + P<float>("Light Probes Shadow Bottom Intensity", 0x7C, ParameterType.FLOAT), + P<float>("Light Probes Shadow Direction", 0x80, ParameterType.VECTOR3), + P<int>("Light Probes Daytime State", 0x9C, ParameterType.INT, pMinMaxStep(0, 6, 1)), + P<float>("Light Probes Daytime Interpolation", 0xA0, ParameterType.FLOAT), + P<int>("Light Probes Max Iter", 0xA4, ParameterType.INT), + P<int>("Light Probes Debug Mode", 0x98, ParameterType.INT, pStep(1)) + }; + private static Parameter[] contactShadowParameters = { P<float>("Fake Light Intensity", 0xEC40, ParameterType.FLOAT), // MonsterHunterWorld.exe+1B18711 - mov [rbx+0000EC44],3F800000 (Other unknown reference). - P<float>("Fake Light Intensity (Gameplay)", lton(0x141B1A19F) + 0x6, ParameterType.PATCH_FLOAT), - P<float>("Fake Light Blend", lton(0x141CDE0CE) + 0x6, ParameterType.PATCH_FLOAT), + P<float>("Fake Light Intensity (Gameplay)", 0x141B1A19F + 0x6, ParameterType.PATCH_FLOAT), + P<float>("Fake Light Blend", 0x141CDE0CE + 0x6, ParameterType.PATCH_FLOAT), P<bool>("Force Disable Contact Shadows", 0xB4ED, ParameterType.BOOL), P<bool>("Facial Contact Shadows Enabled", 0xB4EE, ParameterType.BOOL), P<bool>("Facial Contact Shadows Enable Noise", 0xB501, ParameterType.BOOL), @@ -1745,6 +1836,57 @@ namespace WorldTuningTool P<float>("SSAO Edge Atten Rate", 0xB4DC, ParameterType.FLOAT, pStep(0.001f)) }; + private static MtObject? sVolumeRenderer = null; + private static Parameter[] sVolumeRendererParameters = { + P<bool>("Volume Rendering Enabled", 0x38, ParameterType.BOOL) + }; + + private delegate nint CreateToneMapObject(); + private delegate nint DestroyToneMapObject(nint toneMapObjectInternal, int unknownInt); + private Hook<CreateToneMapObject>? createToneMapObject; + private Hook<DestroyToneMapObject>? destroyToneMapObject; + private nint toneMapObject = 0x0; + private static Parameter[] toneMapParameters = { + P<int>("Tone Map Type", 0x16C, ParameterType.INT, pMinMaxStep(1, 9, 1)), + P<bool>("Tone Map Compute Luminance", 0x170, ParameterType.BOOL), + P<bool>("Tone Map Luminance Version", 0x168, ParameterType.BOOL), + P<float>("Tone Map Shoulder Strength", 0x174, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map Linear Strength", 0x178, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map Linear Angle", 0x17C, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map Toe Strength", 0x180, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map Toe Num", 0x184, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map Toe Denum", 0x188, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Tone Map White Point", 0x18C, ParameterType.FLOAT, pStep(0.01f)), + P<float>("Color Grading LUT Blend", 0x1C8, ParameterType.FLOAT, pMinMaxStep(0.0f, 1.0f, 0.01f)), + P<float>("Color Grading Vfx LUT Blend", 0x1D0, ParameterType.FLOAT, pMinMaxStep(0.0f, 1.0f, 0.01f)), + P<bool>("Color Grading Enable", 0x1D8, ParameterType.BOOL), + P<bool>("Color Grading Is Linear To PQ", 0x1A1, ParameterType.BOOL), + P<bool>("Color Grading Is PQ To Linear", 0x1A0, ParameterType.BOOL), + P<float>("Volume Dispersion", 0x19C, ParameterType.FLOAT), + P<float>("Volume Edge Sharpness", 0x198, ParameterType.FLOAT, pStep(0.00001f)), + P<bool>("Volume Downsample", 0x210, ParameterType.BOOL) + }; + private static Parameter[] exposureParameters = { + P<float>("Exposure Bt Adaption Limit", 0x460, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure Bt Sensitivity", 0x458, ParameterType.FLOAT, pMaxStep(1.0f, 0.001f)), + P<float>("Exposure Dk Adaption Limit", 0x464, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure Dk Sensitivity", 0x45C, ParameterType.FLOAT, pMaxStep(1.0f, 0.001f)), + P<float>("Exposure Value", 0x474, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure Min White Point", 0x470, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure Max White Point", 0x46C, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure Mid Gray", 0x454, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Exposure White Range", 0x468, ParameterType.FLOAT, pMinMaxStep(0.0f, 1.0f, 0.001f)) + }; + private static Parameter[] brightnessParameters = { + P<float>("Gamma Correct", 0x1C8, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Gamma Correct EX", 0x1CC, ParameterType.FLOAT, pStep(0.001f)), + V<bool>("Hdr Output", 0x21A, ParameterType.BOOL), + P<float>("Hdr Output White Level", 0x21C, ParameterType.FLOAT, pStep(0.05f)), + P<float>("Hdr Output Gamut Mapping Ratio", 0x220, ParameterType.FLOAT, pStep(0.001f)), + P<float>("Hdr Output Gamma", 0x224, ParameterType.FLOAT, pStep(0.001f)), + P<bool>("Hdr Is Gui Hdr Gamma", 0x228, ParameterType.BOOL) + }; + private static Parameter[] sslrParameters = { P<int>("SSLR Loop Count", 0xE628, ParameterType.INT, pStep(1)), P<float>("SSLR Loop Count Factor for CBR", 0xE62C, ParameterType.FLOAT), @@ -1764,116 +1906,12 @@ namespace WorldTuningTool P<float>("SSLR Intensity", 0xB424, ParameterType.FLOAT) }; - private static Parameter shadowResParameter = P<int>("Shadow Resolution Multiplier", 0, ParameterType.SHADOW_RESOLUTION, pStep(1)); - private delegate void UpdateShadowParams(nint shadowParams, nint stackOffset); - private delegate void StaticShadowParams(nint shadowParamsStatic, nint shadowObjectInternal); - private Hook<UpdateShadowParams>? updateShadowParams; - private Hook<StaticShadowParams>? staticShadowParams; - private static Parameter[] shadowParameters1 = { - }; - // These are parameters for an Infinite Light object (uSdlInfinite @ 0x143343038). - // "Min Roughness" is +0xFC in params but is never read. - private static Parameter[] shadowParameters2 = { - P<int>("Sunlight Group", 0x14, ParameterType.INT, pMinMaxStep(1, 255, 1)), - P<float>("Sunlight Direction", 0x110, ParameterType.VECTOR3, pStep(0.00025f)), - P<float>("Sunlight Color", 0xE0, ParameterType.COLOR_FACTOR, pMaxStep(1.0f, 0.001f)), - P<float>("Sunlight Intensity", 0xF4, ParameterType.FLOAT, pStep(0.005f)), - P<bool>("Sunlight Is Primary", 0x1D, ParameterType.BOOL), - P<bool>("Do Volumetric", 0x1F, ParameterType.BOOL), - P<bool>("Shadow Cast", 0x23, ParameterType.BOOL), - P<int>("Shadow Map Size", 0x30, ParameterType.ALIGNED_INT, pMinStep(0, 128)), // 0 = 64x64 no multiplier @TODO: Verify in the code. - P<float>("Shadow Near Clip Distance", 0x28, ParameterType.FLOAT), - P<int>("Shadow Cascade Mode", 0x174, ParameterType.INT, pMinMaxStep(0, 3, 1)), - P<float>("Shadow Cascade 2Way Bias", 0x17C, ParameterType.FLOAT), - P<float>("Shadow Distance", 0x6C, ParameterType.FLOAT, pStep(5.0f)), - P<float>("Shadow Backforward Distance", 0x7C, ParameterType.FLOAT, pStep(5.0f)), - P<bool>("Shadow Is Fixed Fov Mode", 0x1F9, ParameterType.BOOL), - P<float>("Shadow Fov", 0x1F4, ParameterType.FLOAT, pStep(0.0001f)), - P<bool>("Shadow Is Discretization Fov Mode", 0x205, ParameterType.BOOL), - P<float>("Shadow Discretization Angle", 0x200, ParameterType.FLOAT, pStep(0.0001f)), - P<float>("Shadow Distribution", 0x74, ParameterType.FLOAT, pStep(0.001f)), - P<bool>("Cascade Manual Split", 0x4D, ParameterType.BOOL), - P<float>("Cascade Manual Split Distance[0]", 0x54, ParameterType.FLOAT), - P<float>("Cascade Manual Split Distance[1]", 0x5C, ParameterType.FLOAT), - P<float>("Cascade Manual Split Distance[2]", 0x64, ParameterType.FLOAT), - P<float>("Shadow Sloped Depth Bias", 0x40, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Shadow Depth Bias", 0x38, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Shadow Max Depth Bias", 0x48, ParameterType.FLOAT, pStep(0.00001f)), - P<bool>("Cascade Individual Shadow Bias", 0x81, ParameterType.BOOL), - P<float>("Cascade Depth Bias[0]", 0x88, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Sloped Depth Bias[0]", 0xA0, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Max Depth Bias[0]", 0xB8, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Depth Bias[1]", 0x90, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Sloped Depth Bias[1]", 0xA8, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Max Depth Bias[1]", 0xC0, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Depth Bias[2]", 0x98, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Sloped Depth Bias[2]", 0xB0, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Cascade Max Depth Bias[2]", 0xC8, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Broad Area Shadow Depth Bias", 0x1C4, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Broad Area Shadow Sloped Depth Bias", 0x1CC, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Broad Area Shadow Max Depth Bias", 0x1D4, ParameterType.FLOAT, pStep(0.00001f)), - P<float>("Projection Scale", 0x134, ParameterType.VECTOR2), - P<float>("Projection Offset Speed", 0x144, ParameterType.VECTOR2), - P<float>("Projection Up", 0x160, ParameterType.VECTOR3), - P<int>("Primary Shadow Sample Num", 0x1DC, ParameterType.INT, pStep(1)), - P<float>("Primary Shadow Radius", 0x1EC, ParameterType.FLOAT, pStep(0.0001f)) - }; - - private static MtObject? sLightProbes = null; - private delegate void UpdateLightProbesParams(nint unknownPtr, int unknownInt); - private static Parameter[] sLightProbesParameters = { - P<int>("Light Probes Probe Color", 0x38, ParameterType.COLOR), - P<float>("Light Probes Probe Intensity", 0x3C, ParameterType.FLOAT), - P<int>("Light Probes Top Color", 0x44, ParameterType.COLOR), - P<float>("Light Probes Top Intensity", 0x48, ParameterType.FLOAT), - P<int>("Light Probes Bottom Color", 0x4C, ParameterType.COLOR), - P<float>("Light Probes Bottom Intensity", 0x50, ParameterType.FLOAT), - P<float>("Light Probes Direction", 0x60, ParameterType.VECTOR3), - P<int>("Light Probes Shadow Top Color", 0x70, ParameterType.COLOR), - P<float>("Light Probes Shadow Top Intensity", 0x74, ParameterType.FLOAT), - P<int>("Light Probes Shadow Bottom Color", 0x78, ParameterType.COLOR), - P<float>("Light Probes Shadow Bottom Intensity", 0x7C, ParameterType.FLOAT), - P<float>("Light Probes Shadow Direction", 0x80, ParameterType.VECTOR3), - P<int>("Light Probes Daytime State", 0x9C, ParameterType.INT, pMinMaxStep(0, 6, 1)), - P<float>("Light Probes Daytime Interpolation", 0xA0, ParameterType.FLOAT), - P<int>("Light Probes Max Iter", 0xA4, ParameterType.INT), - P<int>("Light Probes Debug Mode", 0x98, ParameterType.INT, pStep(1)) - }; - - private delegate nint CreateLightingObject(); - private delegate nint DestroyLightingObject(nint lightingObjectInternal, int unknownInt); - private Hook<CreateLightingObject>? createLightingObject; - private Hook<DestroyLightingObject>? destroyLightingObject; - private nint lightingObject = 0x0; - private static LUT luts = new LUT(); - private static Parameter[] lightingParameters = { - P<int>("Light Tone Map Type", 0x16C, ParameterType.INT, pMinMaxStep(1, 6, 1)), - P<bool>("Light Compute Luminance", 0x170, ParameterType.BOOL), - P<bool>("Light Luminance Version", 0x168, ParameterType.BOOL), - P<float>("Light Shoulder Strength", 0x174, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light Linear Strength", 0x178, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light Linear Angle", 0x17C, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light Toe Strength", 0x180, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light Toe Num", 0x184, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light Toe Denum", 0x188, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Light White Point", 0x18C, ParameterType.FLOAT, pStep(0.01f)), - P<float>("Light LUT Blend", 0x1C8, ParameterType.FLOAT, pMinMaxStep(0.0f, 1.0f, 0.01f)), - P<float>("Light Vfx LUT Blend", 0x1D0, ParameterType.FLOAT, pMinMaxStep(0.0f, 1.0f, 0.01f)), - P<bool>("Light Enable Color Grading", 0x1D8, ParameterType.BOOL), - P<bool>("Light Is Linear To PQ", 0x1A1, ParameterType.BOOL), - P<bool>("Light Is PQ To Linear", 0x1A0, ParameterType.BOOL), - P<float>("Volume Dispersion", 0x19C, ParameterType.FLOAT), - P<float>("Volume Edge Sharpness", 0x198, ParameterType.FLOAT, pStep(0.00001f)), - P<bool>("Volume Downsample", 0x210, ParameterType.BOOL) - }; - private static Parameter[] brightnessParameters = { - P<float>("Gamma Correct", 0x1C8, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Gamma Correct EX", 0x1CC, ParameterType.FLOAT, pStep(0.001f)), - V<bool>("Hdr Output", 0x21A, ParameterType.BOOL), - P<float>("Hdr Output White Level", 0x21C, ParameterType.FLOAT, pStep(0.05f)), - P<float>("Hdr Output Gamut Mapping Ratio", 0x220, ParameterType.FLOAT, pStep(0.001f)), - P<float>("Hdr Output Gamma", 0x224, ParameterType.FLOAT, pStep(0.001f)), - P<bool>("Hdr Is Gui Hdr Gamma", 0x228, ParameterType.BOOL) + private delegate nint CreateRenderPassesObject(nint unknownPtr1, nint unknownPtr2); + private delegate nint DestroyRenderPassesObject(nint renderPassesObjectInternal, int unknownInt); + private Hook<CreateRenderPassesObject>? createRenderPassesObject; + private Hook<DestroyRenderPassesObject>? destroyRenderPassesObject; + private nint renderPassesObject = 0x0; + private static Parameter[] renderPassesParameters = { }; private delegate nint CreateBloomObject(); @@ -2089,6 +2127,30 @@ namespace WorldTuningTool P<float>("Fog Mip Fog Color", 0x330, ParameterType.COLOR_FACTOR, pStep(0.001f)) }; + private static MtObject? sMhSpeedTree = null; + private static Parameter[] speedTreeParameters = { + //P<bool>("Speed Tree is Active", 0x339, ParameterType.BOOL), + P<bool>("Speed Tree Wind Active", 0x33A, ParameterType.BOOL), + //P<bool>("Speed Tree System Wind Active", 0x33C, ParameterType.BOOL), + //P<bool>("Speed Tree Disp Off Water Reflection", 0x33B, ParameterType.BOOL), + P<float>("Speed Tree Wind Direction", 0x210 + 0x30, ParameterType.VECTOR3), + P<float>("Speed Tree Wind Strength", 0x210 + 0x40, ParameterType.FLOAT), + /* + P<float>("Speed Tree Wind Strength Response", 0x210 + 0x44, ParameterType.FLOAT), + P<float>("Speed Tree Wind Direction Response", 0x210 + 0x48, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Frequency", 0x210 + 0x4C, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Strength Min", 0x210 + 0x50, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Strength Max", 0x210 + 0x54, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Duration Min", 0x210 + 0x58, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Duration Max", 0x210 + 0x5C, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Rise Scalar", 0x210 + 0x60, ParameterType.FLOAT), + P<float>("Speed Tree Wind Gust Fall Scalar", 0x210 + 0x64, ParameterType.FLOAT), + P<bool>("Speed Tree Wind Gust Enable", 0x210 + 0x68, ParameterType.BOOL), + P<float>("Speed Tree Wind Instance Delay", 0x32C, ParameterType.FLOAT), + P<float>("Speed Tree Wind Blend Length", 0x328, ParameterType.FLOAT) + */ + }; + private delegate nint CreateWaterWaveObject(nint unknownPtr); private delegate nint DestroyWaterWaveObject(nint waterWaveObjectInternal, int unknownInt); private Hook<CreateWaterWaveObject>? createWaterWaveObject; @@ -2134,24 +2196,29 @@ namespace WorldTuningTool .Concat(sTimeParameters) .Concat(lodParameters) .Concat(snowParameters) + .Concat(passthroughParameters) .Append(shadowResParameter) - .Concat(shadowParameters2) .Concat(shadowCascadeParameters) + .Concat(primaryShadowParameters) .Concat(broadAreaShadowParameters) + .Concat(primaryBroadAreaParameters) + .Concat(primaryLightParameters) .Concat(sLightProbesParameters) .Concat(contactShadowParameters) .Concat(capsuleLightParameters) .Concat(ssaoParameters) - .Concat(sslrParameters) - .Concat(passthroughParameters) - .Concat(lightingParameters) + .Concat(sVolumeRendererParameters) + .Concat(toneMapParameters) + .Concat(exposureParameters) .Concat(brightnessParameters) + .Concat(sslrParameters) .Concat(bloomParameters) .Concat(dofParameters) .Concat(motionBlurParameters) .Concat(hazeParameters) .Concat(simpleSkyParameters) .Concat(fogParameters) + .Concat(speedTreeParameters) .Concat(waterWaveParameters) .Concat(fxaaParameters) .Concat(taaParameters) @@ -2329,6 +2396,12 @@ namespace WorldTuningTool private bool continousSSLRTemporalReset = false; private Patch forceSSLRTemporalReset; +#if SHADER_FEATURES + private bool volumeUpsampleNoLinear = false; + private bool fxaaMaxQuality = false; + private bool skinAllowNegativeWet = false; +#endif + private bool fullResVolumeBlur = false; private Patch volumeSars1; private Patch volumeSars2; @@ -2394,11 +2467,21 @@ namespace WorldTuningTool defaultViewModeLODLimit_4.Disable(); } + private Patch defaultCharaCreatorParam; + private bool charaCreatorFace = false; + private bool largerFoliageSwayRange = false; private Patch addressHigherValueForFoliageSway; private bool disableReducedRateAnimations = false; + private bool disableReducedRateAnimations2 = false; private Patch zeroFrameSkip; + private Patch zeroFrameSkip2; + private Patch zeroFrameSkip3; + + private bool viewModeLodOverride = false; + private Patch viewModeAddressLod1; + private Patch viewModeAddressLod2; private bool nukeEffects = false; private Patch jmpOverEffects; @@ -2458,7 +2541,7 @@ namespace WorldTuningTool // Assert no duplicate names. foreach (Parameter param in allParameters) { - Assert(Array.FindAll(allParameters, (p => p.Name == param.Name)).Length == 1); + Assert(Array.FindAll(allParameters, ((p) => p.Name == param.Name)).Length == 1); } // Assert OrderedStages covers all values. @@ -2475,54 +2558,60 @@ namespace WorldTuningTool // Used for: // "Capsule AO Intensity". // "Broad Area Shadow Direction". Otherwise it will flicker on center change. - evaluateSceneParams = Hook.Create<EvaluateSceneParams>(0x1423C3790, EvaluateSceneParamsHook); // nint, nint, int, nint + evaluateSceneParams = Hook.Create<EvaluateSceneParams>(0x1423C3790, EvaluateSceneParamsHook); // These run in a loop during cutscenes. - updateSSAOParams = Hook.Create<UpdateSSAOParams>(0x1416D8B10, UpdateSSAOParamsHook); // nint - updateSSLRParams = Hook.Create<UpdateSSLRParams>(0x1416DA3F0, UpdateSSLRParamsHook); // nint - updateLightingParams = Hook.Create<UpdateLightingParams>(0x1416DAAB0, UpdateLightingParamsHook); // nint, nint + updateSSAOParams = Hook.Create<UpdateSSAOParams>(0x1416D8B10, UpdateSSAOParamsHook); + updateSSLRParams = Hook.Create<UpdateSSLRParams>(0x1416DA3F0, UpdateSSLRParamsHook); + updateToneMapParams = Hook.Create<UpdateToneMapParams>(0x1416DAAB0, UpdateToneMapParamsHook); + + createToneMapObject = Hook.Create<CreateToneMapObject>(0x1424CDE20, CreateToneMapObjectHook); + destroyToneMapObject = Hook.Create<DestroyToneMapObject>(0x1424CE380, DestroyToneMapObjectHook); - createLightingObject = Hook.Create<CreateLightingObject>(0x1424CDE20, CreateLightingObjectHook); - destroyLightingObject = Hook.Create<DestroyLightingObject>(0x1424CE380, DestroyLightingObjectHook); // nint, int + createRenderPassesObject = Hook.Create<CreateRenderPassesObject>(0x14255BA70, CreateRenderPassesObjectHook); + destroyRenderPassesObject = Hook.Create<DestroyRenderPassesObject>(0x14255C710, DestroyRenderPassesObjectHook); createBloomObject = Hook.Create<CreateBloomObject>(0x1424CB3C0, CreateBloomObjectHook); - createBloomObject2 = Hook.Create<CreateBloomObject2>(0x1424CB5E0, CreateBloomObject2Hook); // nint - destroyBloomObject = Hook.Create<DestroyBloomObject>(0x1424CB750, DestroyBloomObjectHook); // nint, int + createBloomObject2 = Hook.Create<CreateBloomObject2>(0x1424CB5E0, CreateBloomObject2Hook); + destroyBloomObject = Hook.Create<DestroyBloomObject>(0x1424CB750, DestroyBloomObjectHook); createDofObject = Hook.Create<CreateDofObject>(0x142421E80, CreateDofObjectHook); - createDofObject2 = Hook.Create<CreateDofObject2>(0x1424220A0, CreateDofObject2Hook); // nint - destroyDofObject = Hook.Create<DestroyDofObject>(0x142422290, DestroyDofObjectHook); // nint, int + createDofObject2 = Hook.Create<CreateDofObject2>(0x1424220A0, CreateDofObject2Hook); + destroyDofObject = Hook.Create<DestroyDofObject>(0x142422290, DestroyDofObjectHook); createMotionBlurObject = Hook.Create<CreateMotionBlurObject>(0x1424C95E0, CreateMotionBlurObjectHook); - createMotionBlurObject2 = Hook.Create<CreateMotionBlurObject2>(0x1424C9740, CreateMotionBlurObject2Hook); // nint - destroyMotionBlurObject = Hook.Create<DestroyMotionBlurObject>(0x1424C97E0, DestroyMotionBlurObjectHook); // nint, int + createMotionBlurObject2 = Hook.Create<CreateMotionBlurObject2>(0x1424C9740, CreateMotionBlurObject2Hook); + destroyMotionBlurObject = Hook.Create<DestroyMotionBlurObject>(0x1424C97E0, DestroyMotionBlurObjectHook); createHazeObject = Hook.Create<CreateHazeObject>(0x1424C6A80, CreateHazeObjectHook); - createHazeObject2 = Hook.Create<CreateHazeObject2>(0x1424C6C70, CreateHazeObject2Hook); // nint - destroyHazeObject = Hook.Create<DestroyHazeObject>(0x1424C6E20, DestroyHazeObjectHook); // nint, int + createHazeObject2 = Hook.Create<CreateHazeObject2>(0x1424C6C70, CreateHazeObject2Hook); + destroyHazeObject = Hook.Create<DestroyHazeObject>(0x1424C6E20, DestroyHazeObjectHook); - createSimpleSkyObject = Hook.Create<CreateSimpleSkyObject>(0x141FCCC20, CreateSimpleSkyObjectHook); // nint - destroySimpleSkyObject = Hook.Create<DestroySimpleSkyObject>(0x141FCD840, DestroySimpleSkyObjectHook); // nint, int + createSimpleSkyObject = Hook.Create<CreateSimpleSkyObject>(0x141FCCC20, CreateSimpleSkyObjectHook); + destroySimpleSkyObject = Hook.Create<DestroySimpleSkyObject>(0x141FCD840, DestroySimpleSkyObjectHook); createFogObject = Hook.Create<CreateFogObject>(0x141FADB50, CreateFogObjectHook); - createFogObject2 = Hook.Create<CreateFogObject2>(0x141FADC80, CreateFogObject2Hook); // nint - destroyFogObject = Hook.Create<DestroyFogObject>(0x141FADD50, DestroyFogObjectHook); // nint, int + createFogObject2 = Hook.Create<CreateFogObject2>(0x141FADC80, CreateFogObject2Hook); + destroyFogObject = Hook.Create<DestroyFogObject>(0x141FADD50, DestroyFogObjectHook); - createWaterWaveObject = Hook.Create<CreateWaterWaveObject>(0x1423F0850, CreateWaterWaveObjectHook); // nint - destroyWaterWaveObject = Hook.Create<DestroyWaterWaveObject>(0x1423F0EE0, DestroyWaterWaveObjectHook); // nint, int + createWaterWaveObject = Hook.Create<CreateWaterWaveObject>(0x1423F0850, CreateWaterWaveObjectHook); + destroyWaterWaveObject = Hook.Create<DestroyWaterWaveObject>(0x1423F0EE0, DestroyWaterWaveObjectHook); createFXAAObject = Hook.Create<CreateFXAAObject>(0x142393560, CreateFXAAObjectHook); - createFXAAObject2 = Hook.Create<CreateFXAAObject2>(0x142393680, CreateFXAAObject2Hook); // nint - destroyFXAAObject = Hook.Create<DestroyFXAAObject>(0x142393740, DestroyFXAAObjectHook); // nint, int + createFXAAObject2 = Hook.Create<CreateFXAAObject2>(0x142393680, CreateFXAAObject2Hook); + destroyFXAAObject = Hook.Create<DestroyFXAAObject>(0x142393740, DestroyFXAAObjectHook); createTAAObject = Hook.Create<CreateTAAObject>(0x1423911A0, CreateTAAObjectHook); - createTAAObject2 = Hook.Create<CreateTAAObject2>(0x142391320, CreateTAAObject2Hook); // nint - destroyTAAObject = Hook.Create<DestroyTAAObject>(0x1423916E0, DestroyTAAObjectHook); // nint, int + createTAAObject2 = Hook.Create<CreateTAAObject2>(0x142391320, CreateTAAObject2Hook); + destroyTAAObject = Hook.Create<DestroyTAAObject>(0x1423916E0, DestroyTAAObjectHook); nint addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 10 48 89 74 24 18 48 89 7C 24 20 55 41 56 41 57 48 8B EC 48 83 EC 30 48 8B FA 48 8B D9 E8 AA B6 C1 FF 48 8B 47 10 48 8D 57 50")); - Assert(addr == 0x141AB2260); // nint, nint - updateShadowParams = Hook.Create<UpdateShadowParams>(addr, UpdateShadowParamsHook); - staticShadowParams = Hook.Create<StaticShadowParams>(0x1416D94F0, StaticShadowParamsHook); // nint, nint + Assert(addr == 0x141AB2260); + updatePrimaryLightParams = Hook.Create<UpdatePrimaryLightParams>(addr, UpdatePrimaryLightParamsHook); + staticPrimaryLightParams = Hook.Create<StaticPrimaryLightParams>(0x1416D94F0, StaticPrimaryLightParamsHook); + + defaultHqMode = new Patch(0x14226562B, [0xC6, 0x87, 0xA3, 0xE9, 0x00, 0x00, 0x01]); + //defaultHqMode.Enable(); setShadowQuality = new NativeAction<int>(0x14043FF80); @@ -2544,9 +2633,9 @@ namespace WorldTuningTool shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss. shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss. #if OVERSIZED_SHADOW_MAP - shadowRes1_4 = new Patch(lton(0x142288AAA) + 0x4, [0x7A, 0x97, 0xF8, 0x00]); // Limit 4.0 -> 6.0. + shadowRes1_4 = new Patch(0x142288AAA + 0x4, [0x7A, 0x97, 0xF8, 0x00]); // Limit 4.0 -> 6.0. #else - shadowRes1_4 = new Patch(lton(0x142288AAA) + 0x4, [0x9E]); // Limit 4.0 -> 5.0. + shadowRes1_4 = new Patch(0x142288AAA + 0x4, [0x9E]); // Limit 4.0 -> 5.0. #endif addr = PatternScanner.FindFirst(Pattern.FromString("89 91 00 55 00 00 83 FA 05 77 41 48 63 C2 4C 8D 05 ?? ?? ?? ?? 41 8B 94 80 84 8B 28 02 49 03 D0 FF E2 B8 00 08 00 00")); Assert(addr == 0x142288B00); @@ -2570,35 +2659,35 @@ namespace WorldTuningTool broadAreaShadowRes2_Addr = addr; // The volume blur filter is created at a different place in the code and happens at a different - // time (area change/createLightingObject() vs change of Volume Quality setting). It's also rendered + // time (area change/createToneMapObject() vs change of Volume Quality setting). It's also rendered // in a seperate pass that happens after the initial volume rendering. So keep that in mind if inspecting // a frame in renderdoc. - volumeSars1 = new Patch(lton(0x1424D0159), [0x90, 0x90]); - volumeSars2 = new Patch(lton(0x1424D01A0), [0x90, 0x90]); - volumeSars3 = new Patch(lton(0x1424D01C6), [0x90, 0x90]); - volumeSars4 = new Patch(lton(0x1424D0219), [0x90, 0x90]); - volumeSars5 = new Patch(lton(0x1424D0242), [0x90, 0x90]); - volumeSars6 = new Patch(lton(0x1424D029D), [0x90, 0x90]); - volumeSars7 = new Patch(lton(0x1424D02C6), [0x90, 0x90]); - volumeSars8 = new Patch(lton(0x1424D0321), [0x90, 0x90]); - volumeSars9 = new Patch(lton(0x1424D034A), [0x90, 0x90]); + volumeSars1 = new Patch(0x1424D0159, [0x90, 0x90]); + volumeSars2 = new Patch(0x1424D01A0, [0x90, 0x90]); + volumeSars3 = new Patch(0x1424D01C6, [0x90, 0x90]); + volumeSars4 = new Patch(0x1424D0219, [0x90, 0x90]); + volumeSars5 = new Patch(0x1424D0242, [0x90, 0x90]); + volumeSars6 = new Patch(0x1424D029D, [0x90, 0x90]); + volumeSars7 = new Patch(0x1424D02C6, [0x90, 0x90]); + volumeSars8 = new Patch(0x1424D0321, [0x90, 0x90]); + volumeSars9 = new Patch(0x1424D034A, [0x90, 0x90]); /* As far as I can tell, this is limited by buffers created cpu-side. Seems like * it would be an extremely hard change. - froxelRes1 = new Patch(lton(0x142384F15) + 0x1, [0x02]); // 4 -> 2 - froxelRes2 = new Patch(lton(0x142389711) + 0x1, [0x02]); // 4 -> 2 - froxelRes3 = new Patch(lton(0x142389878) + 0x1, [0x02]); // 4 -> 2 - froxelRes4 = new Patch(lton(0x14238989E) + 0x1, [0x02]); // 4 -> 2 - froxelRes5 = new Patch(lton(0x1423898D8) + 0x1, [0x02]); // 4 -> 2 - froxelRes6 = new Patch(lton(0x14238992B) + 0x1, [0x02]); // 4 -> 2 - froxelRes7 = new Patch(lton(0x14238FED1) + 0x4, [0x7B, 0xFF, 0xAB, 0x00]); // 0.25 -> 0.50 - froxelRes8 = new Patch(lton(0x14239009C) + 0x4, [0xB0, 0xFD, 0xAB, 0X00]); // 0.25 -> 0.50 + froxelRes1 = new Patch(0x142384F15 + 0x1, [0x02]); // 4 -> 2 + froxelRes2 = new Patch(0x142389711 + 0x1, [0x02]); // 4 -> 2 + froxelRes3 = new Patch(0x142389878 + 0x1, [0x02]); // 4 -> 2 + froxelRes4 = new Patch(0x14238989E + 0x1, [0x02]); // 4 -> 2 + froxelRes5 = new Patch(0x1423898D8 + 0x1, [0x02]); // 4 -> 2 + froxelRes6 = new Patch(0x14238992B + 0x1, [0x02]); // 4 -> 2 + froxelRes7 = new Patch(0x14238FED1 + 0x4, [0x7B, 0xFF, 0xAB, 0x00]); // 0.25 -> 0.50 + froxelRes8 = new Patch(0x14239009C + 0x4, [0xB0, 0xFD, 0xAB, 0X00]); // 0.25 -> 0.50 */ /* Would require a complicated shader edit to maybe work. Similar to SSLR. - checkerRes1 = new Patch(lton(0x14238580D) + 0x4, [0x43]); // 0.5 -> 1.0 - checkerRes2 = new Patch(lton(0x14238FFC3) + 0x4, [0x8D]); // 0.5 -> 1.0 + checkerRes1 = new Patch(0x14238580D + 0x4, [0x43]); // 0.5 -> 1.0 + checkerRes2 = new Patch(0x14238FFC3 + 0x4, [0x8D]); // 0.5 -> 1.0 */ - value2ForVolumeQuality = new Patch(lton(0x142389652), [0xB8, 0x02, 0x00, 0x00, 0x00, 0x90]); + value2ForVolumeQuality = new Patch(0x142389652, [0xB8, 0x02, 0x00, 0x00, 0x00, 0x90]); // Gameplay. addr = PatternScanner.FindFirst(Pattern.FromString("80 BB 34 EC 00 00 00 88 8B 31 EC 00 00 C6 83 30 EC 00 00 00 74 1C C6 83 34 EC 00 00 00 48 8B 0D 68 4B 4F 03 80 B9 58 02 00 00 00 75 05 E8 5A F5 01 00 48 8B CB E8 E2 05 00 00 83 BB DC EB 00 00 06 74 0A C7 83 DC EB 00 00 06 00 00 00")); @@ -2616,18 +2705,25 @@ namespace WorldTuningTool defaultViewModeLODLimit_2 = new Patch(addr + 0x24, [0x07]); // Talking to NPC. - defaultViewModeLODLimit_3 = new Patch(lton(0x14128F1AC) + 0x1, [0x07]); - defaultViewModeLODLimit_4 = new Patch(lton(0x14128F1AC) + 0xF, [0x07]); + defaultViewModeLODLimit_3 = new Patch(0x14128F1AC + 0x1, [0x07]); + defaultViewModeLODLimit_4 = new Patch(0x14128F1AC + 0xF, [0x07]); + + defaultCharaCreatorParam = new Patch(0x141B1A0C1 + 0x6, [0x1]); addr = PatternScanner.FindFirst(Pattern.FromString("74 4D 33 C0 48 81 C1 00 02 00 00 F3 0F 10 11 0F 2F CA 72 0C FF C0 48 83 C1 04 83 F8 03 72 EC C3")); Assert(addr == 0x1426D89CA); addressHigherValueForFoliageSway = new Patch(addr + 0x7, [0x04]); // Found using mFrameSkipNum annotation from MHW-DTI-Dumps. - zeroFrameSkip = new Patch(lton(0x142246948), [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); + zeroFrameSkip = new Patch(0x142246948, [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); + zeroFrameSkip2 = new Patch(0x142641888, [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); + zeroFrameSkip3 = new Patch(0x14237AD75, [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); + + viewModeAddressLod1 = new Patch(0x141B19A6C + 0x4, [0x1C, 0x02, 0x00, 0x00]); + viewModeAddressLod2 = new Patch(0x141B19B7C + 0x4, [0x20, 0x02, 0x00, 0x00]); // vTable of Interest: 0x1433B8730. - jmpOverEffects = new Patch(lton(0x14263483B), [0xEB]); + jmpOverEffects = new Patch(0x14263483B, [0xEB]); // The game will crash when trying to switch to the FULL_RES path for SSR. It's likley because // it tries to access shaders that are not available in the game files. @@ -2637,78 +2733,78 @@ namespace WorldTuningTool // is that it's compiled out and that this method of increasing the SSR resolution can't work. /* // Attempt to forcefully enable FULL_RES path for SSR. - ssrFullRes1 = new Patch(lton(0x14228894D), [0x0F, 0x85, 0xB9, 0xAA, 0x30, 0x00]); - ssrFullRes1_1 = new Patch(lton(0x14259340C), [0xC6, 0x81, 0x28, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); - ssrFullRes2 = new Patch(lton(0x14228897D), [0x0F, 0x85, 0x99, 0xAA, 0x30, 0x00]); - ssrFullRes2_1 = new Patch(lton(0x14259341C), [0xC6, 0x81, 0x30, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); - ssrFullRes3 = new Patch(lton(0x1422889AD), [0x0F, 0x85, 0x79, 0xAA, 0x30, 0x00]); - ssrFullRes3_1 = new Patch(lton(0x14259342C), [0xC6, 0x81, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); - ssrFullRes4 = new Patch(lton(0x14259268C), [0x41, 0xC7, 0x86, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x34, 0x02, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0xC7, 0x86, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x41, 0xC6, 0x86, 0x3C, 0x02, 0x00, 0x00, 0x01]); + ssrFullRes1 = new Patch(0x14228894D, [0x0F, 0x85, 0xB9, 0xAA, 0x30, 0x00]); + ssrFullRes1_1 = new Patch(0x14259340C, [0xC6, 0x81, 0x28, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); + ssrFullRes2 = new Patch(0x14228897D, [0x0F, 0x85, 0x99, 0xAA, 0x30, 0x00]); + ssrFullRes2_1 = new Patch(0x14259341C, [0xC6, 0x81, 0x30, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); + ssrFullRes3 = new Patch(0x1422889AD, [0x0F, 0x85, 0x79, 0xAA, 0x30, 0x00]); + ssrFullRes3_1 = new Patch(0x14259342C, [0xC6, 0x81, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90]); + ssrFullRes4 = new Patch(0x14259268C, [0x41, 0xC7, 0x86, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC7, 0x86, 0x34, 0x02, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0xC7, 0x86, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x41, 0xC6, 0x86, 0x3C, 0x02, 0x00, 0x00, 0x01]); */ // SSLR resolution factor 0.5 -> 1.0 (not related to fSSLRFactor or fSSLRScale). - ssrRes1 = new Patch(lton(0x1425926B8) + 0x9, [0x80]); - ssrRes2 = new Patch(lton(0x1425934C0) + 0x8, [0x80]); + ssrRes1 = new Patch(0x1425926B8 + 0x9, [0x80]); + ssrRes2 = new Patch(0x1425934C0 + 0x8, [0x80]); // Skip mip mapping pass (part of _FULL_RES). - ssrRes3 = new Patch(lton(0x142282B53), [0x31, 0xC0, 0x90, 0x90, 0x90]); + ssrRes3 = new Patch(0x142282B53, [0x31, 0xC0, 0x90, 0x90, 0x90]); // Depth mips resolution. - ssrShr1 = new Patch(lton(0x14269DE47), [0x90, 0x90]); - ssrShr2 = new Patch(lton(0x14269DE54), [0x90, 0x90]); - ssrShr3 = new Patch(lton(0x14269E07A), [0x90, 0x90]); - ssrShr4 = new Patch(lton(0x14269E080), [0x90, 0x90]); + ssrShr1 = new Patch(0x14269DE47, [0x90, 0x90]); + ssrShr2 = new Patch(0x14269DE54, [0x90, 0x90]); + ssrShr3 = new Patch(0x14269E07A, [0x90, 0x90]); + ssrShr4 = new Patch(0x14269E080, [0x90, 0x90]); // Approximate depth mip resolution. - ssrShr5 = new Patch(lton(0x14269DED3) + 0x2, [0x3]); // 4 -> 3 - ssrShr6 = new Patch(lton(0x14269DEDA) + 0x3, [0x3]); + ssrShr5 = new Patch(0x14269DED3 + 0x2, [0x3]); // 4 -> 3 + ssrShr6 = new Patch(0x14269DEDA + 0x3, [0x3]); // Depth mips pass 1 dispatch dimensions. - ssrSars1 = new Patch(lton(0x142282FD8) + 0x3, [0x3]); // 4 -> 3 - ssrSars2 = new Patch(lton(0x142282FE5) + 0x2, [0x3]); + ssrSars1 = new Patch(0x142282FD8 + 0x3, [0x3]); // 4 -> 3 + ssrSars2 = new Patch(0x142282FE5 + 0x2, [0x3]); // Depth mips pass 2 iRegion parameter. - ssrSars3 = new Patch(lton(0x142283014) + 0x3, [0x3]); - ssrSars4 = new Patch(lton(0x142283018) + 0x3, [0x3]); - ssrSars5 = new Patch(lton(0x14228301C) + 0x3, [0x3]); - ssrSars6 = new Patch(lton(0x142283020) + 0x2, [0x3]); + ssrSars3 = new Patch(0x142283014 + 0x3, [0x3]); + ssrSars4 = new Patch(0x142283018 + 0x3, [0x3]); + ssrSars5 = new Patch(0x14228301C + 0x3, [0x3]); + ssrSars6 = new Patch(0x142283020 + 0x2, [0x3]); // Depth mips pass 2 dispatch dimensions. - ssrSars7 = new Patch(lton(0x1422832B3) + 0x3, [0x3]); - ssrSars8 = new Patch(lton(0x1422832C8) + 0x2, [0x3]); + ssrSars7 = new Patch(0x1422832B3 + 0x3, [0x3]); + ssrSars8 = new Patch(0x1422832C8 + 0x2, [0x3]); // Depth copy, for unknown use, viewport/scissor. - ssrSars9 = new Patch(lton(0x1423C5809), [0x90, 0x90]); - ssrSars10 = new Patch(lton(0x1423C5818), [0x90, 0x90]); - ssrSars11 = new Patch(lton(0x1423C5824), [0x90, 0x90]); - ssrSars12 = new Patch(lton(0x1423C5830), [0x90, 0x90]); - ssrSars13 = new Patch(lton(0x1423C5ABC), [0x90, 0x90]); - ssrSars14 = new Patch(lton(0x1423C5AF3), [0x90, 0x90]); + ssrSars9 = new Patch(0x1423C5809, [0x90, 0x90]); + ssrSars10 = new Patch(0x1423C5818, [0x90, 0x90]); + ssrSars11 = new Patch(0x1423C5824, [0x90, 0x90]); + ssrSars12 = new Patch(0x1423C5830, [0x90, 0x90]); + ssrSars13 = new Patch(0x1423C5ABC, [0x90, 0x90]); + ssrSars14 = new Patch(0x1423C5AF3, [0x90, 0x90]); // RayAppendBuffer dispatch dimensions, 4 -> 3 wasteful. - //new Patch(lton(0x14228C323) + 0x3, [0x3]); - //new Patch(lton(0x14228C32D) + 0x2, [0x3]); + //new Patch(0x14228C323 + 0x3, [0x3]); + //new Patch(0x14228C32D + 0x2, [0x3]); // Clear trace buffer, 8 -> 7 wasteful - //new Patch(lton(0x14228C3F4) + 0x2, [0x7]); + //new Patch(0x14228C3F4 + 0x2, [0x7]); // Approximate mip resolution. - ssrShr7 = new Patch(lton(0x142592EBA) + 0x2, [0x3]); // 4 -> 3 - ssrShr8 = new Patch(lton(0x142592ED0) + 0x2, [0x3]); + ssrShr7 = new Patch(0x142592EBA + 0x2, [0x3]); // 4 -> 3 + ssrShr8 = new Patch(0x142592ED0 + 0x2, [0x3]); // Mips pass 1 dispatch dimensions. - ssrSars15 = new Patch(lton(0x142283626) + 0x3, [0x03]); // 4 -> 3 - ssrSars16 = new Patch(lton(0x142283633) + 0x2, [0x03]); + ssrSars15 = new Patch(0x142283626 + 0x3, [0x03]); // 4 -> 3 + ssrSars16 = new Patch(0x142283633 + 0x2, [0x03]); // Mips pass 2 iRegion parameter. - ssrSars17 = new Patch(lton(0x142283667) + 0x2, [0x03]); - ssrSars18 = new Patch(lton(0x14228366A) + 0x3, [0x03]); - ssrSars19 = new Patch(lton(0x14228366E) + 0x3, [0x03]); - ssrSars20 = new Patch(lton(0x142283672) + 0x3, [0x03]); + ssrSars17 = new Patch(0x142283667 + 0x2, [0x03]); + ssrSars18 = new Patch(0x14228366A + 0x3, [0x03]); + ssrSars19 = new Patch(0x14228366E + 0x3, [0x03]); + ssrSars20 = new Patch(0x142283672 + 0x3, [0x03]); // Mips pass 2 dispatch dimensions. - ssrSars21 = new Patch(lton(0x1422838E7) + 0x3, [0x03]); - ssrSars22 = new Patch(lton(0x1422838FC) + 0x2, [0x03]); + ssrSars21 = new Patch(0x1422838E7 + 0x3, [0x03]); + ssrSars22 = new Patch(0x1422838FC + 0x2, [0x03]); // Mips blur dispatch dimensions. - ssrSars23 = new Patch(lton(0x1422839B0), [0x8D, 0x0E, 0x44, 0x8D, 0x76, 0x01, 0x90]); + ssrSars23 = new Patch(0x1422839B0, [0x8D, 0x0E, 0x44, 0x8D, 0x76, 0x01, 0x90]); // Resolve pass, 4 -> 3 wasteful. - //new Patch(lton(0x14228686D) + 0x3, [0x3]); - //new Patch(lton(0x142286877) + 0x2, [0x3]); + //new Patch(0x14228686D + 0x3, [0x3]); + //new Patch(0x142286877 + 0x2, [0x3]); - forceSSLRTemporalReset = new Patch(lton(0x14228CE53), [0xB9, 0x01, 0x00, 0x00, 0x00, 0x90, 0x90]); + forceSSLRTemporalReset = new Patch(0x14228CE53, [0xB9, 0x01, 0x00, 0x00, 0x00, 0x90, 0x90]); return new PluginData(); } @@ -2719,7 +2815,7 @@ namespace WorldTuningTool disableLightsFeature = config.DisableLightsFeature; if (!disableLightsFeature) { - lights.Initialize(); + Lights.Initialize(); } PatchConfig patches = config.Patches; #if SHADER_FEATURES @@ -2760,6 +2856,9 @@ namespace WorldTuningTool ssrSars22.Enable(); ssrSars23.Enable(); } + volumeUpsampleNoLinear = patches.VolumeUpsampleNoLinear; + fxaaMaxQuality = patches.FXAAMaxQualityPreset; + skinAllowNegativeWet = patches.SkinAllowNegativeWetness; #endif fullResVolumeBlur = patches.FullResolutionVolumeBlur; if (fullResVolumeBlur) @@ -2776,6 +2875,11 @@ namespace WorldTuningTool { disableLODLimitsEnable(); } + charaCreatorFace = patches.CharacterCreatorFaceRendering; + if (charaCreatorFace) + { + defaultCharaCreatorParam.Enable(); + } largerFoliageSwayRange = patches.LargerFoliageSwayRange; if (largerFoliageSwayRange) { @@ -2797,6 +2901,8 @@ namespace WorldTuningTool sQuest = SingletonManager.GetSingleton("sQuest")!; sLightLinker = SingletonManager.GetSingleton("sLightLinker")!; sLightProbes = SingletonManager.GetSingleton("sLightProbes")!; + sVolumeRenderer = SingletonManager.GetSingleton("sVolumeRenderer")!; + sMhSpeedTree = SingletonManager.GetSingleton("sMhSpeedTree")!; foreach (Parameter param in sLightProbesParameters) { param.Update(sLightProbes!.Instance); @@ -2877,7 +2983,7 @@ namespace WorldTuningTool if (!disableLightsFeature) { - lights.OnUpdate(); + Lights.OnUpdate(); } } @@ -2937,6 +3043,19 @@ namespace WorldTuningTool param.Update(sMhRender!.Instance); } + foreach (Parameter param in exposureParameters) + { + param.Update(sMhScene!.Instance); + } + + if (renderPassesObject != 0x0) + { + foreach (Parameter param in renderPassesParameters) + { + param.Update(renderPassesObject); + } + } + if (bloomObject != 0x0) { foreach (Parameter param in bloomParameters) @@ -2987,11 +3106,16 @@ namespace WorldTuningTool param.Update(sLightProbes!.Instance); } - if (lightingObject != 0x0) + foreach (Parameter param in sVolumeRendererParameters) { - foreach (Parameter param in lightingParameters) + param.Update(sVolumeRenderer!.Instance); + } + + if (toneMapObject != 0x0) + { + foreach (Parameter param in toneMapParameters) { - param.Update(lightingObject); + param.Update(toneMapObject); } } @@ -3027,9 +3151,14 @@ namespace WorldTuningTool } } + foreach (Parameter param in speedTreeParameters) + { + param.Update(sMhSpeedTree!.Instance); + } + if (!disableLightsFeature) { - lights.PostUpdateLightLinker(); + Lights.PostUpdateLightLinker(); } } @@ -3066,40 +3195,64 @@ namespace WorldTuningTool } } - private void UpdateLightingParamsHook(nint stackOffset, nint lightingObjectInternal) + private void UpdateToneMapParamsHook(nint stackOffset, nint toneMapObjectInternal) + { + updateToneMapParams!.Original(stackOffset, toneMapObjectInternal); + if (toneMapObject == toneMapObjectInternal) + { + foreach (Parameter param in toneMapParameters) + { + param.Update(toneMapObject, true); + } + } + } + + private nint CreateToneMapObjectHook() + { + toneMapObject = createToneMapObject!.Original(); + foreach (Parameter param in toneMapParameters) + { + param.Update(toneMapObject); + } + return toneMapObject; + } + + private nint DestroyToneMapObjectHook(nint toneMapObjectInternal, int unknownInt) { - updateLightingParams!.Original(stackOffset, lightingObjectInternal); - if (lightingObject == lightingObjectInternal) + Assert(unknownInt == 1); + if (toneMapObject == toneMapObjectInternal) { - foreach (Parameter param in lightingParameters) + toneMapObject = 0x0; + foreach (Parameter param in toneMapParameters) { - param.Update(lightingObject, true); + param.Update(toneMapObject); } } + return destroyToneMapObject!.Original(toneMapObjectInternal, unknownInt); } - private nint CreateLightingObjectHook() + private nint CreateRenderPassesObjectHook(nint unknownPtr1, nint unknownPtr2) { - lightingObject = createLightingObject!.Original(); - foreach (Parameter param in lightingParameters) + renderPassesObject = createRenderPassesObject!.Original(unknownPtr1, unknownPtr2); + foreach (Parameter param in renderPassesParameters) { - param.Update(lightingObject); + param.Update(renderPassesObject); } - return lightingObject; + return renderPassesObject; } - private nint DestroyLightingObjectHook(nint lightingObjectInternal, int unknownInt) + private nint DestroyRenderPassesObjectHook(nint renderPassesObjectInternal, int unknownInt) { Assert(unknownInt == 1); - if (lightingObject == lightingObjectInternal) + if (renderPassesObject == renderPassesObjectInternal) { - lightingObject = 0x0; - foreach (Parameter param in lightingParameters) + renderPassesObject = 0x0; + foreach (Parameter param in renderPassesParameters) { - param.Update(lightingObject); + param.Update(renderPassesObject); } } - return destroyLightingObject!.Original(lightingObjectInternal, unknownInt); + return destroyRenderPassesObject!.Original(renderPassesObjectInternal, unknownInt); } private nint CreateBloomObjectHook() @@ -3388,30 +3541,46 @@ namespace WorldTuningTool return destroyTAAObject!.Original(taaObjectInternal, unknownInt); } - private void UpdateShadowParamsHook(nint shadowParams, nint stackOffset) + private void UpdatePrimaryLightParamsHook(nint primaryLightParams, nint stackOffset) { bool isPrimary = MemoryUtil.Read<byte>(stackOffset + 0x1D) == 0x1; if (isPrimary) { - foreach (Parameter param in shadowParameters2) + foreach (Parameter param in primaryLightParameters) + { + param.Update(stackOffset, true); + } + foreach (Parameter param in primaryShadowParameters) + { + param.Update(stackOffset, true); + } + foreach (Parameter param in primaryBroadAreaParameters) { param.Update(stackOffset, true); } } - updateShadowParams!.Original(shadowParams, stackOffset); + updatePrimaryLightParams!.Original(primaryLightParams, stackOffset); } - private void StaticShadowParamsHook(nint shadowParamsStatic, nint shadowObjectInternal) + private void StaticPrimaryLightParamsHook(nint primaryLightParamsStatic, nint primaryLightObjectInternal) { - if (shadowObjectInternal == 0x0) + if (primaryLightObjectInternal == 0x0) { // Necessary to apply Broad Area Depth Bias overrides on first update. - foreach (Parameter param in shadowParameters2) + foreach (Parameter param in primaryLightParameters) { - param.Update(shadowParamsStatic, true); + param.Update(primaryLightParamsStatic, true); + } + foreach (Parameter param in primaryShadowParameters) + { + param.Update(primaryLightParamsStatic, true); + } + foreach (Parameter param in primaryBroadAreaParameters) + { + param.Update(primaryLightParamsStatic, true); } } - staticShadowParams!.Original(shadowParamsStatic, shadowObjectInternal); + staticPrimaryLightParams!.Original(primaryLightParamsStatic, primaryLightObjectInternal); } private void HandleSetChange(string prevSet, List<Override> globalOverrides, List<Override>? stageOverrides) @@ -3586,6 +3755,7 @@ namespace WorldTuningTool { boxColor = ImGui.GetStyle().Colors[(int)ImGuiCol.Button]; } + boxColor.W = ImGui.GetStyle().Alpha; ImDrawListPtr drawList = ImGui.GetWindowDrawList(); drawList.AddRectFilled(windowPos, windowPos + new Vector2(boxWidth, boxHeight), (uint)ColorVectorToInt(boxColor)); } @@ -3980,7 +4150,11 @@ namespace WorldTuningTool ImGui.Text("External:"); foreach (Override ovE in externalOverrides.Values) { - ovE.Draw(false, null, null, null, false, width); + Vector2 cursorPos = default; + float boxHeight = 0.0f, boxWidth = 0.0f; + prepareStatusBox(ref cursorPos, ref boxHeight, ref boxWidth); + bool hasStatus = ovE.Draw(false, null, null, null, false, width); + drawStatusBox(false, hasStatus, cursorPos, boxHeight, boxWidth); } ImGui.PopID(); @@ -3991,7 +4165,9 @@ namespace WorldTuningTool PatchConfig patches = config.Patches; #if SHADER_FEATURES - if (ImGui.Checkbox("Full Resolution Screen Space Reflections (Requires Restart)", ref fullResSSLR)) + ImGui.Text("Shader (Requires Restart):"); + ImGui.Separator(); + if (ImGui.Checkbox("Full Resolution Screen Space Reflections", ref fullResSSLR)) { patches.FullResolutionSSLR = fullResSSLR; config.Patches = patches; @@ -3999,11 +4175,49 @@ namespace WorldTuningTool } if (ImGui.BeginItemTooltip()) { - ImGui.Text("Restart Required"); + ImGui.Text("Very complex patch, please report any issues you notice.\nThis also appears to scale SSLR Eliminate Depth, it's suggested to half it's value when this is enabled."); + ImGui.EndTooltip(); + } + + if (ImGui.Checkbox("Volume Rendering No Linear Sampling", ref volumeUpsampleNoLinear)) + { + patches.VolumeUpsampleNoLinear = volumeUpsampleNoLinear; + config.Patches = patches; + saveConfig(config); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Fix for black square artifacts on object edges."); + ImGui.EndTooltip(); + } + + if (ImGui.Checkbox("FXAA Max Quality Preset", ref fxaaMaxQuality)) + { + patches.FXAAMaxQualityPreset = fxaaMaxQuality; + config.Patches = patches; + saveConfig(config); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("#define FXAA_QUALITY__PRESET 39"); + ImGui.EndTooltip(); + } + + if (ImGui.Checkbox("Skin Allow Negative Wetness", ref skinAllowNegativeWet)) + { + patches.SkinAllowNegativeWetness = skinAllowNegativeWet; + config.Patches = patches; + saveConfig(config); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Can be used to reverse the effect of wet by default modded armor."); ImGui.EndTooltip(); } #endif + ImGui.Text("General:"); + ImGui.Separator(); if (ImGui.Checkbox("Volume Rendering Full Resolution Blur Pass (Requires Area Change)", ref fullResVolumeBlur)) { if (fullResVolumeBlur) @@ -4064,6 +4278,21 @@ namespace WorldTuningTool ImGui.EndTooltip(); } + if (ImGui.Checkbox("Character Creator Face Rendering", ref charaCreatorFace)) + { + if (charaCreatorFace) + { + defaultCharaCreatorParam.Enable(); + } + else + { + defaultCharaCreatorParam.Disable(); + } + patches.CharacterCreatorFaceRendering = charaCreatorFace; + config.Patches = patches; + saveConfig(config); + } + if (ImGui.Checkbox("Larger Foliage Sway Range", ref largerFoliageSwayRange)) { if (largerFoliageSwayRange) @@ -4103,13 +4332,32 @@ namespace WorldTuningTool ImGui.Text("Ignore the frame skip set on an animal's animation when are far from the camera."); ImGui.EndTooltip(); } + + if (ImGui.Checkbox("Override View Mode LODs", ref viewModeLodOverride)) + { + if (viewModeLodOverride) + { + viewModeAddressLod1.Enable(); + viewModeAddressLod2.Enable(); + } + else + { + viewModeAddressLod1.Disable(); + viewModeAddressLod2.Disable(); + } + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("View Mode still won't consider LOD Length/Pixel Size Bias."); + ImGui.EndTooltip(); + } } if (!disableLightsFeature) { if (ImGui.CollapsingHeader("Lights")) { - lights.DrawUI(width); + Lights.DrawUI(width); } } @@ -4145,7 +4393,7 @@ namespace WorldTuningTool ImGui.PopID(); ImGui.PushID("LOD"); - if (ImGui.CollapsingHeader("Level of Detail")) + if (ImGui.CollapsingHeader("LODs")) { ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); foreach (Parameter param in lodParameters) @@ -4159,52 +4407,49 @@ namespace WorldTuningTool } ImGui.PopID(); - // MonsterHunterWorld.exe+1AB99E0 - mov rax,[MonsterHunterWorld.exe+500E180] - nint shadowAddr = MemoryUtil.Read<nint>(0x14500E180); - nint shadowObject = MemoryUtil.Read<nint>(shadowAddr + 0x4B0); - shadowAddr += 0x5B0; + ImGui.PushID("Passthrough"); + if (ImGui.CollapsingHeader("Passthrough")) + { + ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); + foreach (Parameter param in passthroughParameters) + { + param.Draw(width); + } + } + ImGui.PopID(); + ImGui.PushID("Shadows"); - if (ImGui.CollapsingHeader("Sunlight and Shadows")) + if (ImGui.CollapsingHeader("Shadows")) { shadowResParameter.Draw(width); ImGui.Separator(); - ImGui.Text($"shadowAddr: 0x{shadowAddr:X}, shadowObject: 0x{shadowObject:X}"); - /* - if (ImGui.CollapsingHeader("Pass 1")) + ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); + foreach (Parameter param in shadowCascadeParameters) { - ImGui.PushID("Pass1"); - foreach (Parameter param in shadowParameters1) - { - param.Draw(width); - } - ImGui.PopID(); + param.Draw(width); } - if (ImGui.CollapsingHeader("Pass 2")) + foreach (Parameter param in primaryShadowParameters) { - ImGui.PushID("Pass2"); - */ - foreach (Parameter param in shadowParameters2) - { - param.Draw(width); - } - /* - ImGui.PopID(); + param.Draw(width); } - */ - ImGui.Separator(); - ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); - foreach (Parameter param in shadowCascadeParameters) + foreach (Parameter param in broadAreaShadowParameters) + { + param.Draw(width); + } + foreach (Parameter param in primaryBroadAreaParameters) { param.Draw(width); } } ImGui.PopID(); - ImGui.PushID("BroadAreaShadows"); - if (ImGui.CollapsingHeader("Broad Area Shadows")) + ImGui.PushID("PrimaryLight"); + if (ImGui.CollapsingHeader("Primary Light")) { - ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); - foreach (Parameter param in broadAreaShadowParameters) + // MonsterHunterWorld.exe+1AB99E0 - mov rax,[MonsterHunterWorld.exe+500E180] + nint primaryLightObject = MemoryUtil.Read<nint>(MemoryUtil.Read<nint>(0x14500E180) + 0x4B0); + ImGui.Text($"Address: 0x{primaryLightObject:X}"); + foreach (Parameter param in primaryLightParameters) { param.Draw(width); } @@ -4238,7 +4483,7 @@ namespace WorldTuningTool ImGui.PopID(); ImGui.PushID("SSAO"); - if (ImGui.CollapsingHeader("Ambient Occlusion")) + if (ImGui.CollapsingHeader("SSAO")) { ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); foreach (Parameter param in ssaoParameters) @@ -4248,22 +4493,11 @@ namespace WorldTuningTool } ImGui.PopID(); - ImGui.PushID("SSLR"); - if (ImGui.CollapsingHeader("Reflections")) - { - ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); - foreach (Parameter param in sslrParameters) - { - param.Draw(width); - } - } - ImGui.PopID(); - - ImGui.PushID("Passthrough"); - if (ImGui.CollapsingHeader("Passthrough")) + ImGui.PushID("VolumeRenderer"); + if (ImGui.CollapsingHeader("Volume Renderer")) { - ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); - foreach (Parameter param in passthroughParameters) + ImGui.Text($"Address: 0x{sVolumeRenderer!.Instance:X}"); + foreach (Parameter param in sVolumeRendererParameters) { param.Draw(width); } @@ -4273,30 +4507,40 @@ namespace WorldTuningTool ImGui.PushID("Lighting"); if (ImGui.CollapsingHeader("Lighting")) { - ImGui.Text($"Address: 0x{lightingObject:X}"); - if (lightingObject != 0x0) + ImGui.Text($"Address: 0x{toneMapObject:X}"); + if (toneMapObject != 0x0) { if (ImGui.CollapsingHeader("LUTs")) { - nint lutBlendTexture = MemoryUtil.Read<nint>(lightingObject + 0x1C0); + nint lutBlendTexture = MemoryUtil.Read<nint>(toneMapObject + 0x1C0); ImGui.Text($"LUT Blend: 0x{lutBlendTexture:X}"); - nint lutMap0 = MemoryUtil.Read<nint>(lightingObject + 0x1A8); + nint lutMap0 = MemoryUtil.Read<nint>(toneMapObject + 0x1A8); if (lutMap0 != 0x0) { - luts.DrawUI(lutMap0, lightingObject, 0, width); + WorldLUTs.DrawUI(lutMap0, toneMapObject, 0, width); } - nint lutMap1 = MemoryUtil.Read<nint>(lightingObject + 0x1B0); + nint lutMap1 = MemoryUtil.Read<nint>(toneMapObject + 0x1B0); if (lutMap1 != 0x0) { - luts.DrawUI(lutMap1, lightingObject, 1, width); + WorldLUTs.DrawUI(lutMap1, toneMapObject, 1, width); } } - foreach (Parameter param in lightingParameters) + foreach (Parameter param in toneMapParameters) { param.Draw(width); } } ImGui.Separator(); + ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); + foreach (Parameter param in exposureParameters) + { + param.Draw(width); + } + if (ImGui.Button("Reset")) + { + new NativeAction<nint>(0x142285F50).Invoke(sMhScene!.Instance); + } + ImGui.Separator(); ImGui.Text($"Address: 0x{sMhRender!.Instance:X}"); foreach (Parameter param in brightnessParameters) { @@ -4305,6 +4549,33 @@ namespace WorldTuningTool } ImGui.PopID(); + ImGui.PushID("SSLR"); + if (ImGui.CollapsingHeader("SSLR")) + { + ImGui.Text($"Address: 0x{sMhScene!.Instance:X}"); + foreach (Parameter param in sslrParameters) + { + param.Draw(width); + } + } + ImGui.PopID(); + + /* + ImGui.PushID("Render Passes"); + if (ImGui.CollapsingHeader("Render Passes")) + { + ImGui.Text($"Address: 0x{renderPassesObject:X}"); + if (renderPassesObject != 0x0) + { + foreach (Parameter param in renderPassesParameters) + { + param.Draw(width); + } + } + } + ImGui.PopID(); + */ + ImGui.PushID("Bloom"); if (ImGui.CollapsingHeader("Bloom")) { @@ -4389,6 +4660,17 @@ namespace WorldTuningTool } ImGui.PopID(); + ImGui.PushID("SpeedTree"); + if (ImGui.CollapsingHeader("SpeedTree")) + { + ImGui.Text($"Address: 0x{sMhSpeedTree!.Instance:X}"); + foreach (Parameter param in speedTreeParameters) + { + param.Draw(width); + } + } + ImGui.PopID(); + ImGui.PushID("WaterWave"); if (ImGui.CollapsingHeader("Water Waves")) { @@ -4491,6 +4773,25 @@ namespace WorldTuningTool ImGui.EndTooltip(); } + if (ImGui.Checkbox("Disable Reduced Rate Animations 2", ref disableReducedRateAnimations2)) + { + if (disableReducedRateAnimations2) + { + zeroFrameSkip2.Enable(); + zeroFrameSkip3.Enable(); + } + else + { + zeroFrameSkip2.Disable(); + zeroFrameSkip3.Disable(); + } + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Unlikely to do anything. If you find an instance were a frame skip is set here, please report.\nThis may be included by the first patch in the future."); + ImGui.EndTooltip(); + } + ImGui.Separator(); } @@ -4512,8 +4813,13 @@ namespace WorldTuningTool } #if SHADER_FEATURES - private static bool replaceShaderFromFile(ShaderInfo *info, string path) + private static bool replaceShaderFromFile(ShaderInfo *info, string path, ShaderSourceType type) { + //if (info->Replacement.Source != null) + //{ + // Log.Warn("Shader already replaced"); + // return false; + //} if (!System.IO.File.Exists(path)) { Log.Warn($"File not found: {path}."); @@ -4529,8 +4835,7 @@ namespace WorldTuningTool Log.Error($"Failed to read: {path}."); return false; } - info->Replacement.Length = shaderData.Length; - info->Replacement.Source = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement<byte>(shaderData, 0); + info->Replacement.Set(shaderData, type); return true; } @@ -4539,141 +4844,55 @@ namespace WorldTuningTool public unsafe void OnCreateShader(ShaderInfo *info) { string hash = new string(info->DxbcHash); - if (hash == "0c3dacbd-32c175d5-10d80d04-cce7e689") - { - if (replaceShaderFromFile(info, $"{shaderPath}/alpha_as_luma.hlsl")) - { - info->Replacement.Type = ShaderSourceType.HLSL; - Log.Info("Alpha as luma shader replaced."); - } - } - else if (hash == "9ff245fb-4fd555e0-04d0ef15-84609fe1") - { - if (replaceShaderFromFile(info, $"{shaderPath}/fxaa_max_quality.hlsl")) - { - info->Replacement.Type = ShaderSourceType.HLSL; - Log.Info("FXAA shader replaced."); - } - } - else if (!shadersLoadedOnce && hash == "2e4e18fd-6ea5eeae-2de3d65c-26ab36dd") - { - if (replaceShaderFromFile(info, $"{shaderPath}/volume_upsample1.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Volume upsample shader 1 replaced."); - } - } - else if (!shadersLoadedOnce && hash == "e2c8c13e-45bc99b2-4c3d7699-3d66188e") - { - if (replaceShaderFromFile(info, $"{shaderPath}/volume_upsample2.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Volume upsample shader 2 replaced."); - } - // This allows us to A/B using the volume rendering value 2 switch. - //shadersLoadedOnce = true; - } - /* - else if (hash == "8cf2a107-ecde214b-9939b350-7b2af1a7") - { - if (replaceShaderFromFile(info, $"{shaderPath}/cube_only.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Cube Only shader replaced."); - } - } - */ - else if (hash == "2eed1f00-e24d1b19-9d521064-17b9a586") - { - if (replaceShaderFromFile(info, $"{shaderPath}/body_skin.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Body skin shader replaced."); - } - } - else if (hash == "8e5e3c09-ebe77ee4-ba1cb659-d25bc7bf") - { - if (replaceShaderFromFile(info, $"{shaderPath}/face.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Face shader replaced."); - } - } - /* - else if (hash == "18a797dc-9458d333-59e6dff0-9790fcea") - { - if (replaceShaderFromFile(info, $"{shaderPath}/sssss.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("SSSSS shader replaced."); - } - } - */ - /* - else if (hash == "ca33bab6-2119df84-41786a69-404471cd") - { - if (replaceShaderFromFile(info, $"{shaderPath}/color_grading.shdr")) - { - info->Replacement.Type = ShaderSourceType.Binary; - Log.Info("Color grading shader replaced."); - } - } - */ + if (fullResSSLR) { if (hash == "4b722c0e-8e787cd5-5eaf5e6c-09782f91") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_depth_mips.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_depth_mips.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR depth mips shader replaced."); } } else if (hash == "5abc7a51-f182e7d6-14d2f897-6f851c0b") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_trace.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_trace.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR trace shader replaced."); } } else if (hash == "d7e47ffe-82572c64-795c4698-341e5b91") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_mips.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_mips.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR mips shader replaced."); } } else if (hash == "b21dd223-98ab56ae-918264e6-eb6e8ee4") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR resolve shader replaced."); } } else if (hash == "8703f55f-6c22fba7-1ef876f1-4767379e") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR resolve no jitter shader replaced."); } } else if (hash == "a9372f22-05154267-13f583e1-b08ffd75") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_dither.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_dither.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR resolve no dither shader replaced."); } } else if (hash == "77e20ce4-0538a5f1-908ba0a3-55821b0f") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter_no_dither.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter_no_dither.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR resolve no jitter or dither shader replaced."); } } @@ -4682,13 +4901,97 @@ namespace WorldTuningTool { if (hash == "8703f55f-6c22fba7-1ef876f1-4767379e") { - if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter_min_only.shdr")) + if (replaceShaderFromFile(info, $"{shaderPath}/sslr_resolve_no_jitter_min_only.shdr", ShaderSourceType.Binary)) { - info->Replacement.Type = ShaderSourceType.Binary; Log.Info("SSLR resolve no jitter shader replaced."); } } } + + if (volumeUpsampleNoLinear) + { + if (!shadersLoadedOnce && hash == "2e4e18fd-6ea5eeae-2de3d65c-26ab36dd") + { + if (replaceShaderFromFile(info, $"{shaderPath}/volume_upsample1.shdr", ShaderSourceType.Binary)) + { + Log.Info("Volume upsample shader 1 replaced."); + } + } + else if (!shadersLoadedOnce && hash == "e2c8c13e-45bc99b2-4c3d7699-3d66188e") + { + if (replaceShaderFromFile(info, $"{shaderPath}/volume_upsample2.shdr", ShaderSourceType.Binary)) + { + Log.Info("Volume upsample shader 2 replaced."); + } + // This allows us to A/B using the volume rendering value 2 switch. + //shadersLoadedOnce = true; + } + } + + if (fxaaMaxQuality) + { + if (hash == "9ff245fb-4fd555e0-04d0ef15-84609fe1") + { + if (replaceShaderFromFile(info, $"{shaderPath}/fxaa_max_quality.hlsl", ShaderSourceType.HLSL)) + { + Log.Info("FXAA shader replaced."); + } + } + } + + if (skinAllowNegativeWet) + { + if (hash == "2eed1f00-e24d1b19-9d521064-17b9a586") + { + if (replaceShaderFromFile(info, $"{shaderPath}/body_skin.shdr", ShaderSourceType.Binary)) + { + Log.Info("Body skin shader replaced."); + } + } + else if (hash == "8e5e3c09-ebe77ee4-ba1cb659-d25bc7bf") + { + if (replaceShaderFromFile(info, $"{shaderPath}/face.shdr", ShaderSourceType.Binary)) + { + Log.Info("Face shader replaced."); + } + } + } + + if (hash == "ca33bab6-2119df84-41786a69-404471cd") + { + if (replaceShaderFromFile(info, $"{shaderPath}/color_grading_ex_tonemappers.shdr", ShaderSourceType.Binary)) + { + Log.Info("Color grading shader replaced."); + } + } + + /* + if (hash == "0c3dacbd-32c175d5-10d80d04-cce7e689") + { + if (replaceShaderFromFile(info, $"{shaderPath}/alpha_as_luma.hlsl", ShaderSourceType.HLSL)) + { + Log.Info("Alpha as luma shader replaced."); + } + } + */ + /* + else if (hash == "8cf2a107-ecde214b-9939b350-7b2af1a7") + { + if (replaceShaderFromFile(info, $"{shaderPath}/cube_only.shdr", ShaderSourceType.Binary)) + { + Log.Info("Cube Only shader replaced."); + } + } + */ + /* + else if (hash == "18a797dc-9458d333-59e6dff0-9790fcea") + { + if (replaceShaderFromFile(info, $"{shaderPath}/sssss.shdr", ShaderSourceType.Binary)) + { + Log.Info("SSSSS shader replaced."); + } + } + */ } #endif } diff --git a/Shaders/color_grading_add_uchimura.diff b/Shaders/color_grading_add_uchimura.diff new file mode 100644 index 0000000..aa44115 --- /dev/null +++ b/Shaders/color_grading_add_uchimura.diff @@ -0,0 +1,41 @@ +--- a/color_grading.asm 2026-10-07 20:38:52.515256500 -0400 ++++ b/color_grading.asm 2026-10-07 23:37:24.393674847 -0400 +@@ -148,6 +148,30 @@ + add r1.xyz, r1.xyzx, -cb3[1].yyyy + mul r0.xyz, r1.xyzx, cb3[1].xxxx + else ++ ieq r1.x, cb3[0].x, l(7) ++ if_nz r1.x ++ mul r1.xyz, r0.xyzx, l(4.545455, 4.545455, 4.545455, 0.000000) ++ mov_sat r2.xyz, r1.xyzx ++ mad r3.xyz, r2.xyzx, l(-2.000000, -2.000000, -2.000000, 0.000000), l(3.000000, 3.000000, 3.000000, 0.000000) ++ mul r2.xyz, r2.xyzx, r2.xyzx ++ mad r2.xyz, -r3.xyzx, r2.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) ++ ge r3.xyz, r0.xyzx, l(0.532000, 0.532000, 0.532000, 0.000000) ++ and r4.xyz, r3.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) ++ add r5.xyz, -r2.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000) ++ movc r3.xyz, r3.xyzx, l(-1.000000, -1.000000, -1.000000, 0.000000), l(0x80000000, 0x80000000, 0x80000000, 0) ++ add r3.xyz, r3.xyzx, r5.xyzx ++ log r1.xyz, r1.xyzx ++ mul r1.xyz, r1.xyzx, l(1.330000, 1.330000, 1.330000, 0.000000) ++ exp r1.xyz, r1.xyzx ++ mul r1.xyz, r1.xyzx, r2.xyzx ++ add r2.xyz, r0.xyzx, l(-0.532000, -0.532000, -0.532000, 0.000000) ++ mul r2.xyz, r2.xyzx, l(-3.082682, -3.082682, -3.082682, 0.000000) ++ exp r2.xyz, r2.xyzx ++ mad r2.xyz, -r2.xyzx, l(0.468000, 0.468000, 0.468000, 0.000000), l(1.000000, 1.000000, 1.000000, 0.000000) ++ mul r3.xyz, r0.xyzx, r3.xyzx ++ mad r1.xyz, r1.xyzx, l(0.220000, 0.220000, 0.220000, 0.000000), r3.xyzx ++ mad r0.xyz, r2.xyzx, r4.xyzx, r1.xyzx ++ else + if_nz cb3[0].y + dp3 r1.x, r0.xyzx, l(0.299010, 0.587000, 0.114000, 0.000000) + switch cb3[0].x +@@ -204,6 +228,7 @@ + break + endswitch + endif ++ endif + endif + endif + ine r1.x, cb2[3].x, l(0) |