[Shader]对NGUI的UISprite和UITexture进行裁剪(scrollview + 遮罩)

由于最近比较忙,所以很多我在其它地方发布的博文都没有同步到这里。我会在后面慢慢重新补回来。对各位关注我博客的读者也表示抱歉!
版权所有,转载须注明出处!
喜欢火影、喜欢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代码如下:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Shader "Unlit/Transparent Colored Mask"  
  2. {  
  3.         Properties  
  4.         {  
  5.                 _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}  
  6.                 _Mask ("Mask Alpha (A)", 2D) = "white" {}  
  7.         }  
  8.           
  9.         SubShader  
  10.         {  
  11.                 LOD 100  
  12.   
  13.   
  14.                 Tags  
  15.                 {  
  16.                         "Queue" = "Transparent"  
  17.                         "IgnoreProjector" = "True"  
  18.                         "RenderType" = "Transparent"  
  19.                 }  
  20.                   
  21.                 Cull Off  
  22.                 Lighting Off  
  23.                 ZWrite Off  
  24.                 Fog { Mode Off }  
  25.                 Offset -1, -1  
  26.                 Blend SrcAlpha OneMinusSrcAlpha  
  27.   
  28.   
  29.                 Pass  
  30.                 {  
  31.                         CGPROGRAM  
  32.                         #pragma vertex vert  
  33.                         #pragma fragment frag  
  34.                                   
  35.                         #include "UnityCG.cginc"  
  36.           
  37.                         struct appdata_t  
  38.                         {  
  39.                                 float4 vertex : POSITION;  
  40.                                 float2 texcoord : TEXCOORD0;  
  41.                                 fixed4 color : COLOR;  
  42.                         };  
  43.           
  44.                         struct v2f  
  45.                         {  
  46.                                 float4 vertex : SV_POSITION;  
  47.                                 half2 texcoord : TEXCOORD0;  
  48.                                 fixed4 color : COLOR;  
  49.                                 fixed gray : TEXCOORD1;   
  50.                         };  
  51.           
  52.                         sampler2D _MainTex;  
  53.                         sampler2D _Mask;  
  54.                         float4 _MainTex_ST;  
  55.                         float4 _Mask_ST;  
  56.                                   
  57.                         v2f vert (appdata_t v)  
  58.                         {  
  59.                                 v2f o;  
  60.                                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);  
  61.                                 o.texcoord = v.texcoord;  
  62.                                 o.color = v.color;  
  63.                                 o.gray = dot(v.color, fixed4(1,1,1,0));  
  64.                                 return o;  
  65.                         }  
  66.                                   
  67.                         fixed4 frag (v2f i) : COLOR  
  68.                         {  
  69.                             fixed4 col;  
  70.                                   
  71.                                 col = tex2D(_MainTex, i.texcoord) * i.color;  
  72.                                 col.a = col.a * tex2D(_Mask, i.texcoord).a;  
  73.                                 return col;  
  74.                         }  
  75.                         ENDCG  
  76.                 }  
  77.         }  
  78.   
  79.   
  80.         SubShader  
  81.         {  
  82.                 LOD 100  
  83.   
  84.   
  85.                 Tags  
  86.                 {  
  87.                         "Queue" = "Transparent"  
  88.                         "IgnoreProjector" = "True"  
  89.                         "RenderType" = "Transparent"  
  90.                 }  
  91.                   
  92.                 Pass  
  93.                 {  
  94.                         Cull Off  
  95.                         Lighting Off  
  96.                         ZWrite Off  
  97.                         Fog { Mode Off }  
  98.                         Offset -1, -1  
  99.                         ColorMask RGB  
  100.                         AlphaTest Greater .01  
  101.                         Blend SrcAlpha OneMinusSrcAlpha  
  102.                         ColorMaterial AmbientAndDiffuse  
  103.                           
  104.                         SetTexture [_MainTex]  
  105.                         {  
  106.                                 Combine Texture * Primary  
  107.                         }  
  108.                 }  
  109.         }  
  110. }  
