什么是 SSAA
超级采样抗锯齿(Super-Sampling Anti-aliasing,简称SSAA)此是早期抗锯齿方法,比较消耗资源,但简单直接,先把图像映射到缓存并把它放大,再用超级采样把放大后的图像像素进行采样,一般选取2个或4个邻近像素,把这些采样混合起来后,生成的最终像素,令每个像素拥有邻近像素的特征,像素与像素之间的过渡色彩,就变得近似,令图形的边缘色彩过渡趋于平滑。再把最终像素还原回原来大小的图像,并保存到帧缓存也就是显存中,替代原图像存储起来,最后输出到显示器,显示出一帧画面。
C# 实现
将下面的脚本绑定到需要进行 SSAA 的摄像机上即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
| using System; using System.Collections.Generic; using UnityEngine;
public class Antialiasing : MonoBehaviour { private static GameObject renderTargetCam; private static TextureRenderer textureRenderer; private static RenderTexture renderTexture; public static float scale = 2; private Camera mainCam; private int screenX; private int screenY; private int targetX = 100; private int targetY = 100; private int hideFlagDontShowSave = 61; public bool restart; private bool rendering; public static RenderTextureFormat Format = RenderTextureFormat.ARGB32; public static GameObject RenderTargetCamera { get { return Antialiasing.renderTargetCam; } } public static RenderTexture RenderTexture { get { return Antialiasing.renderTexture; } } public Camera RenderingCamera { get { return this.mainCam; } } private void OnEnable() { this.mainCam = base.GetComponent<Camera>(); if (this.mainCam == null) { Debug.LogError("Missing Camera on GameObject!"); base.enabled = false; return; } this.hideFlagDontShowSave = 13; this.targetX = Screen.width; this.targetY = Screen.height; if (Application.isEditor) { this.restart = true; return; } this.StartAntialiasing(); } private void OnDisable() { this.StopAntialiasing(); } private void Update() { if (this.screenX != Screen.width || this.screenY != Screen.height) { this.restart = true; } if (this.restart) { this.Restart(); } } private void Restart() { this.StopAntialiasing(); this.StartAntialiasing(); this.restart = false; } private void OnPreCull() { if (this.rendering && (this.screenX != Screen.width || this.screenY != Screen.height)) { this.targetX = Screen.width; this.targetY = Screen.height; this.restart = true; } if (this.rendering) { this.mainCam.targetTexture = Antialiasing.renderTexture; } } private void FinishedRendering() { if (this.rendering) { this.mainCam.targetTexture = null; } } public void StartAntialiasing() { if (this.mainCam == null) { Debug.LogError("Missing Camera on Object!"); return; } this.screenX = Screen.width; this.screenY = Screen.height; int num = (int)((float)Screen.width * Antialiasing.scale); int num2 = (int)((float)Screen.height * Antialiasing.scale); if (num <= 0) { num = 100; } if (num2 <= 0) { num2 = 100; } if (Antialiasing.renderTexture == null || Antialiasing.renderTexture.width != num || Antialiasing.renderTexture.height != num2) { if (Antialiasing.renderTexture != null) { Antialiasing.renderTexture.Release(); } Antialiasing.renderTexture = new RenderTexture(num, num2, 2, Antialiasing.Format); Antialiasing.renderTexture.name = "SSAARenderTarget"; Antialiasing.renderTexture.hideFlags = (HideFlags)this.hideFlagDontShowSave; } if (Antialiasing.renderTargetCam == null) { Antialiasing.renderTargetCam = new GameObject("SSAARenderTargetCamera"); Antialiasing.renderTargetCam.hideFlags = (HideFlags)this.hideFlagDontShowSave;
Camera c = Antialiasing.renderTargetCam.AddComponent<Camera>();
c.CopyFrom(this.mainCam); c.cullingMask = 0; c.targetTexture = null; c.depth = this.mainCam.depth + 0.5f; Antialiasing.textureRenderer = Antialiasing.renderTargetCam.AddComponent<TextureRenderer>(); Antialiasing.textureRenderer.hideFlags = (HideFlags)this.hideFlagDontShowSave; } this.rendering = true; } public void StopAntialiasing() { if (this.mainCam != null && this.mainCam.targetTexture != null) { this.mainCam.targetTexture = null; } if (renderTargetCam != null) { GameObject.Destroy(renderTargetCam); } this.rendering = false; } } public class TextureRenderer : MonoBehaviour { private Camera c; public bool stereoFirstPass = true; private void Awake() { this.c = gameObject.GetComponent<Camera>(); if (this.c == null) { Debug.LogError("TextureRenderer init fail! (no Camera)"); base.enabled = false; } } private void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit(Antialiasing.RenderTexture, destination); Antialiasing.RenderTexture.DiscardContents(); } }
|