//LIVENDA CTAA - CINEMATIC TEMPORAL ANTI ALIASING //Copyright Livenda Labs 2016 //pc-v2.5 using UnityEngine; using System.Collections; [RequireComponent (typeof(Camera))] [AddComponentMenu("Image Effects/LIVENDA/CTAA_PC")] public class CTAA_PC : MonoBehaviour { //-------------------------------------------------------------- [Space(5)] public bool CTAA_Enabled = true; [Header("CTAA Settings")] [Range(3, 20)] public int TemporalStability = 5; [Space(5)] [Range(0.0f, 1.0f)] public float AdaptiveEnhance = 0.5f; [Space(5)] [Range(0.4f, 1.4f)] public float TemporalJitterScale = 1.0f; //-------------------------------------------------------------- private bool PreEnhanceEnabled = true; private float preEnhanceStrength = 1.0f; private float preEnhanceClamp = 0.005f; private float AdaptiveResolve = 3000.0f; private float jitterScale = 1.0f; private float LumaContrastFactor = 1.0f; private Material ctaaMat; private Material mat_enhance; private RenderTexture rtAccum0; private RenderTexture rtAccum1; private RenderTexture txaaOut; private RenderTexture afterPreEnhace; private bool firstFrame; private bool swap; private int frameCounter; private float[] x_jit = new float[] { 0.5f, 0.25f, 0.75f, 0.125f, 0.625f, 0.375f, 0.875f, 0.0625f }; private float[] y_jit = new float[] { 0.3333333f, 0.6666667f, 0.1111111f, 0.4444444f, 0.7777778f, 0.2222222f, 0.5555556f, 0.8888889f }; void SetCTAA_Parameters() { //Temporal Enhancement PreEnhanceEnabled = AdaptiveEnhance > 0.01 ? true : false; preEnhanceStrength = Mathf.Lerp (0.2f, 2.0f, AdaptiveEnhance); preEnhanceClamp = Mathf.Lerp (0.005f, 0.012f, AdaptiveEnhance); jitterScale = TemporalJitterScale; AdaptiveResolve = 3000.0f; } private static Material CreateMaterial(string shadername) { if (string.IsNullOrEmpty(shadername)) { return null; } Material material = new Material(Shader.Find(shadername)); material.hideFlags = HideFlags.HideAndDontSave; return material; } private static void DestroyMaterial(Material mat) { if (mat != null) { Object.DestroyImmediate(mat); mat = null; } } void Awake () { if (ctaaMat == null) ctaaMat = CreateMaterial("Hidden/CTAA_PC"); if (mat_enhance == null) mat_enhance = CreateMaterial("Hidden/CTAA_Enhance_PC"); firstFrame = true; swap = true; frameCounter = 0; SetCTAA_Parameters (); } void OnEnable () { Camera mcam = GetComponent (); mcam.depthTextureMode |= DepthTextureMode.Depth; mcam.depthTextureMode |= DepthTextureMode.MotionVectors; } private void OnDisable() { DestroyMaterial(ctaaMat); DestroyMaterial(mat_enhance); DestroyImmediate(rtAccum0); rtAccum0 = null; DestroyImmediate(rtAccum1); rtAccum1 = null; DestroyImmediate(txaaOut); txaaOut = null; DestroyImmediate(afterPreEnhace); afterPreEnhace = null; } void OnPreCull() { jitterCam (); } void jitterCam() { base.GetComponent().nonJitteredProjectionMatrix = base.GetComponent().projectionMatrix; base.GetComponent().ResetProjectionMatrix(); Matrix4x4 matrixx = base.GetComponent().projectionMatrix; float num = this.x_jit[this.frameCounter]*jitterScale; float num2 = this.y_jit[this.frameCounter]*jitterScale; matrixx.m02 += ((num * 2f) - 1f) / base.GetComponent().pixelRect.width; matrixx.m12 += ((num2 * 2f) - 1f) / base.GetComponent().pixelRect.height; this.frameCounter++; this.frameCounter = this.frameCounter % 8; base.GetComponent().projectionMatrix = matrixx; } //[ImageEffectOpaque] void OnRenderImage (RenderTexture source, RenderTexture destination) { if (CTAA_Enabled) { SetCTAA_Parameters (); } else { jitterScale = 0; } //-------------------------------------------------------------------------------------------------- if (((rtAccum0 == null) || (rtAccum0.width != source.width)) || (rtAccum0.height != source.height)) { DestroyImmediate(rtAccum0); rtAccum0 = new RenderTexture(source.width, source.height, 0, source.format); rtAccum0.hideFlags = HideFlags.HideAndDontSave; rtAccum0.filterMode = FilterMode.Bilinear; rtAccum0.wrapMode = TextureWrapMode.Clamp; } if (((rtAccum1 == null) || (rtAccum1.width != source.width)) || (rtAccum1.height != source.height)) { DestroyImmediate(rtAccum1); rtAccum1 = new RenderTexture(source.width, source.height, 0, source.format); rtAccum1.hideFlags = HideFlags.HideAndDontSave; rtAccum1.filterMode = FilterMode.Bilinear; rtAccum1.wrapMode = TextureWrapMode.Clamp; } if (((txaaOut == null) || (txaaOut.width != source.width)) || (txaaOut.height != source.height)) { DestroyImmediate(txaaOut); txaaOut = new RenderTexture(source.width, source.height, 0, source.format); txaaOut.hideFlags = HideFlags.HideAndDontSave; txaaOut.filterMode = FilterMode.Bilinear; txaaOut.wrapMode = TextureWrapMode.Clamp; } if (((afterPreEnhace == null) || (afterPreEnhace.width != source.width)) || (afterPreEnhace.height != source.height)) { DestroyImmediate(afterPreEnhace); afterPreEnhace = new RenderTexture(source.width, source.height, 0, source.format); afterPreEnhace.hideFlags = HideFlags.HideAndDontSave; afterPreEnhace.filterMode = source.filterMode; afterPreEnhace.wrapMode = TextureWrapMode.Clamp; } //----------------------------------------------------------- if(PreEnhanceEnabled) { mat_enhance.SetFloat("_AEXCTAA", 1.0f / (float)Screen.width); mat_enhance.SetFloat("_AEYCTAA", 1.0f / (float)Screen.height); mat_enhance.SetFloat("_AESCTAA", preEnhanceStrength); mat_enhance.SetFloat("_AEMAXCTAA", preEnhanceClamp); Graphics.Blit(source, afterPreEnhace, mat_enhance, 1); } else { Graphics.Blit(source, afterPreEnhace); } if (CTAA_Enabled) { if (firstFrame) { Graphics.Blit (afterPreEnhace, rtAccum0); firstFrame = false; } ctaaMat.SetFloat ("_AdaptiveResolve", AdaptiveResolve); ctaaMat.SetVector ("_ControlParams", new Vector4 (0, (float)TemporalStability, LumaContrastFactor, 0)); if (swap) { ctaaMat.SetTexture ("_Accum", rtAccum0); Graphics.Blit (afterPreEnhace, rtAccum1, ctaaMat); Graphics.Blit (rtAccum1, txaaOut); } else { ctaaMat.SetTexture ("_Accum", rtAccum1); Graphics.Blit (afterPreEnhace, rtAccum0, ctaaMat); Graphics.Blit (rtAccum0, txaaOut); } Graphics.Blit (txaaOut, destination); } else {//End Of CTAA Enabled Graphics.Blit(afterPreEnhace, destination); } swap = !swap; } }