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;
        }
    }

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

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

  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5489836.html
Copyright © 2011-2022 走看看