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.
164 lines
6.1 KiB
164 lines
6.1 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using FidelityFX;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Rendering;
|
|
|
|
/// <summary>
|
|
/// This class is responsible for hooking into various Unity events and translating them to the FSR2 subsystem.
|
|
/// This includes creation and destruction of the FSR2 context, as well as dispatching commands at the right time.
|
|
/// This class also exposes various FSR2 parameters to the Unity inspector.
|
|
/// </summary>
|
|
public class Fsr2Controller : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private bool performSharpenPass = true;
|
|
|
|
[SerializeField, Range(0, 1)]
|
|
private float sharpness = 0.8f;
|
|
|
|
[SerializeField]
|
|
private bool reset;
|
|
|
|
[HideInInspector]
|
|
public Camera gameCamera;
|
|
|
|
[HideInInspector]
|
|
public Camera outputCamera;
|
|
|
|
[HideInInspector]
|
|
public float renderScale;
|
|
|
|
private bool _started;
|
|
|
|
private Vector2Int DisplaySize => new Vector2Int(Screen.width, Screen.height);
|
|
private Vector2Int RenderSize => new Vector2Int(Mathf.FloorToInt(Screen.width * renderScale), Mathf.FloorToInt(Screen.height * renderScale));
|
|
|
|
private Fsr2Context _context;
|
|
private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription();
|
|
|
|
private RenderTexture _upscaledOutput;
|
|
|
|
private Material _copyMotionMat;
|
|
private Material CopyMotionVectorsMaterial
|
|
{
|
|
get
|
|
{
|
|
if (_copyMotionMat == null)
|
|
{
|
|
var copyMotionShader = Fsr2.GlobalCallbacks.LoadShader("Shaders/FSR2_CopyMotionVectors");
|
|
_copyMotionMat = new Material(copyMotionShader);
|
|
}
|
|
|
|
return _copyMotionMat;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_started = true;
|
|
OnEnable();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
// Delay OnEnable until we're sure all fields and properties are set
|
|
if (!_started)
|
|
return;
|
|
|
|
_context = Fsr2.CreateContext(DisplaySize, RenderSize, Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation);
|
|
|
|
// TODO: do we need a depth buffer for the output? We will need depth & motion vectors for subsequent post-FX. How should FSR2 output these?
|
|
// TODO: can probably be a temporary RT
|
|
_upscaledOutput = new RenderTexture(DisplaySize.x, DisplaySize.y, 0, RenderTextureFormat.ARGBHalf) { name = "FSR2 Upscaled Output", enableRandomWrite = true };
|
|
_upscaledOutput.Create();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (_upscaledOutput != null)
|
|
{
|
|
_upscaledOutput.Release();
|
|
_upscaledOutput = null;
|
|
}
|
|
|
|
if (_context != null)
|
|
{
|
|
_context.Destroy();
|
|
_context = null;
|
|
}
|
|
}
|
|
|
|
public void SetJitterOffset(Vector2 jitterOffset)
|
|
{
|
|
_dispatchDescription.JitterOffset = jitterOffset;
|
|
}
|
|
|
|
// For legacy built-in render pipeline
|
|
private void OnRenderImage(RenderTexture src, RenderTexture dest)
|
|
{
|
|
var renderBuffer = gameCamera.targetTexture;
|
|
|
|
var commandBuffer = new CommandBuffer { name = "FSR2" };
|
|
|
|
int motionVectorsId = Shader.PropertyToID("r_input_motion_vectors");
|
|
int upscaledOutputId = Shader.PropertyToID("rw_upscaled_output");
|
|
|
|
// I hate having to allocate extra RTs just to duplicate already existing Unity render buffers, but AFAIK there is no way to directly address motion vectors from code
|
|
// TODO: or can we? Look at RenderTargetIdentifier.MotionVectors with SetGlobalTexture!! (Possibly in gameCamera OnRenderImage)
|
|
commandBuffer.GetTemporaryRT(motionVectorsId, renderBuffer.width, renderBuffer.height, 0, default, RenderTextureFormat.RGHalf);
|
|
commandBuffer.Blit(renderBuffer, motionVectorsId, CopyMotionVectorsMaterial);
|
|
|
|
if (dest != null)
|
|
{
|
|
// We have more image effects lined up after this, so FSR2 can output straight to the intermediate render texture
|
|
// TODO: we should probably use a shader to include depth & motion vectors into the output
|
|
commandBuffer.SetGlobalTexture(upscaledOutputId, dest);
|
|
}
|
|
else
|
|
{
|
|
// We are rendering to the backbuffer, so we need a temporary render texture for FSR2 to output to
|
|
commandBuffer.GetTemporaryRT(upscaledOutputId, DisplaySize.x, DisplaySize.y, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true);
|
|
}
|
|
|
|
_dispatchDescription.ColorDepth = renderBuffer;
|
|
_dispatchDescription.MotionVectors = null;
|
|
_dispatchDescription.Output = null;
|
|
_dispatchDescription.Exposure = null;
|
|
_dispatchDescription.Reactive = null;
|
|
_dispatchDescription.PreExposure = 0;
|
|
_dispatchDescription.EnableSharpening = performSharpenPass;
|
|
_dispatchDescription.Sharpness = sharpness;
|
|
_dispatchDescription.MotionVectorScale.x = -gameCamera.pixelWidth;
|
|
_dispatchDescription.MotionVectorScale.y = -gameCamera.pixelHeight;
|
|
_dispatchDescription.RenderSize = RenderSize;
|
|
_dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime;
|
|
_dispatchDescription.CameraNear = gameCamera.nearClipPlane;
|
|
_dispatchDescription.CameraFar = gameCamera.farClipPlane;
|
|
_dispatchDescription.CameraFovAngleVertical = gameCamera.fieldOfView * Mathf.Deg2Rad;
|
|
_dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
|
|
_dispatchDescription.Reset = reset;
|
|
reset = false;
|
|
|
|
_context.Dispatch(_dispatchDescription, commandBuffer);
|
|
|
|
// Output upscaled image to screen
|
|
// TODO: if `dest` is null, we likely don't care about the depth & motion vectors anymore
|
|
if (dest == null)
|
|
{
|
|
commandBuffer.Blit(upscaledOutputId, dest);
|
|
commandBuffer.ReleaseTemporaryRT(upscaledOutputId);
|
|
}
|
|
|
|
commandBuffer.ReleaseTemporaryRT(motionVectorsId);
|
|
|
|
Graphics.ExecuteCommandBuffer(commandBuffer);
|
|
commandBuffer.Release();
|
|
|
|
// Shut up the Unity warning about not writing to the destination texture
|
|
Graphics.SetRenderTarget(dest);
|
|
}
|
|
}
|