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.
216 lines
7.8 KiB
216 lines
7.8 KiB
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); |
|
|
|
m_HistoryTexture = null; |
|
m_SampleIndex = 0; |
|
ResetHistory(); |
|
} |
|
} |
|
}
|
|
|