效果:
變灰,過濾,流光 都是UI上常用效果。
比如:
1.按鈕禁用時,變灰。
2.一張Icon要應付圓形背景框,又要應付矩形背景框。就要使用過濾的方式來裁剪。
避免了美術提供兩張icon的麻煩,又節省了內存。
3.流光,呃……,策划就是要,你能怎么辦。
實踐:
NGUI把要用到的圖片做成了圖集,它會記錄每一張小圖的信息。
包括:每一張小圖在這張圖集里面的位置,長,寬,padding,border。等等。
使用時只是采樣這張小圖所在區域,然后顯示在UI的mesh上。
如果我們用這張小圖的texcoord,去采樣另外一張圖,采樣到的就只是部分,就不是我們所希望那樣(采樣完整的圖)。
那么,只要把小圖texcoord按照相應比例擴大,得到正確的texcoord即可。
看一下t_sheyaonan在圖集中的位置,Position(0,26) ,width:102,height:111
0,26
再看下圖集,哦,原來圖集的左上角為0,0點。
分析:
要得到正確的texcoord坐標?
只需將小圖A的texcoord坐標,減去偏移,再按規定的比例擴大。
so:
final_uv.x = (小圖A的texcoord.x – x/W ) * (W/w)
final_uv.y = (小圖A的texcoord.y – (H-y-h)/H) * (H/h)
用final_uv去采樣就OK了。
shader代碼:改寫自Unlit – Transparent Colored
//–add– 部分就是我添加的。
Shader "Custom/Unlit/Transparent Colored Grey Mask Flow" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {} //---add--------------------------------- _MaskTex ("Mask Alpha (A)", 2D) = "white" {} _IfMask("Open mask if larger than 0.5", Range(0,1)) = 0 _WidthRate ("Sprite.width/Atlas.width", float) = 1 _HeightRate ("Sprite.height/Atlas.height", float) = 1 _XOffset("offsetX/Atlas.width", float) = 0 _YOffset("offsetY/Atlas.height", float) = 0 _FlowTex("flow tex",2D) = ""{} //-------------------------------------- } 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; }; sampler2D _MainTex; float4 _MainTex_ST; //---add------- sampler2D _MaskTex; float _IfMask; float _WidthRate; float _HeightRate; float _XOffset; float _YOffset; sampler2D _FlowTex; //-------------- v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.texcoord = v.texcoord; o.color = v.color; return o; } fixed4 frag (v2f i) : COLOR { fixed4 col; col = tex2D(_MainTex, i.texcoord); //---------add--------------------------------- //過濾 if(_IfMask>0.5) { col.a = col.a * tex2D(_MaskTex, float2((i.texcoord.x-_XOffset)/_WidthRate, (i.texcoord.y-_YOffset)/_HeightRate)).a; } //變灰 if(i.color.r<=0.1) { float grey = dot(col.rgb, float3(0.299, 0.587, 0.114)); col.rgb = float3(grey, grey, grey); } //流光 if(i.color.g<=0.1) { float2 flow_uv = float2((i.texcoord.x-_XOffset)/_WidthRate, (i.texcoord.y-_YOffset)/_HeightRate); flow_uv.x/=2; flow_uv.x-= _Time.y *2; half flow = tex2D(_FlowTex,flow_uv).a; col.rgb+= half3(flow,flow,flow); } //----------------------------------------------- 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 } } } }
C#腳本:掛在UISprite上
using UnityEngine; using System.Collections; public class ScaleTexcoord : MonoBehaviour { private float widthRate; private float heightRate; private float xOffsetRate; private float yOffsetRate; private UISprite sprite; void Awake() { sprite = GetComponent<UISprite>(); widthRate = sprite.GetAtlasSprite().width * 1.0f / sprite.atlas.spriteMaterial.mainTexture.width; heightRate = sprite.GetAtlasSprite().height * 1.0f / sprite.atlas.spriteMaterial.mainTexture.height; xOffsetRate = sprite.GetAtlasSprite().x * 1.0f / sprite.atlas.spriteMaterial.mainTexture.width; yOffsetRate = (sprite.atlas.spriteMaterial.mainTexture.height-(sprite.GetAtlasSprite().y + sprite.GetAtlasSprite().height)) * 1.0f / sprite.atlas.spriteMaterial.mainTexture.height; } private void Start() { sprite.atlas.spriteMaterial.SetFloat("_WidthRate", widthRate); sprite.atlas.spriteMaterial.SetFloat("_HeightRate", heightRate); sprite.atlas.spriteMaterial.SetFloat("_XOffset", xOffsetRate); sprite.atlas.spriteMaterial.SetFloat("_YOffset", yOffsetRate); } }
測試一下:掛在主相機上
using UnityEngine; using System.Collections; public class test : MonoBehaviour { public UISprite sprite1; public UISprite sprite2; public UISprite sprite3; public Material default_mat; public Material mask1_mat; public Material mask2_mat; void OnGUI() { if(GUI.Button( new Rect(0,100,100,50),"過濾圖1")) { sprite1.atlas.spriteMaterial = mask1_mat; } if(GUI.Button( new Rect(110,100,100,50),"過濾圖2")) { sprite1.atlas.spriteMaterial = mask2_mat; } if(GUI.Button( new Rect(0,160,100,50),"變灰")) { sprite2.color = new Color(0,1,1); } if(GUI.Button( new Rect(110,160,100,50),"流光")) { sprite3.color = new Color(1,0,1); } } void OnDestroy() { sprite1.atlas.spriteMaterial = default_mat; } }
學習的腳步不能停~~~~~~~~~~~~~~~~~
需要我的測試工程,請留言。嘻嘻!
- 本文固定鏈接: http://www.shihuanjue.com/?p=305
- 轉載請注明: 喬 2016年01月19日 於 是幻覺 發表