欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

UnityShader后處理中如何實現(xiàn)簡單均值模糊

這篇文章主要為大家展示了“Unity Shader后處理中如何實現(xiàn)簡單均值模糊”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“Unity Shader后處理中如何實現(xiàn)簡單均值模糊”這篇文章吧。

十余年的和靜網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。網(wǎng)絡(luò)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整和靜建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)公司從事“和靜網(wǎng)站設(shè)計”,“和靜網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。

一.簡介

后處理中比較常用的一種效果,屏幕模糊效果。模糊效果,在圖像處理中經(jīng)常用到,Photoshop中也有類似的濾鏡。我們在游戲中也會經(jīng)常用到。因為屏幕模糊效果是一些高級后處理效果的基礎(chǔ),比如景深等效果都需要用屏幕模糊效果來實現(xiàn),所以我們首先看一下屏幕模糊效果,然后通過屏幕模糊,進一步學習景深效果與運動模糊效果的實現(xiàn)。


所謂模糊,也就是不清楚,清晰的圖片,各個像素之間會有明顯的過渡,而如果各個像素之間的差距不是很大,那么圖像就會模糊了,極端一點的情況,當一張圖片所有的像素之間顏色都差不多時,那么這張圖片也就是一個純色的圖片了。模糊操作就是讓像素間的顏色差距變小,比如A點是紅色,A點周圍的點是綠色,模糊就像用一把刷子,將A點和周圍的點的顏色混合起來,變成最終的顏色。而怎樣混合,按照不同的權(quán)值進行混合,就可以達到不同的效果了。比如均值模糊,以及著名的高斯模糊。


影響模糊程度的重要因素是模糊半徑,模糊半徑越大,模糊程度越大,模糊半徑越小,模糊程度越小。那么,模糊半徑是什么?所謂模糊半徑,也就是我們采樣的一個范圍,比如我們模糊的半徑很小,只是把像素和它周圍的一圈定點混合,那么模糊的程度就很小,而如果我們加大模糊半徑,極端情況是每個頂點都取了周圍所有點,也就是整張圖的像素平均值,那么這張圖的顏色就會偏向一種顏色。

二.均值模糊

最簡單的,我們看一下簡單的模糊,直接用周圍像素求和平均,我們混合的最終圖像,在某一點的權(quán)重僅僅跟模糊半徑有關(guān)。換句話說,比如模糊半徑為1,那么,我們?nèi)∫粋€像素點,以及他周圍的一圈像素點,一共九個點,直接取平均,那么每個點的權(quán)重設(shè)置為1/9。這也就是所謂的均值模糊。我們看一下均值模糊的例子。

shader部分:

