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