diff --git a/Assets/Scripts/DebugDumper.cs b/Assets/Scripts/DebugDumper.cs index 4c19a74..e4d956e 100644 --- a/Assets/Scripts/DebugDumper.cs +++ b/Assets/Scripts/DebugDumper.cs @@ -46,6 +46,7 @@ public class DebugDumper : MonoBehaviour Debug.Log(sb); _layer = GetComponent(); + _layer.superResolution.dynamicScale = _scaleFactor; } void Update() @@ -84,11 +85,12 @@ public class DebugDumper : MonoBehaviour } float vertical = Input.GetAxis("Vertical"); - if (vertical is < -0.3f or > 0.3f && Time.realtimeSinceStartup > _lastScaleTime + 0.5f) + if (vertical is < -0.3f or > 0.3f && Time.realtimeSinceStartup > _lastScaleTime + 0.3f) { - _scaleFactor += 0.1f * Math.Sign(vertical); + _scaleFactor += 0.05f * Math.Sign(vertical); _scaleFactor = Mathf.Clamp(_scaleFactor, 0.1f, 1.0f); + _layer.superResolution.dynamicScale = _scaleFactor; _lastScaleTime = Time.realtimeSinceStartup; } } @@ -107,7 +109,7 @@ public class DebugDumper : MonoBehaviour GUILayout.Label($"FSR2: {(_layer.antialiasingMode == PostProcessLayer.Antialiasing.SuperResolution ? "Enabled" : "Disabled")}"); GUILayout.Label($"Quality: {_layer.superResolution.qualityMode}"); GUILayout.Label($"Auto-exposure: {(_layer.superResolution.exposureSource)}"); - GUILayout.Label($"Scale: {_scaleFactor:0.00}"); + GUILayout.Label($"Scale: {_layer.superResolution.dynamicScale:0.00}"); if (Input.GetButton("Jump")) { GUILayout.Label("Reset"); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/SuperResolution.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/SuperResolution.cs index b9c653c..fb3f6ac 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/SuperResolution.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/SuperResolution.cs @@ -99,13 +99,14 @@ namespace UnityEngine.Rendering.PostProcessing [Range(0, 1)] public float autoReactiveMax = 0.9f; } + public float dynamicScale { get; set; } = 1.0f; public Vector2 jitter { get; private set; } - public Vector2Int renderSize => _renderSize; + public Vector2Int renderSize => GetScaledRenderSize(); public Vector2Int displaySize => _displaySize; public RenderTargetIdentifier colorOpaqueOnly { get; set; } private Fsr2Context _fsrContext; - private Vector2Int _renderSize; + private Vector2Int _maxRenderSize; private Vector2Int _displaySize; private bool _resetHistory; @@ -153,12 +154,13 @@ namespace UnityEngine.Rendering.PostProcessing // Determine the desired rendering and display resolutions _displaySize = new Vector2Int(camera.pixelWidth, camera.pixelHeight); - Fsr2.GetRenderResolutionFromQualityMode(out int renderWidth, out int renderHeight, _displaySize.x, _displaySize.y, qualityMode); - _renderSize = new Vector2Int(renderWidth, renderHeight); + Fsr2.GetRenderResolutionFromQualityMode(out int maxRenderWidth, out int maxRenderHeight, _displaySize.x, _displaySize.y, qualityMode); + _maxRenderSize = new Vector2Int(maxRenderWidth, maxRenderHeight); // Render to a smaller portion of the screen by manipulating the camera's viewport rect + var scaledRenderSize = GetScaledRenderSize(); camera.aspect = (_displaySize.x * _originalRect.width) / (_displaySize.y * _originalRect.height); - camera.rect = new Rect(0, 0, _originalRect.width * _renderSize.x / _displaySize.x, _originalRect.height * _renderSize.y / _displaySize.y); + camera.rect = new Rect(0, 0, _originalRect.width * scaledRenderSize.x / _displaySize.x, _originalRect.height * scaledRenderSize.y / _displaySize.y); } public void ResetCameraViewport(PostProcessRenderContext context) @@ -188,8 +190,9 @@ namespace UnityEngine.Rendering.PostProcessing if (autoGenerateReactiveMask) { SetupAutoReactiveDescription(context); - - cmd.GetTemporaryRT(Fsr2ShaderIDs.UavAutoReactive, _renderSize.x, _renderSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true); + + var scaledRenderSize = _genReactiveDescription.RenderSize; + cmd.GetTemporaryRT(Fsr2ShaderIDs.UavAutoReactive, scaledRenderSize.x, scaledRenderSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true); _fsrContext.GenerateReactiveMask(_genReactiveDescription, cmd); _dispatchDescription.Reactive = Fsr2ShaderIDs.UavAutoReactive; } @@ -214,10 +217,10 @@ namespace UnityEngine.Rendering.PostProcessing if (exposureSource == ExposureSource.Auto) flags |= Fsr2.InitializationFlags.EnableAutoExposure; _callbacks = callbacksFactory(context); - _fsrContext = Fsr2.CreateContext(_displaySize, _renderSize, _callbacks, flags); + _fsrContext = Fsr2.CreateContext(_displaySize, _maxRenderSize, _callbacks, flags); // Apply a mipmap bias so that textures retain their sharpness - float biasOffset = Fsr2.GetMipmapBiasOffset(_renderSize.x, _displaySize.x); + float biasOffset = Fsr2.GetMipmapBiasOffset(_maxRenderSize.x, _displaySize.x); if (!float.IsNaN(biasOffset) && !float.IsInfinity(biasOffset)) { _callbacks.ApplyMipmapBias(biasOffset); @@ -247,14 +250,16 @@ namespace UnityEngine.Rendering.PostProcessing private void ApplyJitter(Camera camera) { + var scaledRenderSize = GetScaledRenderSize(); + // Perform custom jittering of the camera's projection matrix according to FSR2's recipe - int jitterPhaseCount = Fsr2.GetJitterPhaseCount(_renderSize.x, _displaySize.x); + int jitterPhaseCount = Fsr2.GetJitterPhaseCount(scaledRenderSize.x, _displaySize.x); Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount); _dispatchDescription.JitterOffset = new Vector2(jitterX, jitterY); - jitterX = 2.0f * jitterX / _renderSize.x; - jitterY = 2.0f * jitterY / _renderSize.y; + jitterX = 2.0f * jitterX / scaledRenderSize.x; + jitterY = 2.0f * jitterY / scaledRenderSize.y; var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0)); camera.nonJitteredProjectionMatrix = camera.projectionMatrix; @@ -281,15 +286,17 @@ namespace UnityEngine.Rendering.PostProcessing if (exposureSource == ExposureSource.Unity) _dispatchDescription.Exposure = context.autoExposureTexture; if (reactiveMask != null) _dispatchDescription.Reactive = reactiveMask; if (transparencyAndCompositionMask != null) _dispatchDescription.TransparencyAndComposition = transparencyAndCompositionMask; + + var scaledRenderSize = GetScaledRenderSize(); _dispatchDescription.Output = context.destination; _dispatchDescription.PreExposure = preExposure; _dispatchDescription.EnableSharpening = performSharpenPass; _dispatchDescription.Sharpness = sharpness; - _dispatchDescription.MotionVectorScale.x = -_renderSize.x; - _dispatchDescription.MotionVectorScale.y = -_renderSize.y; - _dispatchDescription.RenderSize = _renderSize; - _dispatchDescription.InputResourceSize = _renderSize; // TODO: this may need to be maxRenderSize to support dynamic resolution + _dispatchDescription.MotionVectorScale.x = -scaledRenderSize.x; + _dispatchDescription.MotionVectorScale.y = -scaledRenderSize.y; + _dispatchDescription.RenderSize = scaledRenderSize; + _dispatchDescription.InputResourceSize = scaledRenderSize; _dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime; _dispatchDescription.CameraNear = camera.nearClipPlane; _dispatchDescription.CameraFar = camera.farClipPlane; @@ -321,13 +328,21 @@ namespace UnityEngine.Rendering.PostProcessing _genReactiveDescription.ColorOpaqueOnly = colorOpaqueOnly; _genReactiveDescription.ColorPreUpscale = null; _genReactiveDescription.OutReactive = null; - _genReactiveDescription.RenderSize = _renderSize; + _genReactiveDescription.RenderSize = GetScaledRenderSize(); _genReactiveDescription.Scale = generateReactiveParameters.scale; _genReactiveDescription.CutoffThreshold = generateReactiveParameters.cutoffThreshold; _genReactiveDescription.BinaryValue = generateReactiveParameters.binaryValue; _genReactiveDescription.Flags = generateReactiveParameters.flags; } + private Vector2Int GetScaledRenderSize() + { + if (Mathf.Approximately(dynamicScale, 1.0f)) + return _maxRenderSize; + + return new Vector2Int(Mathf.CeilToInt(_maxRenderSize.x * dynamicScale), Mathf.CeilToInt(_maxRenderSize.y * dynamicScale)); + } + private class Callbacks : Fsr2CallbacksBase { private readonly PostProcessResources _resources;