diff --git a/Assets/Scenes/SampleScenePPV2.unity b/Assets/Scenes/SampleScenePPV2.unity index ba76870..fb21bd0 100644 --- a/Assets/Scenes/SampleScenePPV2.unity +++ b/Assets/Scenes/SampleScenePPV2.unity @@ -152,7 +152,7 @@ Light: m_Type: 1 m_Shape: 0 m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 + m_Intensity: 3 m_Range: 10 m_SpotAngle: 30 m_InnerSpotAngle: 21.80208 diff --git a/Assets/Scenes/SampleScenePPV2_Profiles/Main Camera Profile.asset b/Assets/Scenes/SampleScenePPV2_Profiles/Main Camera Profile.asset index 5199d52..bc57051 100644 --- a/Assets/Scenes/SampleScenePPV2_Profiles/Main Camera Profile.asset +++ b/Assets/Scenes/SampleScenePPV2_Profiles/Main Camera Profile.asset @@ -14,6 +14,54 @@ MonoBehaviour: m_EditorClassIdentifier: settings: - {fileID: 3185594499184808736} + - {fileID: 318921389242660834} +--- !u!114 &318921389242660834 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 48a79b01ea5641d4aa6daa2e23605641, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + intensity: + overrideState: 1 + value: 2 + threshold: + overrideState: 1 + value: 1 + softKnee: + overrideState: 0 + value: 0.5 + clamp: + overrideState: 0 + value: 65472 + diffusion: + overrideState: 1 + value: 4 + anamorphicRatio: + overrideState: 0 + value: 0 + color: + overrideState: 0 + value: {r: 1, g: 1, b: 1, a: 1} + fastMode: + overrideState: 0 + value: 0 + dirtTexture: + overrideState: 0 + value: {fileID: 0} + defaultState: 1 + dirtIntensity: + overrideState: 0 + value: 0 --- !u!114 &3185594499184808736 MonoBehaviour: m_ObjectHideFlags: 3 @@ -33,6 +81,24 @@ MonoBehaviour: qualityMode: overrideState: 0 value: 2 + performSharpenPass: + overrideState: 0 + value: 1 + sharpness: + overrideState: 0 + value: 0.8 + enableFP16: + overrideState: 0 + value: 0 + enableAutoExposure: + overrideState: 0 + value: 1 + preExposure: + overrideState: 0 + value: 1 + autoGenerateReactiveMask: + overrideState: 0 + value: 1 --- !u!114 &4429786910217829299 MonoBehaviour: m_ObjectHideFlags: 3 diff --git a/Assets/Scripts/Fsr2ImageEffect.cs b/Assets/Scripts/Fsr2ImageEffect.cs index 66de6d8..fdf875b 100644 --- a/Assets/Scripts/Fsr2ImageEffect.cs +++ b/Assets/Scripts/Fsr2ImageEffect.cs @@ -105,7 +105,7 @@ namespace FidelityFX _renderCamera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _opaqueInputCommandBuffer); } - // Apply a mipmap bias so that textures retain their original sharpness + // Apply a mipmap bias so that textures retain their sharpness float biasOffset = Fsr2.GetMipmapBiasOffset(_renderSize.x, _displaySize.x); Fsr2.GlobalCallbacks.ApplyMipmapBias(biasOffset); diff --git a/Assets/Scripts/Fsr2PostProcessEffect.cs b/Assets/Scripts/Fsr2PostProcessEffect.cs index 3aefdb7..8903415 100644 --- a/Assets/Scripts/Fsr2PostProcessEffect.cs +++ b/Assets/Scripts/Fsr2PostProcessEffect.cs @@ -42,10 +42,11 @@ namespace FidelityFX private Fsr2Context _fsrContext; private Fsr2PostProcessHelper _helper; - private Vector2Int _displaySize; - private Vector2Int _renderSize; + private ref Vector2Int DisplaySize => ref _helper.DisplaySize; + private ref Vector2Int RenderSize => ref _helper.RenderSize; private Fsr2.QualityMode _prevQualityMode; + private Vector2Int _prevDisplaySize; public override void Init() { @@ -77,16 +78,6 @@ namespace FidelityFX return; } - // Monitor for any resolution changes and recreate the FSR2 context if necessary - // We can't create an FSR2 context without info from the post-processing context, so delay the initial setup until here - if (_fsrContext == null || context.screenWidth != _displaySize.x || context.screenHeight != _displaySize.y || settings.qualityMode != _prevQualityMode) - { - DestroyFsrContext(); - CreateFsrContext(context); - - _prevQualityMode = settings.qualityMode; - } - // Ensure that the helper script exists and is enabled if (_helper == null || !_helper.enabled) { @@ -99,6 +90,16 @@ namespace FidelityFX cmd.BlitFullscreenTriangle(context.source, context.destination); return; } + + // Monitor for any resolution changes and recreate the FSR2 context if necessary + // We can't create an FSR2 context without info from the post-processing context, so delay the initial setup until here + if (_fsrContext == null || DisplaySize.x != _prevDisplaySize.x || DisplaySize.y != _prevDisplaySize.y || settings.qualityMode != _prevQualityMode) + { + DestroyFsrContext(); + CreateFsrContext(context); + + _prevQualityMode = settings.qualityMode; + } //Debug.Log("[FSR2] Render, where am I being called from?"); // In OnPreCull... OH // TODO: executing in OnPreCull means we can do jittering in here, at least. Rect manipulation should still happen before PPV2 entirely. @@ -122,9 +123,10 @@ namespace FidelityFX private void CreateFsrContext(PostProcessRenderContext context) { - _displaySize = new Vector2Int(context.screenWidth, context.screenHeight); - Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, _displaySize.x, _displaySize.y, settings.qualityMode); - _renderSize = new Vector2Int(renderWidth, renderHeight); + _prevDisplaySize = DisplaySize; + + Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, DisplaySize.x, DisplaySize.y, settings.qualityMode); + RenderSize = new Vector2Int(renderWidth, renderHeight); Fsr2.InitializationFlags flags = 0; if (context.camera.allowHDR) flags |= Fsr2.InitializationFlags.EnableHighDynamicRange; @@ -135,7 +137,11 @@ namespace FidelityFX flags |= Fsr2.InitializationFlags.EnableDebugChecking; #endif - _fsrContext = Fsr2.CreateContext(_displaySize, _renderSize, flags); + _fsrContext = Fsr2.CreateContext(DisplaySize, RenderSize, flags); + + // Apply a mipmap bias so that textures retain their sharpness + float biasOffset = Fsr2.GetMipmapBiasOffset(RenderSize.x, DisplaySize.x); + Fsr2.GlobalCallbacks.ApplyMipmapBias(biasOffset); } private void DestroyFsrContext() @@ -144,17 +150,21 @@ namespace FidelityFX { _fsrContext.Destroy(); _fsrContext = null; + + // Undo the previous mipmap bias adjustment + float biasOffset = Fsr2.GetMipmapBiasOffset(RenderSize.x, _prevDisplaySize.x); + Fsr2.GlobalCallbacks.ApplyMipmapBias(-biasOffset); } } private void ApplyJitter(Camera camera) { // 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(RenderSize.x, DisplaySize.x); Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount); - jitterX = 2.0f * jitterX / _renderSize.x; - jitterY = 2.0f * jitterY / _renderSize.y; + jitterX = 2.0f * jitterX / RenderSize.x; + jitterY = 2.0f * jitterY / RenderSize.y; var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0)); camera.nonJitteredProjectionMatrix = camera.projectionMatrix; @@ -166,25 +176,63 @@ namespace FidelityFX internal class Fsr2PostProcessHelper : MonoBehaviour { internal Fsr2PostProcessEffect Settings; + internal Vector2Int DisplaySize; + internal Vector2Int RenderSize; private Camera _camera; + private Rect _originalRect; private void Awake() { _camera = GetComponent(); // TODO: inject opaque-only command buffer & anything else? + + DisplaySize.x = _camera.pixelWidth; + DisplaySize.y = _camera.pixelHeight; + RenderSize = DisplaySize; } - private void OnPreCull() // TODO: may need to do this in LateUpdate instead? So we execute before PPV2's OnPreCull + private void Start() + { + StartCoroutine(CResetCamera()); + } + + /// + /// This needs to run before PostProcessLayer's OnPreCull, hence why we place this code in LateUpdate. + /// + private void LateUpdate() { - // TODO: check if FSR2 is still enabled; if not: reset PPV2 source texture & disable self - // TODO: fiddle with the camera parameters, rect, jitter, etc - // Debug.Log("[FSR2] OnPreCull"); + if (!Settings.enabled) + { + enabled = false; + return; + } + + // Relay information about the camera's output size before rescaling + DisplaySize.x = _camera.pixelWidth; + DisplaySize.y = _camera.pixelHeight; + + // Render to a smaller portion of the screen by manipulating the camera's viewport rect + _originalRect = _camera.rect; + _camera.aspect = (_camera.pixelWidth * _originalRect.width) / (_camera.pixelHeight * _originalRect.height); + _camera.rect = new Rect(0, 0, _originalRect.width * RenderSize.x / DisplaySize.x, _originalRect.height * RenderSize.y / DisplaySize.y); } - private void OnPostRender() + // private void OnPreCull() // TODO: may need to do this in LateUpdate instead? So we execute before PPV2's OnPreCull + // { + // // TODO: check if FSR2 is still enabled; if not: reset PPV2 source texture & disable self + // // TODO: fiddle with the camera parameters, rect, jitter, etc + // } + + private IEnumerator CResetCamera() { - _camera.ResetProjectionMatrix(); + while (true) + { + yield return new WaitForEndOfFrame(); + + _camera.rect = _originalRect; + _camera.ResetProjectionMatrix(); + } } } }