上期讲了在UIpanel.clipping != Clipping.SoftClip下按钮变灰的方案,但是当应用到SoftClip下时,会导致Sprite无法正常遮罩,而且变灰效果也消失的情况,例如ScrollView下,会导致上述问题。
因一时无从知晓到底哪里出现问题,于是便从ScrollView实现遮罩的方式入手,先了解下NGUI实现遮罩的方式,NGUI的渲染都是通过UIDrawCall类进行的,通过断点发现,当ScrollView进行遮罩时会在UIDrawCall的CreateMaterial()函数内进行动态换Shader操作:
if (panel.clipping == Clipping.TextureMask)
{
mTextureClip = true;
shader = Shader.Find("Hidden/" + shaderName +textureClip);
}
else if (mClipCount != 0)
{
shader = Shader.Find("Hidden/" + shaderName + " " + mClipCount);
if (shader == null) shader = Shader.Find(shaderName + " " + mClipCount);
// Legacy functionality
if (shader == null && mClipCount == 1)
{
mLegacyShader = true;
shader = Shader.Find(shaderName + soft);
}
}
通过上述代码可知,当为SoftClip状态下时,NGUI会自动给Sprite寻找名字为”Hidden/” + shaderName + ” ” + mClipCount的shader,显然,在Normal状态下,此时shader会变为NGUI自带的”Hidden/Unlit/Transparent Colored 1”,进入该shader后,我们会发现在frag()函数内有这么句代码col.a *= clamp( min(factor.x, factor.y), 0.0, 1.0);问题找到了,原来ScrollView是通过句代码来实现遮罩的,那么当我们将shader换成我们自己的shader时,首先在SoftClip下找不到一个叫”Hidden/xxxx 1”的shader进行替换,这时NGUI会强行换成默认状态的shader,因此,这就是导致我们上述问题的元凶。
替换为默认shader代码// Always fallback to the default shader
if (shader == null) shader = Shader.Find(“Unlit/Transparent Colored”)。
既然问题找到了,那么就可以着手解决这个问题了,首先仿照NGUI的shader,建立一个名叫”Hidden/UI/Sprite/Gray 1” 的shader,///注意此处shader命名需要与我第一篇的shader命名一致才可,即UI/Sprite/Gray处两个shader必须保持一致!!!!然后将”Hidden/Unlit/Transparent Colored 1”完全copy过来,最后在他的frag()函数内自行添加实现Sprite变灰的代码即可,这样在遮罩时就会找到正确的shader并替换,现在贴上我修改后的shader:
Shader "Hidden/UI/Sprite/Gray 1"
{
Properties
{
_MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
}
SubShader
{
LOD 200
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Cull Off
Lighting Off
ZWrite Off
Offset -1, -1
Fog { Mode Off }
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _ClipRange0 = float4(0.0, 0.0, 1.0, 1.0);
float2 _ClipArgs0 = float2(1000.0, 1000.0);
struct appdata_t
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
float2 worldPos : TEXCOORD1;
};
v2f o;
v2f vert (appdata_t v)
{
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.color = v.color;
o.texcoord = v.texcoord;
o.worldPos = v.vertex.xy * _ClipRange0.zw + _ClipRange0.xy;
return o;
}
half4 frag (v2f IN) : COLOR
{
// Softness factor
float2 factor = (float2(1.0, 1.0) - abs(IN.worldPos)) * _ClipArgs0;
// Sample the texture
half4 col = tex2D(_MainTex, IN.texcoord) * IN.color;
col.rgb = dot(col.rgb, fixed3(.222,.707,.071));
col.a *= clamp( min(factor.x, factor.y), 0.0, 1.0);
return col;
}
ENDCG
}
}
}
跟上一篇shader一样,通过 col.rgb = dot(col.rgb, fixed3(.222,.707,.071)); 实现变灰效果, col.a *= clamp( min(factor.x, factor.y), 0.0, 1.0);实现遮罩效果,现在两种效果合一,应该可以正常工作了,
下面上图
可以看到正常工作,ok收工,下期开讲当ScrollView下有成百上千个item时优化工作,让滑动变得流畅。