[Shader]對NGUI的UISprite和UITexture進行裁剪,nguiuisprite

來源:互聯網
上載者:User

[Shader]對NGUI的UISprite和UITexture進行裁剪,nguiuisprite
由於最近比較忙,所以很多我在其它地方發布的博文都沒有同步到這裡。我會在後面慢慢重新補回來。對各位關注我部落格的讀者也表示抱歉!

著作權,轉載須註明出處!
喜歡火影、喜歡Java、喜歡unity3D、喜歡遊戲開發的都可以加入木葉村Q群: 379076227
0、隨便聊本人真正學習Shader的時間莫過於今年春節在家的兩天時間,雖然短短兩天。但是已經深深喜歡上Shader。深受其魅力吸引。
但是平常主要做的還是服務端和用戶端的開發,偏邏輯向。所以好久也沒碰Shader了。
但是昨天在一個群裡有人討論NGUI不能對Sprite進行裁剪。比如把一個方形的,顯示成一個圓形的。如:

這個應該是挺常見的,或許你會說,美術直接幫你裁成圓的不就可以嗎。有時候可以,有時候不行。什麼時候不行呢?當你在遊戲中有些地方使用方形的,有些地方使用圓形的。這時候就不能讓美術幫你裁了。不然不就有兩份資源了。

本文讀者最好已經知道怎麼使用NGUI建立圖集,使用它的UISprite和UITexture。


本文編寫測試環境為:
系統:Win7 X64引擎:Unity3D V4.3.3

外掛程式:NGUI 3.5.7

1、開始動手

作為一個學習過兩天Shader的人,我覺得,這應該難不倒我。因此,我立馬在U3D的Project面板中劈裡啪啦一陣狂搞。建立一個Shader。


