FiE-Game/Assets/PostProcessing/Runtime/Components/TaaComponent.cs

220 lines
7.9 KiB
C#
Raw Normal View History

2023-07-24 21:52:50 +02:00
using System;
namespace UnityEngine.PostProcessing
{
public sealed class TaaComponent : PostProcessingComponentRenderTexture<AntialiasingModel>
{
static class Uniforms
{
internal static int _Jitter = Shader.PropertyToID("_Jitter");
internal static int _SharpenParameters = Shader.PropertyToID("_SharpenParameters");
internal static int _FinalBlendParameters = Shader.PropertyToID("_FinalBlendParameters");
internal static int _HistoryTex = Shader.PropertyToID("_HistoryTex");
internal static int _MainTex = Shader.PropertyToID("_MainTex");
}
const string k_ShaderString = "Hidden/Post FX/Temporal Anti-aliasing";
const int k_SampleCount = 8;
readonly RenderBuffer[] m_MRT = new RenderBuffer[2];
int m_SampleIndex = 0;
bool m_ResetHistory = true;
RenderTexture m_HistoryTexture;
public override bool active
{
get
{
return model.enabled
&& model.settings.method == AntialiasingModel.Method.Taa
&& SystemInfo.supportsMotionVectors
&& SystemInfo.supportedRenderTargetCount >= 2
&& !context.interrupted;
}
}
public override DepthTextureMode GetCameraFlags()
{
return DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
}
public Vector2 jitterVector { get; private set; }
public void ResetHistory()
{
m_ResetHistory = true;
}
public void SetProjectionMatrix(Func<Vector2, Matrix4x4> jitteredFunc)
{
var settings = model.settings.taaSettings;
var jitter = GenerateRandomOffset();
jitter *= settings.jitterSpread;
context.camera.nonJitteredProjectionMatrix = context.camera.projectionMatrix;
if (jitteredFunc != null)
{
context.camera.projectionMatrix = jitteredFunc(jitter);
}
else
{
context.camera.projectionMatrix = context.camera.orthographic
? GetOrthographicProjectionMatrix(jitter)
: GetPerspectiveProjectionMatrix(jitter);
}
#if UNITY_5_5_OR_NEWER
context.camera.useJitteredProjectionMatrixForTransparentRendering = false;
#endif
jitter.x /= context.width;
jitter.y /= context.height;
var material = context.materialFactory.Get(k_ShaderString);
material.SetVector(Uniforms._Jitter, jitter);
jitterVector = jitter;
}
public void Render(RenderTexture source, RenderTexture destination)
{
var material = context.materialFactory.Get(k_ShaderString);
material.shaderKeywords = null;
var settings = model.settings.taaSettings;
if (m_ResetHistory || m_HistoryTexture == null || m_HistoryTexture.width != source.width || m_HistoryTexture.height != source.height)
{
if (m_HistoryTexture)
RenderTexture.ReleaseTemporary(m_HistoryTexture);
m_HistoryTexture = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
m_HistoryTexture.name = "TAA History";
Graphics.Blit(source, m_HistoryTexture, material, 2);
}
const float kMotionAmplification = 100f * 60f;
material.SetVector(Uniforms._SharpenParameters, new Vector4(settings.sharpen, 0f, 0f, 0f));
material.SetVector(Uniforms._FinalBlendParameters, new Vector4(settings.stationaryBlending, settings.motionBlending, kMotionAmplification, 0f));
material.SetTexture(Uniforms._MainTex, source);
material.SetTexture(Uniforms._HistoryTex, m_HistoryTexture);
var tempHistory = RenderTexture.GetTemporary(source.width, source.height, 0, source.format);
tempHistory.name = "TAA History";
m_MRT[0] = destination.colorBuffer;
m_MRT[1] = tempHistory.colorBuffer;
Graphics.SetRenderTarget(m_MRT, source.depthBuffer);
GraphicsUtils.Blit(material, context.camera.orthographic ? 1 : 0);
RenderTexture.ReleaseTemporary(m_HistoryTexture);
m_HistoryTexture = tempHistory;
m_ResetHistory = false;
}
float GetHaltonValue(int index, int radix)
{
float result = 0f;
float fraction = 1f / (float)radix;
while (index > 0)
{
result += (float)(index % radix) * fraction;
index /= radix;
fraction /= (float)radix;
}
return result;
}
Vector2 GenerateRandomOffset()
{
var offset = new Vector2(
GetHaltonValue(m_SampleIndex & 1023, 2),
GetHaltonValue(m_SampleIndex & 1023, 3));
if (++m_SampleIndex >= k_SampleCount)
m_SampleIndex = 0;
return offset;
}
// Adapted heavily from PlayDead's TAA code
// https://github.com/playdeadgames/temporal/blob/master/Assets/Scripts/Extensions.cs
Matrix4x4 GetPerspectiveProjectionMatrix(Vector2 offset)
{
float vertical = Mathf.Tan(0.5f * Mathf.Deg2Rad * context.camera.fieldOfView);
float horizontal = vertical * context.camera.aspect;
offset.x *= horizontal / (0.5f * context.width);
offset.y *= vertical / (0.5f * context.height);
float left = (offset.x - horizontal) * context.camera.nearClipPlane;
float right = (offset.x + horizontal) * context.camera.nearClipPlane;
float top = (offset.y + vertical) * context.camera.nearClipPlane;
float bottom = (offset.y - vertical) * context.camera.nearClipPlane;
var matrix = new Matrix4x4();
matrix[0, 0] = (2f * context.camera.nearClipPlane) / (right - left);
matrix[0, 1] = 0f;
matrix[0, 2] = (right + left) / (right - left);
matrix[0, 3] = 0f;
matrix[1, 0] = 0f;
matrix[1, 1] = (2f * context.camera.nearClipPlane) / (top - bottom);
matrix[1, 2] = (top + bottom) / (top - bottom);
matrix[1, 3] = 0f;
matrix[2, 0] = 0f;
matrix[2, 1] = 0f;
matrix[2, 2] = -(context.camera.farClipPlane + context.camera.nearClipPlane) / (context.camera.farClipPlane - context.camera.nearClipPlane);
matrix[2, 3] = -(2f * context.camera.farClipPlane * context.camera.nearClipPlane) / (context.camera.farClipPlane - context.camera.nearClipPlane);
matrix[3, 0] = 0f;
matrix[3, 1] = 0f;
matrix[3, 2] = -1f;
matrix[3, 3] = 0f;
return matrix;
}
Matrix4x4 GetOrthographicProjectionMatrix(Vector2 offset)
{
float vertical = context.camera.orthographicSize;
float horizontal = vertical * context.camera.aspect;
offset.x *= horizontal / (0.5f * context.width);
offset.y *= vertical / (0.5f * context.height);
float left = offset.x - horizontal;
float right = offset.x + horizontal;
float top = offset.y + vertical;
float bottom = offset.y - vertical;
return Matrix4x4.Ortho(left, right, bottom, top, context.camera.nearClipPlane, context.camera.farClipPlane);
}
public override void OnDisable()
{
if (m_HistoryTexture != null)
RenderTexture.ReleaseTemporary(m_HistoryTexture);
#if UNITY_5_5_OR_NEWER
context.camera.useJitteredProjectionMatrixForTransparentRendering = true;
#endif
m_HistoryTexture = null;
m_SampleIndex = 0;
ResetHistory();
}
}
}