zoukankan      html  css  js  c++  java
  • Unity3d 超级采样抗锯齿 Super Sampling Anti-Aliasing

    Super Sampling Anti-Aliasing
    SSAA算是在众多抗锯齿算法中比较昂贵的一种了,年代也比较久远,但是方法比较简单,
    主要概括为两步
    1.    查找边缘
    2.    模糊边缘
    这是一种post processing的处理方法,
    接下来我们就看看怎么实现

    查找边缘

    查找边缘的原因也是因为减少消耗,这样就可以只在边缘处进行超级采样,不必为全图进行采样了。
    之前的文章详细说过三种查找边缘的方法Roberts,Sobel,Canny ,其中sobel最优,所以我们就是用sobel查找边缘
    这里简单讲解一下,查找边缘的不同在于过滤器的不同,但都是水平垂直采样
    Sobel算子的两个过滤器分别算出横向与纵向的灰度
     
    GX为水平过滤器,GY为垂直过滤器,垂直过滤器就是水平过滤器旋转90度。
    过滤器为3x3的矩阵,将与图像作平面卷积。
    如果不存在边则两个点颜色很接近,过滤器返回一个较小的值,否则就可判断出边缘的存在。
    找出边缘之后就可以模糊边缘了

    模糊边缘

    模糊边缘就是要进行超级采样了,采取周围的像素点再进行混色

    大家经常看到比如说SSAAx2,SSAAx4,x8….后面的数目就是采样点的个数。

    之前翻译了一篇wiki上的超级采样

    模糊边缘的方式(采样方式)有很多种,比较流行的几种有
    网格采样,随机采样,poisson disc采样,Jitter算法采样,旋转网格采样
     

    部分方法的采样范围,我设定为他们边缘的灰度了,也就是边缘检测中的G,因为G越大边缘越深,出现锯齿越明显,就要加大采样范围。

    我们试试网格,随机,与旋转采样

    网格采样比较简单,但是因为太规则了,模糊的效果可能不够好,
    显获取周围的点,然后进行混色

    		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);




    然后就是随机,个人认为随机的效果不太好,因为像是边缘被噪波了一样,有像素点扩散的痕迹

    				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);




    然后就是旋转网格采样,最佳的旋转角度是arctan (1/2) (大约 26.6°),这里偷个懒,也省去了旋转计算的消耗,大概个位置进行采样,效果还算好。

    		<span style="font-size:14px;">		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);</span>

    结果比较

    性能

    性能方面SSAA比其他AA弱了一些,主要因为方法是这样暴力的采样

    SSAA采样方式间的损耗都差不多

    都是SSAAx4

    无抗锯齿


    网格采样


    随机采样

    旋转采样

     

    在unity中image effect的SSAA消耗与本文差不多

    又看了一下其他的unity的抗锯齿方法,发现FXAA消耗是最少的在2.8ms左右

    全部代码已共享至GitHub

                                 ----- by wolf96

  • 相关阅读:
    mac 安装Windows系统
    各种镜像源
    应用官方下载地址汇总
    centos7 升级openssh
    ubuntu16.04升级openssh
    腾讯云
    msdeploy 远程发布到lls
    Java Script 什么是闭包?
    JavaScript我的怀疑
    HTML 之 js是干什么的
  • 原文地址:https://www.cnblogs.com/zhanlang96/p/4471769.html
Copyright © 2011-2022 走看看