如果你学习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编程时,我们可以认为它是一个过时的方法。