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
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;
|
|
}
|
|
}
|
|
}
|