unity3d 理解Graphics.BlitMultiTap

如果你学习unity3d官方的Image Effects包中的Shader,可能会看到这个方法。
unity的文档对它并没有一个很明确的描述(链接)

在官方范例的BlurEffect.cs里,它是被这样使用的:

    // 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有关的代码应该是这里:

    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中读取并使用:

    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会被忽略。

所以,其实Graphics.BlitMultiTap是一个用来配合固定管线工作的方法。对于可编程管线,它只是提供了最基本的兼容性。不过对于可编程管线可以提供的灵活性来说,BlitMultiTap所提供的功能也是完全没有必要的,我们所能够定制的MultiTap方式远远比这个方法提供的要丰富。在进行当代GPU编程时,我们可以认为它是一个过时的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值