主要实现裁剪的代码为:
[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. fixed4 frag (v2f i) : COLOR  
  2. {  
  3.     fixed4 col;  
  4.     col = tex2D(_MainTex, i.texcoord) * i.color;  
  5.     col.a = col.a * tex2D(_Mask, i.texcoord).a;  
  6.     return col;  
  7. }  
相信大家很容易就看懂了,这里是把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了吗?
机智的我立马动起手来。

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Shader "Unlit/Transparent Colored Mask"  
  2. {  
  3.         Properties  
  4.         {  
  5.                 _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}  
  6.                 _Mask ("Mask Alpha (A)", 2D) = "white" {}  
  7.                 _WidthRate ("Sprite.width/Atlas.width", float) = 1  
  8.                 _HeightRate ("Sprite.height/Atlas.height", float) = 1  
  9.                 _XOffset("offsetX", float) = 0  
  10.                 _XOffset("offsetY", float) = 0  
  11.         }  
  12.           
  13.         SubShader  
  14.         {  
  15.                 LOD 100  
  16.   
  17.   
  18.                 Tags  
  19.                 {  
  20.                         "Queue" = "Transparent"  
  21.                         "IgnoreProjector" = "True"  
  22.                         "RenderType" = "Transparent"  
  23.                 }  
  24.                   
  25.                 Cull Off  
  26.                 Lighting Off  
  27.                 ZWrite Off  
  28.                 Fog { Mode Off }  
  29.                 Offset -1, -1  
  30.                 Blend SrcAlpha OneMinusSrcAlpha  
  31.   
  32.   
  33.                 Pass  
  34.                 {  
  35.                         CGPROGRAM  
  36.                         #pragma vertex vert  
  37.                         #pragma fragment frag  
  38.                                   
  39.                         #include "UnityCG.cginc"  
  40.           
  41.                         struct appdata_t  
  42.                         {  
  43.                                 float4 vertex : POSITION;  
  44.                                 float2 texcoord : TEXCOORD0;  
  45.                                 fixed4 color : COLOR;  
  46.                         };  
  47.           
  48.                         struct v2f  
  49.                         {  
  50.                                 float4 vertex : SV_POSITION;  
  51.                                 half2 texcoord : TEXCOORD0;  
  52.                                 fixed4 color : COLOR;  
  53.                                 fixed gray : TEXCOORD1;   
  54.                         };  
  55.           
  56.                         sampler2D _MainTex;  
  57.                         sampler2D _Mask;  
  58.                         float4 _MainTex_ST;  
  59.                         float4 _Mask_ST;  
  60.                         float _WidthRate;  
  61.                         float _HeightRate;  
  62.                         float _XOffset;   
  63.                         float _YOffset;   
  64.                                   
  65.                         v2f vert (appdata_t v)  
  66.                         {  
  67.                                 v2f o;  
  68.                                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);  
  69.                                 o.texcoord = v.texcoord;  
  70.                                 o.color = v.color;  
  71.                                 o.gray = dot(v.color, fixed4(1,1,1,0));  
  72.                                 return o;  
  73.                         }  
  74.                                   
  75.                         fixed4 frag (v2f i) : COLOR  
  76.                         {  
  77.                             fixed4 col;  
  78.                                   
  79.                                 col = tex2D(_MainTex, i.texcoord) * i.color;  
  80.                                 col.a = col.a * tex2D(_Mask, float2((i.texcoord.x-_XOffset)/_WidthRate, (i.texcoord.y-(1-_YOffset))/_HeightRate)).a;   
  81.                                 return col;  
  82.                         }  
  83.                         ENDCG  
  84.                 }  
  85.         }  
  86.   
  87.   
  88.         SubShader  
  89.         {  
  90.                 LOD 100  
  91.   
  92.   
  93.                 Tags  
  94.                 {  
  95.                         "Queue" = "Transparent"  
  96.                         "IgnoreProjector" = "True"  
  97.                         "RenderType" = "Transparent"  
  98.                 }  
  99.                   
  100.                 Pass  
  101.                 {  
  102.                         Cull Off  
  103.                         Lighting Off  
  104.                         ZWrite Off  
  105.                         Fog { Mode Off }  
  106.                         Offset -1, -1  
  107.                         ColorMask RGB  
  108.                         AlphaTest Greater .01  
  109.                         Blend SrcAlpha OneMinusSrcAlpha  
  110.                         ColorMaterial AmbientAndDiffuse  
  111.                           
  112.                         SetTexture [_MainTex]  
  113.                         {  
  114.                                 Combine Texture * Primary  
  115.                         }  
  116.                 }  
  117.         }  
  118. }  

好了。那么怎么使用这个Shader。我们需要多一个脚本来设置这个shader的参数。

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4.   
  5. [ExecuteInEditMode]  
  6. public class ScaleTexcoord : MonoBehaviour  
  7. {  
  8.     private float wr;  
  9.     private float hr;  
  10.     private float offX;  
  11.     private float offY;  
  12.     private UISprite s;  
  13.     void Awake()  
  14.     {  
  15.         s = GetComponent<UISprite>();  
  16.   
  17.   
  18.         wr = s.GetAtlasSprite().width * 1.0f / s.atlas.spriteMaterial.mainTexture.width;  
  19.         offX = s.GetAtlasSprite().x * 1.0f / s.atlas.spriteMaterial.mainTexture.width;  
  20.   
  21.   
  22.         hr = s.GetAtlasSprite().height * 1.0f / s.atlas.spriteMaterial.mainTexture.height;  
  23.         offY = (s.GetAtlasSprite().y + s.GetAtlasSprite().height) * 1.0f / s.atlas.spriteMaterial.mainTexture.height;  
  24.     }  
  25.   
  26.   
  27.     public void Update()  
  28.     {  
  29.         s.atlas.spriteMaterial.SetFloat("_WidthRate", wr);  
  30.         s.atlas.spriteMaterial.SetFloat("_HeightRate", hr);  
  31.         s.atlas.spriteMaterial.SetFloat("_XOffset", offX);  
  32.         s.atlas.spriteMaterial.SetFloat("_YOffset", offY);  
  33.     }  
  34. }  


只要把这个脚本附在UISprite上即可。


可以发现现在正常了。NGUI图集的材质变成了



好了。这次真的可以好好庆祝下啦~~

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


下载测试工程


版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值