本文轉(zhuǎn)自:Unity3D開發(fā)(二):NGUI之UIButton"禁用"狀態(tài)時置灰
和 修改Shader讓NGUI支持灰色濾鏡
在使用NGUI的按鈕時,經(jīng)常需要在某種情況下禁用按鈕,使其點擊無效,這時如果能使按鈕變成灰色可以起到不錯的提醒用戶的作用,正常做法是:
UIButton.isEnabled=false找筝;
這句話會觸發(fā)UIButton的Disabled Color投队,但其效果并不是使按鈕圖標(biāo)變成灰色寝志,而是在上面疊加了一層暗色的效果哆料,如圖:
1.原理
Unity3d中所有的渲染都是基于Shader的,而Shader綁定在Material上吗铐,打開一個NGUI例子中自帶的Material东亦,得到其使用Shader的文件
NGUI中大部分材質(zhì)都使用的Unlit/Transparent Colored(PS:雖然在Unlit下,但并不是Unity3d內(nèi)置的唬渗,而是NGUI擴展的)
找到其片段著色器典阵,代碼如下:
fixed4 frag (v2f i) : COLOR
{
fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
return col;
}
可以看到從頂點著色器中傳出的顏色屬性乘到了紋理采樣得到的像素上。在本例中镊逝,紋理顏色從國旗上采樣得到壮啊,頂點著色器的顏色則是上圖中"Disabled"屬性的顏色值,所以這是一種疊加效果撑蒜,而不會使圖標(biāo)變灰歹啼。
2.解決方案
方案有兩種,一是準(zhǔn)備兩套素材座菠,一組正常一組灰色狸眼,在合適時機切換到灰色素材即可,但如果游戲中需要置灰的UI比較多浴滴,那么會造成游戲包體變大拓萌。
另一種就是在shader中作處理,以某一個顏色作為"約定"升略,比純黑色(0,0,0,1)微王,將UIButton的Disabled Color設(shè)為(0,0,0,255)屡限,再將Unlit/Transparent Colored的片段著色器部分改成如下代碼:
fixed4 frag (v2f i) : COLOR
{
fixed4 col;
if (i.color.r < 0.001)
{
col = tex2D(_MainTex, i.texcoord);
float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = float3(grey, grey, grey);
}
else
{
col = tex2D(_MainTex, i.texcoord) * i.color;
}
return col;
}
其中(0.299,0.587炕倘,0.114)為灰度公式的參數(shù)钧大,渲染效果如圖:
圖中兩個按鈕的Sprite屬于同一張圖集Atlas,將左邊按鈕設(shè)置isEnabled=false后激才,可以看到其變成了灰色圖標(biāo)拓型。
3.優(yōu)化
上述代碼效率比較低,原因是if (i.color.r < 0.001)這里訪問了color的分量r瘸恼,但在官方文檔中明確說了這樣做效率低劣挫,除非必要情況時才使用。因此可將代碼改成下面這樣:
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
fixed4 color : COLOR;
fixed gray : TEXCOORD1; //添加這一行
};
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.texcoord;
o.color = v.color;
o.gray = dot(v.color, fixed4(1,1,1,0)); //添加這一行
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 col;
if (i.gray == 0) //修改判斷條件
{
col = tex2D(_MainTex, i.texcoord);
float grey = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = float3(grey, grey, grey);
}
else
{
col = tex2D(_MainTex, i.texcoord) * i.color;
}
return col;
}
這樣可以避免訪問color的分量东帅,提高渲染效率压固。