2、編寫第一版Shader。雙擊我們上面建立的Shader。因為這個是給NGUI用的。然後我就依照NGUI的Shader命名,給我們的Shader命名為:Unlit/Transparent Colored Mask
Shader代碼如下:
Shader "Unlit/Transparent Colored Mask"{        Properties        {                _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}                _Mask ("Mask Alpha (A)", 2D) = "white" {}        }                SubShader        {                LOD 100                Tags                {                        "Queue" = "Transparent"                        "IgnoreProjector" = "True"                        "RenderType" = "Transparent"                }                                Cull Off                Lighting Off                ZWrite Off                Fog { Mode Off }                Offset -1, -1                Blend SrcAlpha OneMinusSrcAlpha                Pass                {                        CGPROGRAM                        #pragma vertex vert                        #pragma fragment frag                                                        #include "UnityCG.cginc"                                struct appdata_t                        {                                float4 vertex : POSITION;                                float2 texcoord : TEXCOORD0;                                fixed4 color : COLOR;                        };                                struct v2f                        {                                float4 vertex : SV_POSITION;                                half2 texcoord : TEXCOORD0;                                fixed4 color : COLOR;                                fixed gray : TEXCOORD1;                         };                                sampler2D _MainTex;                        sampler2D _Mask;                        float4 _MainTex_ST;                        float4 _Mask_ST;                                                        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;                                                                col = tex2D(_MainTex, i.texcoord) * i.color;                                col.a = col.a * tex2D(_Mask, i.texcoord).a;                                return col;                        }                        ENDCG                }        }        SubShader        {                LOD 100                Tags                {                        "Queue" = "Transparent"                        "IgnoreProjector" = "True"                        "RenderType" = "Transparent"                }                                Pass                {                        Cull Off                        Lighting Off                        ZWrite Off                        Fog { Mode Off }                        Offset -1, -1                        ColorMask RGB                        AlphaTest Greater .01                        Blend SrcAlpha OneMinusSrcAlpha                        ColorMaterial AmbientAndDiffuse                                                SetTexture [_MainTex]                        {                                Combine Texture * Primary                        }                }        }}
主要實現裁剪的代碼為:
fixed4 frag (v2f i) : COLOR{    fixed4 col;    col = tex2D(_MainTex, i.texcoord) * i.color;    col.a = col.a * tex2D(_Mask, i.texcoord).a;    return col;}
相信大家很容易就看懂了,這裡是把Mask貼圖的Alpha通道的值和原圖片的進行相乘。
怎麼用呢。

建立一個UItexture。



然後選擇一個材質。用上我們上面的Shader。然後設定一個Mask。

這個Mask圖片為



可以看到Alpha通道裡面是一個白色的圓圈。
記得這個Mask圖片的匯入設定如下:


那麼可以看看運行效果:

3、歡呼,慶祝?貌似一切都挺順利的。但是這個Shader能否對UISprite起效果呢?
我們來試試。
隨便搞個圖集。然後加個UISprite,


然後修改這個圖集的材質使用我們的Shader。

額。。。效果咋成下面這樣啦。。。不太對的趕腳


4、停一停想一想難道這是NGUI的bug。。。啊!!!啊!!!!!
不行,我要想想看
。。。。。。。。。
1分鐘過去了。
為什麼col.a = col.a * tex2D(_Mask, i.texcoord).a這個公式對Sprite的效果是錯誤的呢。
難道i.texcoord的範圍不是0~1.
這麼一想,倒好像也有點道理。因為NGUI把要用到的圖片做成了圖集。因此,每次只是取圖集中的一小個地區顯示到UI的Mesh上。
那麼,我只要把i.texcoord的範圍重新對應到0~1。然後用於取Mask上面的顏色,不就OK了嗎?
機智的我立馬動起手來。
Shader "Unlit/Transparent Colored Mask"{        Properties        {                _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}                _Mask ("Mask Alpha (A)", 2D) = "white" {}                _WidthRate ("Sprite.width/Atlas.width", float) = 1                _HeightRate ("Sprite.height/Atlas.height", float) = 1                _XOffset("offsetX", float) = 0                _XOffset("offsetY", float) = 0        }                SubShader        {                LOD 100                Tags                {                        "Queue" = "Transparent"                        "IgnoreProjector" = "True"                        "RenderType" = "Transparent"                }                                Cull Off                Lighting Off                ZWrite Off                Fog { Mode Off }                Offset -1, -1                Blend SrcAlpha OneMinusSrcAlpha                Pass                {                        CGPROGRAM                        #pragma vertex vert                        #pragma fragment frag                                                        #include "UnityCG.cginc"                                struct appdata_t                        {                                float4 vertex : POSITION;                                float2 texcoord : TEXCOORD0;                                fixed4 color : COLOR;                        };                                struct v2f                        {                                float4 vertex : SV_POSITION;                                half2 texcoord : TEXCOORD0;                                fixed4 color : COLOR;                                fixed gray : TEXCOORD1;                         };                                sampler2D _MainTex;                        sampler2D _Mask;                        float4 _MainTex_ST;                        float4 _Mask_ST;                        float _WidthRate;                        float _HeightRate;                        float _XOffset;                         float _YOffset;                                                         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;                                                                col = tex2D(_MainTex, i.texcoord) * i.color;                                col.a = col.a * tex2D(_Mask, float2((i.texcoord.x-_XOffset)/_WidthRate, (i.texcoord.y-(1-_YOffset))/_HeightRate)).a;                                 return col;                        }                        ENDCG                }        }        SubShader        {                LOD 100                Tags                {                        "Queue" = "Transparent"                        "IgnoreProjector" = "True"                        "RenderType" = "Transparent"                }                                Pass                {                        Cull Off                        Lighting Off                        ZWrite Off                        Fog { Mode Off }                        Offset -1, -1                        ColorMask RGB                        AlphaTest Greater .01                        Blend SrcAlpha OneMinusSrcAlpha                        ColorMaterial AmbientAndDiffuse                                                SetTexture [_MainTex]                        {                                Combine Texture * Primary                        }                }        }}

好了。那麼怎麼使用這個Shader。我們需要多一個指令碼來設定這個shader的參數。

using UnityEngine;using System.Collections;[ExecuteInEditMode]public class ScaleTexcoord : MonoBehaviour{    private float wr;    private float hr;    private float offX;    private float offY;    private UISprite s;    void Awake()    {        s = GetComponent<UISprite>();        wr = s.GetAtlasSprite().width * 1.0f / s.atlas.spriteMaterial.mainTexture.width;        offX = s.GetAtlasSprite().x * 1.0f / s.atlas.spriteMaterial.mainTexture.width;        hr = s.GetAtlasSprite().height * 1.0f / s.atlas.spriteMaterial.mainTexture.height;        offY = (s.GetAtlasSprite().y + s.GetAtlasSprite().height) * 1.0f / s.atlas.spriteMaterial.mainTexture.height;    }    public void Update()    {        s.atlas.spriteMaterial.SetFloat("_WidthRate", wr);        s.atlas.spriteMaterial.SetFloat("_HeightRate", hr);        s.atlas.spriteMaterial.SetFloat("_XOffset", offX);        s.atlas.spriteMaterial.SetFloat("_YOffset", offY);    }}


只要把這個指令碼附在UISprite上即可。


可以發現現在正常了。NGUI圖集的材質變成了


好了。這次真的可以好好慶祝下啦~~

整個效果其實只用上面的Shader和那個ScaleTexcoord.cs即可。


下載測試工程:


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.