Shader "Custom/SimpleBlurEffect"   
{  
  
    Properties  
    {  
        _MainTex("Base (RGB)", 2D) = "white" {}  
    }  
  
    //通過CGINCLUDE我們可以預定義一些下面在Pass中用到的struct以及函數(shù),  
    //這樣在pass中只需要設(shè)置渲染狀態(tài)以及調(diào)用函數(shù),shader更加簡潔明了  
    CGINCLUDE  
    //cg文件,包含了unity內(nèi)置的一些cg函數(shù)  
    #include "UnityCG.cginc"  
      
    //blur結(jié)構(gòu)體,從blur的vert函數(shù)傳遞到frag函數(shù)的參數(shù)  
    struct v2f_blur  
    {  
        float4 pos : SV_POSITION; //頂點位置  
        float2 uv  : TEXCOORD0;   //紋理坐標  
        float2 uv1 : TEXCOORD1;  //周圍紋理1  
        float2 uv2 : TEXCOORD2;  //周圍紋理2  
        float2 uv3 : TEXCOORD3;  //周圍紋理3  
        float2 uv4 : TEXCOORD4;  //周圍紋理4  
    };  
  
    //用到的變量  
    sampler2D _MainTex;  
    //XX_TexelSize,XX紋理的像素相關(guān)大小width,height對應(yīng)紋理的分辨率,x = 1/width, y = 1/height, z = width, w = height  
    float4 _MainTex_TexelSize;  
    //模糊半徑  
    float _BlurRadius;  
  
    //vertex shader  
    v2f_blur vert_blur(appdata_img v)  
    {  
        v2f_blur o;  
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
        o.uv = v.texcoord.xy;  
        //計算uv上下左右四個點對于blur半徑下的uv坐標  
        o.uv1 = v.texcoord.xy + _BlurRadius * _MainTex_TexelSize * float2( 1,  1);  
        o.uv2 = v.texcoord.xy + _BlurRadius * _MainTex_TexelSize * float2(-1,  1);  
        o.uv3 = v.texcoord.xy + _BlurRadius * _MainTex_TexelSize * float2(-1, -1);  
        o.uv4 = v.texcoord.xy + _BlurRadius * _MainTex_TexelSize * float2( 1, -1);  
  
        return o;  
    }  
  
    //fragment shader  
    fixed4 frag_blur(v2f_blur i) : SV_Target  
    {  
        fixed4 color = fixed4(0,0,0,0);  
  
        color += tex2D(_MainTex, i.uv );  
        color += tex2D(_MainTex, i.uv1);  
        color += tex2D(_MainTex, i.uv2);  
        color += tex2D(_MainTex, i.uv3);  
        color += tex2D(_MainTex, i.uv4);  
          
        //相加取平均,據(jù)說shader中乘法比較快  
        return color * 0.2;  
    }  
  
    ENDCG  
  
    //子著色器  
    SubShader  
    {  
        //pass 0: blur effect  
        Pass  
        {  
            ZTest Always  
            Cull Off  
            ZWrite Off  
            Fog{ Mode Off }  
  
            //直接調(diào)用vert_blur和frag_blur  
            CGPROGRAM  
            #pragma vertex vert_blur  
            #pragma fragment frag_blur  
            ENDCG  
        }  
    }  
}

C#腳本部分:

using UnityEngine;  
using System.Collections;  
  
//編輯狀態(tài)下也運行  
[ExecuteInEditMode]  
//繼承自PostEffectBase  
public class SimpleBlurEffect : PostEffectBase  
{  
    //模糊半徑  
    public float BlurRadius = 1.0f;  
  
    void OnRenderImage(RenderTexture source, RenderTexture destination)  
    {  
        if (_Material)  
        {  
  
            //blur   
            _Material.SetFloat("_BlurRadius", BlurRadius);  
            Graphics.Blit(source, destination, _Material);  
  
        }  
    }  
}

注意,此處的PostEffectBase為各種后處理效果的基類,在上一篇文章: Unity Shader-后處理:簡單的顏色調(diào)整(亮度,飽和度,對比度)中有該類的完整實現(xiàn),此處不予貼出代碼。

效果如下圖所示:

原圖效果

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

blurRadius = 1

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

blurRadius = 5

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

從上面的模糊效果我們看到,模糊半徑越大,模糊的效果越明顯。但是!這種效果看起來一點都不舒服,有種近視的趕腳,完全不是平滑的模糊效果,就更不要說進一步的毛玻璃之類的全模糊效果了。


三.均值模糊的改進

既然,一次模糊我們感覺效果不是很盡人意,那么,我們可以嘗試迭代模糊,也就是用上一次模糊的輸出作為下一次模糊的輸入,迭代之后的模糊效果更加明顯。先看一下代碼,這次,我們的shader代碼和上面的一樣,沒有變動,僅僅是修改了腳本,增加了降分辨率和迭代的兩個操作。

using UnityEngine;  
using System.Collections;  
  
//編輯狀態(tài)下也運行  
[ExecuteInEditMode]  
//繼承自PostEffectBase  
public class SimpleBlurEffect : PostEffectBase  
{  
    //模糊半徑  
    public float BlurRadius = 1.0f;  
    //降分辨率  
    public int downSample = 2;  
    //迭代次數(shù)  
    public int iteration = 3;  
  
    void OnRenderImage(RenderTexture source, RenderTexture destination)  
    {  
        if (_Material)  
        {  
            //申請RenderTexture,RT的分辨率按照downSample降低  
            RenderTexture rt1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);  
            RenderTexture rt2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);  
            
            //直接將原圖拷貝到降分辨率的RT上  
            Graphics.Blit(source, rt1);  
  
