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.
 
 
 
 

156 lines
5.3 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class SubsampleTest : MonoBehaviour
{
private Camera gameCamera;
private GameObject outputCameraObject;
private Camera outputCamera;
[SerializeField]
private float renderScale = 0.5f;
[SerializeField]
private bool enableJitter;
private FSR2Thing fsr2Thing;
private void OnEnable()
{
gameCamera = GetComponent<Camera>();
if (outputCameraObject == null)
{
outputCameraObject = new GameObject("FSR2 Camera Object");
outputCameraObject.transform.SetParent(transform);
outputCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
//outputCameraObject.transform.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
outputCamera = outputCameraObject.AddComponent<Camera>();
outputCamera.eventMask = 0;
fsr2Thing = outputCameraObject.AddComponent<FSR2Thing>();
fsr2Thing.gameCamera = gameCamera;
fsr2Thing.outputCamera = outputCamera;
fsr2Thing.renderScale = renderScale;
fsr2Thing.enabled = true;
//outputCamera.CopyFrom(gameCamera);
outputCamera.cullingMask = 0;
outputCamera.clearFlags = CameraClearFlags.Nothing;
}
else
{
fsr2Thing.enabled = true;
}
gameCamera.targetTexture = new RenderTexture(
(int)(Screen.width * renderScale), (int)(Screen.height * renderScale),
24, // Can we copy depth value from original camera?
RenderTextureFormat.ARGBHalf); // Can we copy format from original camera? Or renderer quality settings?
gameCamera.depthTextureMode = DepthTextureMode.Depth | DepthTextureMode.DepthNormals | DepthTextureMode.MotionVectors;
gameCamera.targetTexture.name = "FSR2 Source Texture";
gameCamera.targetTexture.Create();
// 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
// TODO: add to Callbacks class/interface (ApplyMipmapBias)
float biasOffset = GetMipmapBiasOffset();
foreach (var tex in Resources.FindObjectsOfTypeAll<Texture2D>())
{
tex.mipMapBias += biasOffset;
}
}
private void OnDisable()
{
float biasOffset = GetMipmapBiasOffset();
foreach (var tex in Resources.FindObjectsOfTypeAll<Texture2D>())
{
tex.mipMapBias -= biasOffset;
}
gameCamera.targetTexture.Release();
gameCamera.targetTexture = null;
fsr2Thing.enabled = false;
outputCamera.enabled = false;
}
public float GetMipmapBiasOffset()
{
return Mathf.Log(renderScale) - 1.0f;
}
private void Update()
{
outputCamera.enabled = gameCamera.enabled;
//outputCamera.CopyFrom(gameCamera);
outputCamera.clearFlags = CameraClearFlags.Color;
}
private Rect tempRect;
private void OnPreRender()
{
gameCamera.aspect = (Screen.width * gameCamera.rect.width) / (Screen.height * gameCamera.rect.height);
tempRect = gameCamera.rect;
gameCamera.rect = new Rect(0, 0, 1, 1);
if (enableJitter)
{
// Perform custom jittering of the camera's projection matrix according to FSR2's instructions
// Unity already does jittering behind the scenes for certain post-effects, so can we perhaps integrate with that?
int jitterPhaseCount = GetJitterPhaseCount(gameCamera.targetTexture.width, Screen.width);
GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
jitterX = 2.0f * jitterX / gameCamera.targetTexture.width;
jitterY = -2.0f * jitterY / gameCamera.targetTexture.height;
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
gameCamera.projectionMatrix = jitterTranslationMatrix * gameCamera.nonJitteredProjectionMatrix;
}
}
private void OnPostRender()
{
gameCamera.rect = tempRect;
gameCamera.ResetProjectionMatrix();
}
private static int GetJitterPhaseCount(int renderWidth, int displayWidth)
{
const float basePhaseCount = 8.0f;
int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f));
return jitterPhaseCount;
}
private static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount)
{
outX = Halton((index % phaseCount) + 1, 2) - 0.5f;
outY = Halton((index % phaseCount) + 1, 3) - 0.5f;
}
// Calculate halton number for index and base.
private static float Halton(int index, int @base)
{
float f = 1.0f, result = 0.0f;
for (int currentIndex = index; currentIndex > 0;) {
f /= @base;
result += f * (currentIndex % @base);
currentIndex = (int)Mathf.Floor((float)currentIndex / @base);
}
return result;
}
}