unity3d 理解Graphics.BlitMultiTap

若是你學習unity3d官方的Image Effects包中的Shader,可能會看到這個方法。
unity的文檔對它並無一個很明確的描述(連接)php

在官方範例的BlurEffect.cs裏,它是被這樣使用的:html

// Performs one blur iteration.
    public void FourTapCone (RenderTexture source, RenderTexture dest, int iteration)
    {
        float off = 0.5f + iteration*blurSpread;
        Graphics.BlitMultiTap (source, dest, material,
            new Vector2(-off, -off),
            new Vector2(-off,  off),
            new Vector2( off,  off),
            new Vector2( off, -off)
        );
    }

在相應的Shader中有一段SubShader和這段代碼進行配合工做:編程

SubShader { 
        Pass {
            ZTest Always Cull Off ZWrite Off Fog { Mode Off }
            SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant alpha}
            SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
            SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
            SetTexture [_MainTex] {constantColor (0,0,0,0.25) combine texture * constant + previous}
        }
    }

根據以前有朋友發佈的研究,以上代碼含義是針對Graphics.BlitMultiTap所傳入的每個偏移值,進行一次紋理採樣,而且與前一步的渲染結果進行疊加。你還能夠額外增長本身的採樣(tap)數,只要在C#中添加一個向量,而且在固定管線SubShader中添加一行SetTexture語句就能夠。數組

可是,當與可編程管線結合的時候,狀況就不大同樣了。
官方範例的BlurEffectConeTaps.shader中就提供了另一個使用可編程管線實現Blur的SubShader。
(默認狀況下它是不生效的,由於固定管線的SubShader在它以前,通常狀況下它不會被選擇激活。若是咱們把固定管線的SubShader註釋掉,那麼可編程管線的SubShader就能夠生效。)
在這個SubShader中最早找到的和BlitMultiTap有關的代碼應該是這裏:app

struct v2f {
        float4 pos : POSITION;
        half2 uv : TEXCOORD0;
        half2 taps[4] : TEXCOORD1; 
    };

接下來在VS裏,對這個四項數組的每一項都進行了賦值:學習

half4 _MainTex_TexelSize;
    half4 _BlurOffsets;
    v2f vert( appdata_img v ) {
        v2f o; 
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = v.texcoord - _BlurOffsets.xy * _MainTex_TexelSize.xy; // hack, see BlurEffect.cs for the reason for this. let's make a new blur effect soon
        o.taps[0] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy;
        o.taps[1] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy;
        o.taps[2] = o.uv + _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
        o.taps[3] = o.uv - _MainTex_TexelSize * _BlurOffsets.xy * half2(1,-1);
        return o;
    }

並最終在FS中讀取並使用:this

sampler2D _MainTex;
    half4 frag(v2f i) : COLOR {
        half4 color = tex2D(_MainTex, i.taps[0]);
        color += tex2D(_MainTex, i.taps[1]);
        color += tex2D(_MainTex, i.taps[2]);
        color += tex2D(_MainTex, i.taps[3]); 
        return color * 0.25;
    }

在這種情景下,其實taps[]數組的數據來源並非C#代碼中指定的四個偏移量,而是Shader本身結合_BlurOffsets變量計算出來的。
_BlurOffsets是一個特殊的uniform變量,若是在C#代碼中調用了Graphics.BlitMultiTap來進行後期處理,那麼這個方法傳入的第一個offsets參數會被賦值到_BlurOffsets的xy,然後續的更多offsets會被忽略。3d

因此,其實Graphics.BlitMultiTap是一個用來配合固定管線工做的方法。對於可編程管線,它只是提供了最基本的兼容性。不過對於可編程管線能夠提供的靈活性來講,BlitMultiTap所提供的功能也是徹底沒有必要的,咱們所可以定製的MultiTap方式遠遠比這個方法提供的要豐富。在進行當代GPU編程時,咱們能夠認爲它是一個過期的方法。code

相關文章
相關標籤/搜索