这个应该是挺常见的,或许你会说,美术直接帮你裁成圆的不就可以吗。有时候可以,有时候不行。什么时候不行呢?当你在游戏中有些地方使用方形的,有些地方使用圆形的。这时候就不能让美术帮你裁了。不然不就有两份资源了。
本文读者最好已经知道怎么使用NGUI创建图集,使用它的UISprite和UITexture。
插件:NGUI 3.5.7
作为一个学习过两天Shader的人,我觉得,这应该难不倒我。因此,我立马在U3D的Project面板中噼里啪啦一阵狂搞。创建一个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。
这个Mask图片为
然后修改这个图集的材质使用我们的Shader。
额。。。效果咋成下面这样啦。。。不太对的赶脚
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 } } } }
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); } }
整个效果其实只用上面的Shader和那个ScaleTexcoord.cs即可。
下载测试工程: