很多時候需要把相機得texture渲染到texture上。但是效果往往不理想。
如圖對比:
沒有處理過得效果 處理過得效果
還是比較明顯得變化得。
那么如何處理呢?下面介紹四種方式
方式一
具體原理不多啰嗦,直接講步驟。
首先創建一個腳本Antialiasing.cs
using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; 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 RawImage StoreRenderTexture; 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; // Shader a= new Shader(); 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; StoreRenderTexture.texture = Antialiasing.RenderTexture; } 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(); } }
然后,將腳本掛載到相機上。
將你要展示得RawImage拽到腳本中得RawImage處。
大功告成!
方式二
當然你想要獲得更好得效果還可以這樣做。
1、打開菜單欄Edit中Project Settings中的Quality選項
2、在QualitySettings中可以找到Shadows設置
3、開始各種調整,直到自己滿意
4、Shadow Distance值如果很大就會邊緣鋸齒,Resolution也有影響
方式三
也可以這樣做,通過官方得抗鋸齒濾鏡插件。
這里推薦Beautify,可以加很多得相機效果,同時在鋸齒處理也是相當完美。官網35刀。不過CSDN或者隨便哪個論壇都可以下載。這個錢能省則省,實在需要聯系我,哈哈哈請問吃頓飯就好。開玩笑拉自己去下載
方式四
當然這里也有通過Super Sampling Anti-Aliasing來進行抗鋸齒處理,跟前面得也是差不多。這里貼出Shader代碼
Shader "Custom/SSAA1" { Properties{ _MainTex("MainTex", 2D) = "white" {} _Size("Size", range(1, 2048)) = 512 } SubShader{ pass{ Tags{ "LightMode" = "ForwardBase" } Cull off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float _Size; sampler2D _MainTex; float4 _MainTex_ST; struct v2f { float4 pos : SV_POSITION; float2 uv_MainTex : TEXCOORD0; }; v2f vert(appdata_full v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } float4 frag(v2f i) :COLOR { /* *this part is about edge detection algorithms used Sobel operator */ float3 lum = float3(0.2125, 0.7154, 0.0721); float mc00 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(1, 1) / _Size).rgb, lum); float mc10 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(0, 1) / _Size).rgb, lum); float mc20 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(-1, 1) / _Size).rgb, lum); float mc01 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(1, 0) / _Size).rgb, lum); float mc11mc = dot(tex2D(_MainTex, i.uv_MainTex).rgb, lum); float mc21 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(-1, 0) / _Size).rgb, lum); float mc02 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(1, -1) / _Size).rgb, lum); float mc12 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(0, -1) / _Size).rgb, lum); float mc22 = dot(tex2D(_MainTex, i.uv_MainTex - fixed2(-1, -1) / _Size).rgb, lum); float GX = -1 * mc00 + mc20 + -2 * mc01 + 2 * mc21 - mc02 + mc22; float GY = mc00 + 2 * mc10 + mc20 - mc02 - 2 * mc12 - mc22; float G = abs(GX) + abs(GY); float4 c = 0; c = length(float2(GX, GY)); /* *this part is about blur edge */ float4 cc = tex2D(_MainTex, i.uv_MainTex); if (c.x < 0.2) { return cc; } else { float2 n = float2(GX, GY); n *= 1 / _Size / c.x; //roated float4 c0 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.2 / 2, 0.8) / _Size); float4 c1 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.8 / 2, -0.2) / _Size); float4 c2 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.2 / 2, -0.8) / _Size); float4 c3 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.8 / 2, 0.2) / _Size); //random float2 randUV = 0; randUV = rand(float2(n.x, n.y)); float4 c0 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size); randUV = rand(float2(-n.x, n.y)); float4 c1 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size); randUV = rand(float2(n.x, -n.y)); float4 c2 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size); randUV = rand(float2(-n.x, -n.y)); float4 c3 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size); //Gird float4 c0 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.5, 1) / _Size); float4 c1 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.5, 1) / _Size); float4 c2 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.5, -1) / _Size); float4 c3 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.5, -1) / _Size); cc = (cc + c0 + c1 + c2 + c3) *0.2; return cc; } } ENDCG } } }
關於SSAA得抗鋸齒處理原理比較簡單就是;查找邊緣然會進行模糊化處理。這樣鋸齒就能減弱,幾乎沒有啥感覺!
推薦博文:https://blog.csdn.net/wolf96/article/details/45438653
NVIDIA資料(自行翻譯了解):https://docs.nvidia.com/gameworks/index.html#gameworkslibrary/graphicssamples/d3d_samples/antialiaseddeferredrendering.htm