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.
146 lines
6.5 KiB
146 lines
6.5 KiB
using System.Collections;
|
|
using FidelityFX;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
[RequireComponent(typeof(Camera))]
|
|
public class SubsampleTest : MonoBehaviour // TODO: rename this to Fsr2Controller
|
|
{
|
|
[SerializeField]
|
|
private Fsr2.QualityMode qualityMode;
|
|
|
|
private Camera _renderCamera;
|
|
private RenderTexture _originalRenderTarget;
|
|
|
|
private GameObject _displayCameraObject;
|
|
private Camera _displayCamera;
|
|
|
|
private Fsr2Controller _fsr2Controller;
|
|
|
|
private Fsr2.QualityMode _prevQualityMode;
|
|
private Vector2Int _prevScreenSize;
|
|
|
|
private CommandBuffer _opaqueOnlyCommandBuffer;
|
|
private CommandBuffer _inputsCommandBuffer;
|
|
|
|
private void OnEnable()
|
|
{
|
|
_renderCamera = GetComponent<Camera>();
|
|
if (_displayCameraObject == null)
|
|
{
|
|
_displayCameraObject = new GameObject("FSR2 Camera Object");
|
|
_displayCameraObject.transform.SetParent(transform);
|
|
_displayCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
|
|
//outputCameraObject.transform.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
|
|
|
|
// Create a camera that does nothing except output the upscaled image
|
|
_displayCamera = _displayCameraObject.AddComponent<Camera>();
|
|
_displayCamera.backgroundColor = Color.clear;
|
|
_displayCamera.clearFlags = CameraClearFlags.Nothing;
|
|
_displayCamera.eventMask = 0;
|
|
_displayCamera.cullingMask = 0;
|
|
_displayCamera.useOcclusionCulling = false;
|
|
_displayCamera.orthographic = true;
|
|
_displayCamera.allowMSAA = false;
|
|
_displayCamera.renderingPath = RenderingPath.Forward;
|
|
|
|
_fsr2Controller = _displayCameraObject.AddComponent<Fsr2Controller>();
|
|
}
|
|
|
|
_fsr2Controller.renderCamera = _renderCamera;
|
|
_fsr2Controller.renderScale = 1.0f / Fsr2.GetUpscaleRatioFromQualityMode(qualityMode);
|
|
_fsr2Controller.enabled = true;
|
|
|
|
Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
|
|
|
|
_originalRenderTarget = _renderCamera.targetTexture; // TODO: if this isn't null, could maybe reuse this for the output texture?
|
|
|
|
_renderCamera.targetTexture = new RenderTexture(
|
|
renderWidth, renderHeight,
|
|
_originalRenderTarget != null ? _originalRenderTarget.depth : 32,
|
|
_originalRenderTarget != null ? _originalRenderTarget.format : RenderTextureFormat.ARGBHalf) { name = "FSR2 Input Texture" };
|
|
|
|
_renderCamera.targetTexture.Create();
|
|
|
|
_renderCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
|
|
|
|
_opaqueOnlyCommandBuffer = new CommandBuffer { name = "FSR2 Opaque Input" };
|
|
// TODO: may need to copy the opaque-only render buffer to a temp RT here, in which case we'll need an additional CommandBuffer to release the temp RT again
|
|
_opaqueOnlyCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvOpaqueOnly, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
|
|
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
|
|
|
|
_inputsCommandBuffer = new CommandBuffer { name = "FSR2 Inputs" };
|
|
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputColor, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
|
|
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputDepth, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Depth);
|
|
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputMotionVectors, BuiltinRenderTextureType.MotionVectors);
|
|
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
|
|
|
|
// Adjust texture mipmap LOD bias by log2(renderResolution/displayResolution) - 1.0;
|
|
// May need to leave this to the game dev, as we don't know which textures do and don't belong to the 3D scene
|
|
float biasOffset = Fsr2.GetMipmapBiasOffset(renderWidth, Screen.width);
|
|
Fsr2.GlobalCallbacks.ApplyMipmapBias(biasOffset);
|
|
|
|
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
|
|
_prevQualityMode = qualityMode;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
float biasOffset = Fsr2.GetMipmapBiasOffset(_renderCamera.targetTexture.width, _prevScreenSize.x);
|
|
Fsr2.GlobalCallbacks.ApplyMipmapBias(-biasOffset);
|
|
|
|
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
|
|
_opaqueOnlyCommandBuffer.Release();
|
|
_opaqueOnlyCommandBuffer = null;
|
|
|
|
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
|
|
_inputsCommandBuffer.Release();
|
|
_inputsCommandBuffer = null;
|
|
|
|
_renderCamera.targetTexture.Release();
|
|
_renderCamera.targetTexture = _originalRenderTarget;
|
|
|
|
_fsr2Controller.enabled = false;
|
|
_displayCamera.enabled = false;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
_displayCamera.enabled = _renderCamera.enabled;
|
|
|
|
if (Screen.width != _prevScreenSize.x || Screen.height != _prevScreenSize.y || qualityMode != _prevQualityMode)
|
|
{
|
|
// Force all resources to be destroyed and recreated with the new settings
|
|
OnDisable();
|
|
OnEnable();
|
|
}
|
|
}
|
|
|
|
private Rect _tempRect;
|
|
|
|
private void OnPreRender()
|
|
{
|
|
_tempRect = _renderCamera.rect;
|
|
_renderCamera.aspect = (Screen.width * _tempRect.width) / (Screen.height * _tempRect.height);
|
|
_renderCamera.rect = new Rect(0, 0, 1, 1);
|
|
|
|
// Perform custom jittering of the camera's projection matrix according to FSR2's instructions
|
|
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(_renderCamera.targetTexture.width, Screen.width);
|
|
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
|
|
|
|
_fsr2Controller.SetJitterOffset(new Vector2(jitterX, jitterY));
|
|
|
|
var targetTexture = _renderCamera.targetTexture;
|
|
jitterX = 2.0f * jitterX / targetTexture.width;
|
|
jitterY = 2.0f * jitterY / targetTexture.height;
|
|
|
|
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
|
|
_renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix;
|
|
}
|
|
|
|
private void OnPostRender()
|
|
{
|
|
_renderCamera.rect = _tempRect;
|
|
_renderCamera.ResetProjectionMatrix();
|
|
}
|
|
}
|