zoukankan      html  css  js  c++  java
  • Antialiasing 抗锯齿效果(render to texture锯齿问题处理)

    很多时候需要把相机得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

  • 相关阅读:
    BAT 大厂最流行的测试技术体系与测试职业发展晋级指南
    通知 | 2021 第一期《测试开发实战宝典》赠书活动顺利结束!
    你还缺个好工作?但7月毕业季即将来临怎么办
    一图看懂云栖大会「云原生」重磅发布
    阿里云重磅发布业务中台产品 BizWorks,中台发展进入下一个阶段
    云栖·追踪云原生|Serverless入围阿里云十大核心技术
    先行一步,7大技术创新和突破,阿里云把 Serverless 领域的这些难题都给解了
    New homework
    German
    suggestion
  • 原文地址:https://www.cnblogs.com/VR-1024/p/9895111.html
Copyright © 2011-2022 走看看