FSR2 tests in Unity based on built-in render pipeline
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

134 lines
5.8 KiB

// Copyright (c) 2023 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
///
/// </summary>
[RequireComponent(typeof(Camera))]
public class Fsr2CameraHelper : MonoBehaviour
{
[Tooltip("Standard scaling ratio presets.")]
public Fsr2.QualityMode qualityMode = Fsr2.QualityMode.Quality;
private Vector2Int _maxRenderSize;
private Vector2Int _displaySize;
private Camera _renderCamera;
private DepthTextureMode _originalDepthTextureMode;
private Rect _originalRect;
private void OnEnable()
{
// Set up the original camera to output all of the required FSR2 input resources at the desired resolution
_renderCamera = GetComponent<Camera>();
_originalDepthTextureMode = _renderCamera.depthTextureMode;
_renderCamera.depthTextureMode = _originalDepthTextureMode | DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
}
private void OnDisable()
{
// Restore the camera's original state
_renderCamera.depthTextureMode = _originalDepthTextureMode;
}
private void LateUpdate()
{
// Determine the desired rendering and display resolutions
_displaySize = GetDisplaySize();
Fsr2.GetRenderResolutionFromQualityMode(out var maxRenderWidth, out var maxRenderHeight, _displaySize.x, _displaySize.y, qualityMode);
_maxRenderSize = new Vector2Int(maxRenderWidth, maxRenderHeight);
if (_maxRenderSize.x == 0 || _maxRenderSize.y == 0)
{
Debug.LogError($"FSR2 render size is invalid: {_maxRenderSize.x}x{_maxRenderSize.y}. Please check your screen resolution and camera viewport parameters.");
enabled = false;
}
// Remember the original camera viewport before we modify it in OnPreCull
_originalRect = _renderCamera.rect;
}
private void OnPreCull()
{
// Render to a smaller portion of the screen by manipulating the camera's viewport rect
_renderCamera.aspect = (_displaySize.x * _originalRect.width) / (_displaySize.y * _originalRect.height);
_renderCamera.rect = new Rect(0, 0, _originalRect.width * _maxRenderSize.x / _renderCamera.pixelWidth, _originalRect.height * _maxRenderSize.y / _renderCamera.pixelHeight);
ApplyJitter();
}
private void ApplyJitter()
{
var scaledRenderSize = GetScaledRenderSize();
// Perform custom jittering of the camera's projection matrix according to FSR2's recipe
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(scaledRenderSize.x, _displaySize.x);
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
jitterX = 2.0f * jitterX / scaledRenderSize.x;
jitterY = 2.0f * jitterY / scaledRenderSize.y;
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
_renderCamera.nonJitteredProjectionMatrix = _renderCamera.projectionMatrix;
_renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix;
_renderCamera.useJitteredProjectionMatrixForTransparentRendering = true;
}
private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
// Restore the camera's viewport rect so we can output at full resolution
_renderCamera.rect = _originalRect;
_renderCamera.ResetProjectionMatrix();
Graphics.Blit(src, dest);
}
private Vector2Int GetDisplaySize()
{
var targetTexture = _renderCamera.targetTexture;
if (targetTexture != null)
return new Vector2Int(targetTexture.width, targetTexture.height);
return new Vector2Int(_renderCamera.pixelWidth, _renderCamera.pixelHeight);
}
private bool UsingDynamicResolution()
{
var targetTexture = _renderCamera.targetTexture;
return _renderCamera.allowDynamicResolution || (targetTexture != null && targetTexture.useDynamicScale);
}
private Vector2Int GetScaledRenderSize()
{
if (UsingDynamicResolution())
return new Vector2Int(Mathf.CeilToInt(_maxRenderSize.x * ScalableBufferManager.widthScaleFactor), Mathf.CeilToInt(_maxRenderSize.y * ScalableBufferManager.heightScaleFactor));
return _maxRenderSize;
}
}
}