using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.XR; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RepoRTGI")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Screen-space ray-traced global illumination for R.E.P.O.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RepoRTGI")] [assembly: AssemblyTitle("RepoRTGI")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RepoRTGI { internal static class BuildInfo { internal const string Version = "1.0.0"; } internal sealed class GpuClassification { internal string Name { get; } internal string Reason { get; } internal bool IsAutomaticTier { get; } internal int VramMb { get; } internal GpuClassification(string name, bool isAutomaticTier, string reason, int vramMb) { Name = name; IsAutomaticTier = isAutomaticTier; Reason = reason; VramMb = vramMb; } } internal static class GpuClassifier { private static readonly Regex NvidiaModel = new Regex("RTX\\s*(\\d{4})", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private static readonly Regex AmdModel = new Regex("RX\\s*(\\d{4,5})\\s*(XTX|XT)?", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); internal static GpuClassification Detect() { string text = SystemInfo.graphicsDeviceName ?? "Unknown GPU"; int graphicsMemorySize = SystemInfo.graphicsMemorySize; string text2 = Regex.Replace(text.ToUpperInvariant(), "\\s+", " "); if (text2.Contains("MICROSOFT BASIC") || text2.Contains("REMOTE DISPLAY") || text2.Contains("VMWARE") || text2.Contains("VIRTUAL")) { return new GpuClassification(text, isAutomaticTier: false, "software or virtual graphics adapter", graphicsMemorySize); } Match match = NvidiaModel.Match(text2); if (match.Success && int.TryParse(match.Groups[1].Value, out var result)) { if (text2.Contains("LAPTOP") || text2.Contains("MOBILE")) { return new GpuClassification(text, isAutomaticTier: false, "mobile GPU variants use manual activation because their power limits vary widely", graphicsMemorySize); } int num = result / 1000; int num2 = result % 1000; bool flag = num >= 6 || (num == 5 && num2 >= 70) || (num == 4 && (num2 >= 80 || text2.Contains("4070 TI"))) || (num == 3 && num2 >= 90); return new GpuClassification(text, flag, flag ? "NVIDIA GPU meets the RTX 5070-class automatic threshold" : "NVIDIA GPU is below the RTX 5070-class automatic threshold", graphicsMemorySize); } Match match2 = AmdModel.Match(text2); if (match2.Success && int.TryParse(match2.Groups[1].Value, out var result2)) { string text3 = match2.Groups[2].Value.ToUpperInvariant(); bool flag2 = result2 >= 10000 || result2 >= 9070 || (result2 == 7900 && text3 == "XTX"); return new GpuClassification(text, flag2, flag2 ? "AMD GPU meets the RX 9070 / RTX 5070-class automatic threshold" : "AMD GPU is below the RTX 5070-class automatic threshold", graphicsMemorySize); } return new GpuClassification(text, isAutomaticTier: false, "GPU model is not in the conservative automatic-enable allowlist", graphicsMemorySize); } } internal static class NativeBridge { private const string NativeLibraryName = "RepoRTGI.Native"; private static IntPtr _module; private static IntPtr _renderEvent; private static ManualLogSource? _log; internal static bool IsLoaded { get { if (_module != IntPtr.Zero) { return _renderEvent != IntPtr.Zero; } return false; } } internal static IntPtr RenderEvent => _renderEvent; internal static bool Load(string pluginDirectory, ManualLogSource log) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 _log = log; if ((int)Application.platform != 2) { log.LogWarning((object)"RepoRTGI native renderer currently supports the Windows player only."); return false; } string text = Path.Combine(pluginDirectory, "RepoRTGI.Native.dll"); if (!File.Exists(text)) { log.LogError((object)("Native renderer is missing: " + text)); return false; } _module = LoadLibrary(text); if (_module == IntPtr.Zero) { log.LogError((object)$"Could not load RepoRTGI.Native.dll (Win32 error {Marshal.GetLastWin32Error()})."); return false; } try { _renderEvent = RepoRtgiGetRenderEventFunc(); } catch (Exception ex) { log.LogError((object)("Native renderer entry point failed: " + ex.Message)); return false; } if (_renderEvent == IntPtr.Zero) { log.LogError((object)"Native renderer returned an invalid render callback."); return false; } return true; } internal static bool Submit(int slot, ref NativeFrameRequest request) { if (!IsLoaded) { return false; } int num = RepoRtgiSubmitFrame(slot, ref request); if (num == 0) { return true; } string lastError = GetLastError(); ManualLogSource? log = _log; if (log != null) { log.LogWarning((object)$"Native RTGI frame was rejected ({num}): {lastError}"); } return false; } internal static string GetLastError() { if (_module == IntPtr.Zero) { return "native module is not loaded"; } StringBuilder stringBuilder = new StringBuilder(1024); RepoRtgiGetLastError(stringBuilder, stringBuilder.Capacity); return stringBuilder.ToString(); } internal static int GetStatus() { if (!(_module == IntPtr.Zero)) { return RepoRtgiGetStatus(); } return -1; } internal static void Shutdown() { _renderEvent = IntPtr.Zero; } [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string fileName); [DllImport("RepoRTGI.Native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "RepoRtgi_GetRenderEventFunc")] private static extern IntPtr RepoRtgiGetRenderEventFunc(); [DllImport("RepoRTGI.Native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "RepoRtgi_SubmitFrame")] private static extern int RepoRtgiSubmitFrame(int slot, ref NativeFrameRequest request); [DllImport("RepoRTGI.Native", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "RepoRtgi_GetLastError")] private static extern void RepoRtgiGetLastError(StringBuilder buffer, int capacity); [DllImport("RepoRTGI.Native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "RepoRtgi_GetStatus")] private static extern int RepoRtgiGetStatus(); } internal struct NativeFrameRequest { internal IntPtr Source; internal IntPtr Destination; internal IntPtr DepthNormals; internal IntPtr HistoryRead; internal IntPtr HistoryWrite; internal int Width; internal int Height; internal int GiWidth; internal int GiHeight; internal int RayCount; internal int StepCount; internal int FrameIndex; internal int ResetHistory; internal float RayDistance; internal float Thickness; internal float Intensity; internal float Saturation; internal float TemporalWeight; internal float DenoiseRadius; internal float FarClip; internal float Projection11; internal float Projection22; } [BepInPlugin("ModsForGames.RepoRTGI", "R.E.P.O. RTGI", "1.0.0")] public sealed class RepoRtgiPlugin : BaseUnityPlugin { public const string PluginGuid = "ModsForGames.RepoRTGI"; public const string PluginName = "R.E.P.O. RTGI"; private static RepoRtgiPlugin? _instance; private static RtgiConfig _config = null; private static GpuClassification _gpu = null; private static bool _sessionDisabled; private static bool _depthWarningReported; private static Camera? _renderCamera; private static FieldInfo? _gameDirectorInstanceField; private static FieldInfo? _gameDirectorMainCameraField; private static readonly List XrDisplays = new List(); private int _nextNativeStatusCheck; private int _nextCameraCheck; private bool _nativeErrorReported; private bool _nativeReadyReported; internal static ManualLogSource Log => ((BaseUnityPlugin)_instance).Logger; internal static RtgiSettings Settings => _config.Resolve(); internal static bool ShouldRender { get { if ((Object)(object)_instance == (Object)null || _sessionDisabled) { return false; } if (IsVrRunning()) { return false; } string value = _config.Activation.Value; if (!(value == "Enabled")) { if (value == "Disabled") { return false; } return _gpu.IsAutomaticTier; } return true; } } internal static bool IsRenderCamera(Camera camera) { return (Object)(object)_renderCamera == (Object)(object)camera; } private static bool IsVrRunning() { SubsystemManager.GetInstances(XrDisplays); foreach (XRDisplaySubsystem xrDisplay in XrDisplays) { if (((IntegratedSubsystem)xrDisplay).running) { return true; } } return false; } private void Awake() { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Invalid comparison between Unknown and I4 //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown _instance = this; _config = new RtgiConfig(((BaseUnityPlugin)this).Config); _gpu = GpuClassifier.Detect(); _config.Changed += OnConfigChanged; bool flag = NativeBridge.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath, ((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogInfo((object)"R.E.P.O. RTGI v1.0.0 loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"GPU: {_gpu.Name} ({_gpu.VramMb} MB). {_gpu.Reason}."); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Graphics API: {SystemInfo.graphicsDeviceType}."); if ((int)SystemInfo.graphicsDeviceType != 2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"RTGI requires Direct3D 11. Start R.E.P.O. with -force-d3d11 to use the effect."); } else if (flag) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(ShouldRender ? "RTGI is active. Change Mode in REPOConfig to disable it." : "RTGI is bypassed. Automatic mode did not enable it for this GPU; manual Enabled remains available.")); } Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnAnyCameraPreCull)); } private void Update() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount >= _nextCameraCheck) { _nextCameraCheck = Time.frameCount + 60; EnsureRenderCamera(); } if (NativeBridge.IsLoaded && !_nativeErrorReported && Time.frameCount >= _nextNativeStatusCheck) { _nextNativeStatusCheck = Time.frameCount + 120; int status = NativeBridge.GetStatus(); if (status > 0 && !_nativeReadyReported) { _nativeReadyReported = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Native RTGI renderer initialized successfully."); } else if (status < 0) { _nativeErrorReported = true; ((BaseUnityPlugin)this).Logger.LogError((object)("Native RTGI renderer stopped: " + NativeBridge.GetLastError())); } } if (Enum.TryParse(_config.ToggleKey.Value, ignoreCase: true, out KeyCode result) && Input.GetKeyDown(result)) { _sessionDisabled = !_sessionDisabled; RefreshAttachedEffects(resetHistory: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)(_sessionDisabled ? "RTGI disabled for this session." : "RTGI session override cleared.")); } } private void OnAnyCameraPreCull(Camera camera) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (ShouldRender && NativeBridge.IsLoaded && (int)SystemInfo.graphicsDeviceType == 2) { Camera val = ResolveRenderCamera(); if ((Object)(object)val == (Object)null && LooksLikeWorldCamera(camera)) { _renderCamera = camera; val = camera; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Selected fallback render camera '" + ((Object)camera).name + "'.")); } if (!((Object)(object)camera != (Object)(object)val) && !((Object)(object)((Component)camera).GetComponent() != (Object)null)) { ((Component)camera).gameObject.AddComponent(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Attached RTGI to render camera '" + ((Object)camera).name + "'.")); } } } private void EnsureRenderCamera() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (!ShouldRender || !NativeBridge.IsLoaded || (int)SystemInfo.graphicsDeviceType != 2) { RefreshAttachedEffects(); return; } Camera val = ResolveRenderCamera(); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Attached RTGI to render camera '" + ((Object)val).name + "'.")); } RefreshAttachedEffects(); } private static bool LooksLikeWorldCamera(Camera camera) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if (!((Behaviour)camera).enabled || !((Component)camera).gameObject.activeInHierarchy || (int)camera.cameraType != 1 || camera.cullingMask == 0) { return false; } string text = ((Object)camera).name.ToLowerInvariant(); if (!text.Contains("overlay") && !text.Contains("ui") && !text.Contains("map") && !text.Contains("preview")) { return !text.Contains("icon"); } return false; } private void OnConfigChanged() { _sessionDisabled = false; Camera val = ResolveRenderCamera(); if (ShouldRender && (Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); } RefreshAttachedEffects(resetHistory: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)("RTGI settings updated. Effective state: " + (ShouldRender ? "enabled" : "disabled") + ".")); } private static void RefreshAttachedEffects(bool resetHistory = false) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 Camera val = ResolveRenderCamera(); bool flag = ShouldRender && NativeBridge.IsLoaded && (int)SystemInfo.graphicsDeviceType == 2; RtgiCameraEffect[] array = Object.FindObjectsOfType(); foreach (RtgiCameraEffect rtgiCameraEffect in array) { bool flag2 = flag && (Object)(object)rtgiCameraEffect.TargetCamera == (Object)(object)val; if (((Behaviour)rtgiCameraEffect).enabled != flag2) { ((Behaviour)rtgiCameraEffect).enabled = flag2; } if (flag2 && resetHistory) { rtgiCameraEffect.ResetHistory(); } } } private static Camera? ResolveRenderCamera() { Camera val = null; try { if (_gameDirectorInstanceField == null || _gameDirectorMainCameraField == null) { Type? type = Type.GetType("GameDirector, Assembly-CSharp"); _gameDirectorInstanceField = type?.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _gameDirectorMainCameraField = type?.GetField("MainCamera", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object obj = _gameDirectorInstanceField?.GetValue(null); if (obj != null) { object? obj2 = _gameDirectorMainCameraField?.GetValue(obj); val = (Camera)((obj2 is Camera) ? obj2 : null); } } catch (Exception ex) { if ((Object)(object)_instance != (Object)null) { ((BaseUnityPlugin)_instance).Logger.LogDebug((object)("GameDirector camera lookup is not ready: " + ex.Message)); } } if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val != (Object)(object)_renderCamera) { _renderCamera = val; if ((Object)(object)val != (Object)null && (Object)(object)_instance != (Object)null) { ((BaseUnityPlugin)_instance).Logger.LogInfo((object)("Selected render camera '" + ((Object)val).name + "'.")); } } return _renderCamera; } internal static void ReportMissingDepthNormals() { if (!_depthWarningReported && !((Object)(object)_instance == (Object)null)) { _depthWarningReported = true; ((BaseUnityPlugin)_instance).Logger.LogWarning((object)"The main camera did not expose a depth-normal texture. RTGI will retry on later frames."); } } private void OnDestroy() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnAnyCameraPreCull)); _config.Changed -= OnConfigChanged; NativeBridge.Shutdown(); _instance = null; } } [DisallowMultipleComponent] [RequireComponent(typeof(Camera))] internal sealed class RtgiCameraEffect : MonoBehaviour { private Camera _camera; private RenderTexture? _historyA; private RenderTexture? _historyB; private RenderTexture? _composite; private bool _historyFlip; private bool _resetHistory = true; private int _frameIndex; internal Camera TargetCamera => _camera; private void Awake() { _camera = ((Component)this).GetComponent(); } private void OnEnable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Camera camera = _camera; camera.depthTextureMode = (DepthTextureMode)(camera.depthTextureMode | 2); _resetHistory = true; } private void OnPreCull() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Camera camera = _camera; camera.depthTextureMode = (DepthTextureMode)(camera.depthTextureMode | 2); } internal void ResetHistory() { _resetHistory = true; } private void OnRenderImage(RenderTexture source, RenderTexture destination) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) if (!RepoRtgiPlugin.ShouldRender || !NativeBridge.IsLoaded || (int)SystemInfo.graphicsDeviceType != 2 || !RepoRtgiPlugin.IsRenderCamera(_camera)) { Graphics.Blit((Texture)(object)source, destination); return; } Texture globalTexture = Shader.GetGlobalTexture("_CameraDepthNormalsTexture"); RenderTexture val = (RenderTexture)(object)((globalTexture is RenderTexture) ? globalTexture : null); if ((Object)(object)val == (Object)null) { RepoRtgiPlugin.ReportMissingDepthNormals(); Graphics.Blit((Texture)(object)source, destination); return; } RtgiSettings settings = RepoRtgiPlugin.Settings; EnsureTargets(source, settings.ResolutionScale); if ((Object)(object)_historyA == (Object)null || (Object)(object)_historyB == (Object)null || (Object)(object)_composite == (Object)null) { Graphics.Blit((Texture)(object)source, destination); return; } Graphics.Blit((Texture)(object)source, _composite); RenderTexture val2 = (_historyFlip ? _historyB : _historyA); RenderTexture val3 = (_historyFlip ? _historyA : _historyB); Matrix4x4 projectionMatrix = _camera.projectionMatrix; NativeFrameRequest request = new NativeFrameRequest { Source = ((Texture)source).GetNativeTexturePtr(), Destination = ((Texture)_composite).GetNativeTexturePtr(), DepthNormals = ((Texture)val).GetNativeTexturePtr(), HistoryRead = ((Texture)val2).GetNativeTexturePtr(), HistoryWrite = ((Texture)val3).GetNativeTexturePtr(), Width = ((Texture)source).width, Height = ((Texture)source).height, GiWidth = ((Texture)val3).width, GiHeight = ((Texture)val3).height, RayCount = settings.RayCount, StepCount = settings.StepCount, FrameIndex = _frameIndex, ResetHistory = (_resetHistory ? 1 : 0), RayDistance = settings.RayDistance, Thickness = settings.Thickness, Intensity = settings.Intensity, Saturation = settings.Saturation, TemporalWeight = settings.TemporalWeight, DenoiseRadius = settings.DenoiseRadius, FarClip = _camera.farClipPlane, Projection11 = projectionMatrix.m00, Projection22 = projectionMatrix.m11 }; int num = _frameIndex & 0xF; if (request.Source != IntPtr.Zero && request.Destination != IntPtr.Zero && request.DepthNormals != IntPtr.Zero && request.HistoryRead != IntPtr.Zero && request.HistoryWrite != IntPtr.Zero && NativeBridge.Submit(num, ref request)) { GL.IssuePluginEvent(NativeBridge.RenderEvent, num); _historyFlip = !_historyFlip; _resetHistory = false; _frameIndex++; } Graphics.Blit((Texture)(object)_composite, destination); } private void EnsureTargets(RenderTexture source, float scale) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown int num = Mathf.Max(16, Mathf.RoundToInt((float)((Texture)source).width * scale)); int num2 = Mathf.Max(16, Mathf.RoundToInt((float)((Texture)source).height * scale)); if (!((Object)(object)_historyA != (Object)null) || !((Object)(object)_historyB != (Object)null) || !((Object)(object)_composite != (Object)null) || ((Texture)_historyA).width != num || ((Texture)_historyA).height != num2 || ((Texture)_composite).width != ((Texture)source).width || ((Texture)_composite).height != ((Texture)source).height) { ReleaseTargets(); _historyA = CreateHistory(num, num2, "RepoRTGI History A"); _historyB = CreateHistory(num, num2, "RepoRTGI History B"); RenderTextureDescriptor descriptor = source.descriptor; ((RenderTextureDescriptor)(ref descriptor)).depthBufferBits = 0; ((RenderTextureDescriptor)(ref descriptor)).msaaSamples = 1; ((RenderTextureDescriptor)(ref descriptor)).useMipMap = false; ((RenderTextureDescriptor)(ref descriptor)).autoGenerateMips = false; ((RenderTextureDescriptor)(ref descriptor)).enableRandomWrite = false; _composite = new RenderTexture(descriptor) { name = "RepoRTGI Composite", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; _composite.Create(); _historyFlip = false; _resetHistory = true; _frameIndex = 0; } } private static RenderTexture CreateHistory(int width, int height, string name) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown RenderTexture val = new RenderTexture(width, height, 0, (RenderTextureFormat)2, (RenderTextureReadWrite)1) { name = name, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, useMipMap = false, autoGenerateMips = false, hideFlags = (HideFlags)61 }; val.Create(); return val; } private void OnDisable() { ReleaseTargets(); } private void OnDestroy() { ReleaseTargets(); } private void ReleaseTargets() { Release(ref _historyA); Release(ref _historyB); Release(ref _composite); } private static void Release(ref RenderTexture? texture) { if (!((Object)(object)texture == (Object)null)) { texture.Release(); Object.Destroy((Object)(object)texture); texture = null; } } } internal sealed class RtgiConfig { internal readonly ConfigEntry Activation; internal readonly ConfigEntry QualityPreset; internal readonly ConfigEntry Intensity; internal readonly ConfigEntry Saturation; internal readonly ConfigEntry ResolutionScale; internal readonly ConfigEntry RayCount; internal readonly ConfigEntry StepCount; internal readonly ConfigEntry RayDistance; internal readonly ConfigEntry Thickness; internal readonly ConfigEntry TemporalWeight; internal readonly ConfigEntry DenoiseRadius; internal readonly ConfigEntry ToggleKey; internal event Action? Changed; internal RtgiConfig(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected O, but got Unknown Activation = config.Bind("01. Activation", "Mode", "Automatic", new ConfigDescription("Automatic enables RTGI only on an RTX 5070-class or faster GPU. Enabled is a manual override. Disabled fully bypasses the renderer.", (AcceptableValueBase)(object)new AcceptableValueList(new string[3] { "Automatic", "Enabled", "Disabled" }), Array.Empty())); QualityPreset = config.Bind("02. Quality", "Preset", "High", new ConfigDescription("Low, Medium, High and Ultra use tuned settings. Choose Custom to use every value in 03. Advanced.", (AcceptableValueBase)(object)new AcceptableValueList(new string[5] { "Low", "Medium", "High", "Ultra", "Custom" }), Array.Empty())); Intensity = config.Bind("02. Quality", "Indirect Light Intensity", 1f, new ConfigDescription("Strength of bounced indirect light.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3f), Array.Empty())); Saturation = config.Bind("02. Quality", "Bounce Saturation", 1f, new ConfigDescription("Color saturation of bounced light. 0 is monochrome; 1 preserves the source color.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 2f), Array.Empty())); ResolutionScale = config.Bind("03. Advanced", "GI Resolution Scale", 0.75f, new ConfigDescription("Internal RTGI resolution. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 1f), Array.Empty())); RayCount = config.Bind("03. Advanced", "Rays Per Pixel", 3, new ConfigDescription("Diffuse rays evaluated per pixel. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 8), Array.Empty())); StepCount = config.Bind("03. Advanced", "Steps Per Ray", 28, new ConfigDescription("Maximum ray-march steps. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 64), Array.Empty())); RayDistance = config.Bind("03. Advanced", "Ray Distance", 25f, new ConfigDescription("Maximum view-space ray length. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 60f), Array.Empty())); Thickness = config.Bind("03. Advanced", "Depth Thickness", 0.5f, new ConfigDescription("Screen-space hit thickness. Raise it when thin geometry loses bounced light. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 2f), Array.Empty())); TemporalWeight = config.Bind("03. Advanced", "Temporal Stability", 0.85f, new ConfigDescription("History weight. Higher values reduce noise but may increase ghosting. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.97f), Array.Empty())); DenoiseRadius = config.Bind("03. Advanced", "Denoise Radius", 2, new ConfigDescription("Edge-aware spatial filter radius. 0 disables spatial denoising. Used only by the Custom preset.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3), Array.Empty())); ToggleKey = config.Bind("01. Activation", "Session Toggle Key", "F8", new ConfigDescription("Temporarily toggles the effect without changing saved settings.", (AcceptableValueBase)(object)new AcceptableValueList(new string[6] { "F5", "F6", "F7", "F8", "F9", "F10" }), Array.Empty())); Subscribe(Activation); Subscribe(QualityPreset); Subscribe(Intensity); Subscribe(Saturation); Subscribe(ResolutionScale); Subscribe(RayCount); Subscribe(StepCount); Subscribe(RayDistance); Subscribe(Thickness); Subscribe(TemporalWeight); Subscribe(DenoiseRadius); Subscribe(ToggleKey); } internal RtgiSettings Resolve() { RtgiSettings result = QualityPreset.Value switch { "Low" => new RtgiSettings(0.5f, 1, 12, 12f, 0.8f, 0.72f, 1), "Medium" => new RtgiSettings(0.66f, 2, 20, 18f, 0.65f, 0.8f, 1), "Ultra" => new RtgiSettings(1f, 4, 40, 35f, 0.4f, 0.9f, 3), "Custom" => new RtgiSettings(ResolutionScale.Value, RayCount.Value, StepCount.Value, RayDistance.Value, Thickness.Value, TemporalWeight.Value, DenoiseRadius.Value), _ => new RtgiSettings(0.75f, 3, 28, 25f, 0.5f, 0.85f, 2), }; result.Intensity = Intensity.Value; result.Saturation = Saturation.Value; return result; } private void Subscribe(ConfigEntry entry) { entry.SettingChanged += delegate { this.Changed?.Invoke(); }; } } internal struct RtgiSettings { internal float ResolutionScale; internal int RayCount; internal int StepCount; internal float RayDistance; internal float Thickness; internal float TemporalWeight; internal int DenoiseRadius; internal float Intensity; internal float Saturation; internal RtgiSettings(float resolutionScale, int rayCount, int stepCount, float rayDistance, float thickness, float temporalWeight, int denoiseRadius) { ResolutionScale = resolutionScale; RayCount = rayCount; StepCount = stepCount; RayDistance = rayDistance; Thickness = thickness; TemporalWeight = temporalWeight; DenoiseRadius = denoiseRadius; Intensity = 1f; Saturation = 1f; } } }