| | |
| | | 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 != null && 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(); |
| | | } |
| | | } |
| | | } |
| | | 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 != null && 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();
|
| | | }
|
| | | }
|
| | | }
|