@ -42,10 +42,11 @@ namespace FidelityFX
private Fsr2Context _fsrContext ;
private Fsr2Context _fsrContext ;
private Fsr2PostProcessHelper _helper ;
private Fsr2PostProcessHelper _helper ;
private Vector2Int _d isplaySize;
private Vector2Int _renderSize ;
private ref Vector2Int DisplaySize = > ref _helper . D isplaySize;
private ref Vector2Int RenderSize = > ref _helpe r . R enderSize;
private Fsr2 . QualityMode _prevQualityMode ;
private Fsr2 . QualityMode _prevQualityMode ;
private Vector2Int _prevDisplaySize ;
public override void Init ( )
public override void Init ( )
{
{
@ -77,16 +78,6 @@ namespace FidelityFX
return ;
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
// Ensure that the helper script exists and is enabled
if ( _helper = = null | | ! _helper . enabled )
if ( _helper = = null | | ! _helper . enabled )
{
{
@ -100,6 +91,16 @@ namespace FidelityFX
return ;
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
//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.
// TODO: executing in OnPreCull means we can do jittering in here, at least. Rect manipulation should still happen before PPV2 entirely.
ApplyJitter ( context . camera ) ;
ApplyJitter ( context . camera ) ;
@ -122,9 +123,10 @@ namespace FidelityFX
private void CreateFsrContext ( PostProcessRenderContext context )
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 ;
Fsr2 . InitializationFlags flags = 0 ;
if ( context . camera . allowHDR ) flags | = Fsr2 . InitializationFlags . EnableHighDynamicRange ;
if ( context . camera . allowHDR ) flags | = Fsr2 . InitializationFlags . EnableHighDynamicRange ;
@ -135,7 +137,11 @@ namespace FidelityFX
flags | = Fsr2 . InitializationFlags . EnableDebugChecking ;
flags | = Fsr2 . InitializationFlags . EnableDebugChecking ;
#endif
#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 ( )
private void DestroyFsrContext ( )
@ -144,17 +150,21 @@ namespace FidelityFX
{
{
_fsrContext . Destroy ( ) ;
_fsrContext . Destroy ( ) ;
_fsrContext = null ;
_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 )
private void ApplyJitter ( Camera camera )
{
{
// Perform custom jittering of the camera's projection matrix according to FSR2's recipe
// Perform custom jittering of the camera's projection matrix according to FSR2's recipe
int jitterPhaseCount = Fsr2 . GetJitterPhaseCount ( _r enderSize. x , _d isplaySize. x ) ;
int jitterPhaseCount = Fsr2 . GetJitterPhaseCount ( R enderSize. x , D isplaySize. x ) ;
Fsr2 . GetJitterOffset ( out float jitterX , out float jitterY , Time . frameCount , jitterPhaseCount ) ;
Fsr2 . GetJitterOffset ( out float jitterX , out float jitterY , Time . frameCount , jitterPhaseCount ) ;
jitterX = 2.0f * jitterX / _r enderSize. x ;
jitterY = 2.0f * jitterY / _r enderSize. y ;
jitterX = 2.0f * jitterX / R enderSize. x ;
jitterY = 2.0f * jitterY / R enderSize. y ;
var jitterTranslationMatrix = Matrix4x4 . Translate ( new Vector3 ( jitterX , jitterY , 0 ) ) ;
var jitterTranslationMatrix = Matrix4x4 . Translate ( new Vector3 ( jitterX , jitterY , 0 ) ) ;
camera . nonJitteredProjectionMatrix = camera . projectionMatrix ;
camera . nonJitteredProjectionMatrix = camera . projectionMatrix ;
@ -166,26 +176,64 @@ namespace FidelityFX
internal class Fsr2PostProcessHelper : MonoBehaviour
internal class Fsr2PostProcessHelper : MonoBehaviour
{
{
internal Fsr2PostProcessEffect Settings ;
internal Fsr2PostProcessEffect Settings ;
internal Vector2Int DisplaySize ;
internal Vector2Int RenderSize ;
private Camera _camera ;
private Camera _camera ;
private Rect _originalRect ;
private void Awake ( )
private void Awake ( )
{
{
_camera = GetComponent < Camera > ( ) ;
_camera = GetComponent < Camera > ( ) ;
// TODO: inject opaque-only command buffer & anything else?
// 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 ( ) ) ;
}
/// <summary>
/// This needs to run before PostProcessLayer's OnPreCull, hence why we place this code in LateUpdate.
/// </summary>
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 ( )
{
while ( true )
{
{
yield return new WaitForEndOfFrame ( ) ;
_camera . rect = _originalRect ;
_camera . ResetProjectionMatrix ( ) ;
_camera . ResetProjectionMatrix ( ) ;
}
}
}
}
}
}
}
#endif // UNITY_POST_PROCESSING_STACK_V2
#endif // UNITY_POST_PROCESSING_STACK_V2