            //進行迭代,一次迭代進行了兩次模糊操作,使用兩張RT交叉處理  
            for(int i = 0; i < iteration; i++)  
            {  
                //用降過分辨率的RT進行模糊處理  
                _Material.SetFloat("_BlurRadius", BlurRadius);  
                Graphics.Blit(rt1, rt2, _Material);  
                Graphics.Blit(rt2, rt1, _Material);  
            }  
  
            //將結(jié)果拷貝到目標RT  
            Graphics.Blit(rt1, destination);  
  
            //釋放申請的兩塊RenderBuffer內(nèi)容  
            RenderTexture.ReleaseTemporary(rt1);  
            RenderTexture.ReleaseTemporary(rt2);  
        }  
    }  
}

結(jié)果如下:

blurRadius = 1, downSample = 2,  iteration = 3 

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

blurRadius = 1, downSample = 2, iteration = 5

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

我們看到,通過迭代以及降低分辨率,我們的模糊效果更加明顯了,當?shù)螖?shù)較大時,會有一種毛玻璃的效果。這里,雖然迭代次數(shù)增加了,會耗費更多的性能,但是相應(yīng)地,我們也降低了分辨率,也減少了采樣等計算操作的消耗。

四.RenderTexture介紹

這里,我們通過多次處理,包括降分辨率以及迭代,完成了模糊操作,這里我們需要臨時存儲上一次處理過的中間輸出,所以就需要用渲染中常用的一個概念RenderTexture。

關(guān)于RenderTexture,簡要介紹一下,我們在渲染場景時,一般都是直接輸出到幀緩存,然后輸出到屏幕上,然而有的時候,我們并不想直接輸出結(jié)果,而是需要對這個渲染的結(jié)果進行處理,所以,我們就將渲染的結(jié)果輸出到了一張紋理上,也就是RenderTexture,這也是所有后處理的基礎(chǔ)。Unity的RenderTexture還是很好用的,我們不僅僅可以在后處理時使用,還可以通過把攝像機的輸出設(shè)置到某個RT上,然后用這張RT作為一些類似鏡子的物體上,就可以實現(xiàn)鏡面效果或者屏幕效果。

不過RenderTexture還是很耗費資源的,一張大的RenderTexture是屏幕分辨率大小的一張圖片,而且是完全不能夠壓縮的,所以當后處理中RenderTexture用得多時,內(nèi)存消耗很大,在手機,尤其是大屏手機,內(nèi)存比較小的情況下,后處理疊加時很可能會由于內(nèi)存耗盡而崩潰。所以,我們在使用RenderTexture時需要慎重考慮。如果效果可以接受,我們就可以考慮降低RenderTexture的分辨率,這樣,輸出的畫面效果可能會打一些折扣,但是性能會有很大的提高。而我們的模糊效果,本身降低分辨率就會導致畫面比較模糊,所以在這里,我們完全可以放心大膽地降低RT的分辨率,既可以提升效果,又可以大大地減少開銷。

這里還有一點,由于OnRenderImage函數(shù)每幀在渲染之前都會調(diào)用,之前曾經(jīng)擔心會不會每一幀在這里申請RT,然后釋放,會不會有很高的GC?經(jīng)過查找了一些資料,發(fā)現(xiàn)Unity這里是進行過處理的,RenderTexture是之前申請好的一塊內(nèi)存區(qū)域,我們可以直接使用,而不需要考慮GC的問題,正如這兩個函數(shù)的名字一樣,RenderTexture.GetTemporary和RenderTexture.ReleaseTemporary一樣。并且,本人親測,使用Profile掛了一下這個腳本,發(fā)現(xiàn)的確沒有GC:

Unity Shader后處理中如何實現(xiàn)簡單均值模糊

以上是“Unity Shader后處理中如何實現(xiàn)簡單均值模糊”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

當前題目:UnityShader后處理中如何實現(xiàn)簡單均值模糊
本文來源:http://chinadenli.net/article0/giepio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作自適應(yīng)網(wǎng)站、網(wǎng)站設(shè)計公司網(wǎng)站設(shè)計、定制網(wǎng)站軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護公司