zoukankan      html  css  js  c++  java
  • Shader实例:NGUI图集中的UISprite正确使用Shader的方法

    效果:

    变灰,过滤,流光 都是UI上常用效果。
    比如:
    1.按钮禁用时,变灰。
    2.一张Icon要应付圆形背景框,又要应付矩形背景框。就要使用过滤的方式来裁剪。
    避免了美术提供两张icon的麻烦,又节省了内存。
    3.流光,呃……,策划就是要,你能怎么办。

    实践:
    NGUI把要用到的图片做成了图集,它会记录每一张小图的信息。
    包括:每一张小图在这张图集里面的位置,长,宽,padding,border。等等。
    使用时只是采样这张小图所在区域,然后显示在UI的mesh上。
    如果我们用这张小图的texcoord,去采样另外一张图,采样到的就只是部分,就不是我们所希望那样(采样完整的图)。
    那么,只要把小图texcoord按照相应比例扩大,得到正确的texcoord即可。

    看一下t_sheyaonan在图集中的位置,Position(0,26) ,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;
        }
    }

    学习的脚步不能停~~~~~~~~~~~~~~~~~

    需要我的测试工程,请留言。嘻嘻!

  • 相关阅读:
    国产化硬件设备性能追踪
    遇到的 超时重传
    系统加载
    nginx 全景图 转载
    引擎国产化适配&重构笔记
    记录一次syn后只收到ack的情况 --timewait
    PCIe网卡查看工具
    短说 反向代理&透传代理如何关闭connect
    XDP/AF_XDP ? eBPF
    ipvs--eBPF转载
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5489836.html
Copyright © 2011-2022 走看看