Shader实例:NGUI图集中的UISprite正确使用Shader的方法

效果:

变灰,过滤,流光 都是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;
    }
}

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

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

时间: 2024-10-16 23:50:51

Shader实例:NGUI图集中的UISprite正确使用Shader的方法的相关文章

Shader实例:NGUI制作网格样式血条

效果: 思路: 1.算出正确的uv去采样过滤图,上一篇文章说的很明白了.Shader实例:NGUI图集中的UISprite正确使用Shader的方法 2.用当前血量占总血量的百分比来设置shader中的变量,来控制血条的裁剪. 实际操作中,在shader中声明一个uniform float _Factor 然后在C#脚本中,对这个变量进行设置,结果发现,界面上不能实时响应这个值,进行正确的裁剪. 那么我只好牺牲color的一个分量,比如设置g分量,shader中用g分量的值来对血条进行裁剪.最终

【OpenGL】Shader实例分析(七)- 雪花飘落效果

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40624603 研究了一个雪花飘落效果.感觉挺不错的.分享给大家,效果例如以下: 代码例如以下: Shader "shadertoy/Flakes" { // https://www.shadertoy.com/view/4d2Xzc Properties{ iMouse ("Mouse Pos", Vector) = (100,100,0,0) iChan

【OpenGL】Shader实例分析(六)- 卡牌特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/30989295 本文将介绍怎么通过alpha通道来隐藏信息,并实现卡牌特效.运行效果如下: 代码如下: Shader "stalendp/imageShine" { Properties { _MainTex ("image", 2D) = "white" {} _NoiseTex("noise", 2D) = &qu

【OpenGL】Shader实例分析(九)- AngryBots中的主角受伤特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一个非常棒的样例.非常有研究价值. 曾经研究的时候.因为其内容丰富,一时间不知道从哪入手写文章分析. 这一段时间研究shader技术比較多一些,就从shader的这一方面開始吧.首先分析当中的一个屏幕特效:当主角受到攻击时会出现的全屏效果(postScreenEffect).效果例如以下: 事实上这是一种的Bloom效果,相关文件有:M

Unity Shader 法线贴图的实现

这里有一个细节,关于法线贴图是有两个不同的空间的,如下: 切线空间:法线贴图颜色为偏蓝色 模型空间:法线贴图颜色为五颜六色 因此根据不同的空间变换位置方便一致计算. 1 // 法线贴图映射的编写+透明 2 Shader "TMoon/05-NormalMapAndAlpha" { 3 Properties{ 4 _Color("Color",Color) = (1,1,1,1) 5 _MainTex("Main Tex",2D) = "

unity shader序列帧动画代码,顺便吐槽一下unity shader系统

http://www.cnblogs.com/hellohuan/archive/2014/01/10/3512784.html 一.看到UNITY论坛里有些人求unity shader序列帧动画,写shader我擅长啊,就顺势写了个CG的shader.代码很简单,就是变换UV采样序列帧贴图,美术配置行数列数以及变换速度. Shader "HELLOHUAN/Hello_Sequence" { Properties { _Color ("Main Color", C

Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达到需要的效果.一个最常见的流程是. 1)创建一个材质 2)创建一个Unity Shader,并把它赋给上一步创建的材质 3)把材质赋给要渲染的对象 4)在材质面板中调整Unity Shader的属性,以得到满意的效果 下图显示了Unity Shader和材质是如何一起工作来控制物体的渲染的. Uni

TableViewCell reuse 重用 我认为的正确理解与使用方法

其实有点失望,因为用google搜索“uitableviewcell dequeueReusableCellWithIdentifier”出来一堆堆资深博主的文章.看了看,大部分都是在解决一个问题:使用重用时cell显示混乱的问题.该问题本身并不让我失望,失望的是博主们的解释. 首先,回顾一下UITableViewCell的重用,其基本逻辑就是tableView一开始会创建一屏幕的cell(如果有那么多)并把他们标记(Identifier),之后用户上下滑动tableView时,使用Identi

cocos2d-js Shader系列2:在cc.Sprite上使用Shader(黑白、灰度、造旧效果)

在Sprite中使用Shader做特殊的颜色处理比较简单,只需要把Shader程序绑定到Sprite上即可: sprite.shaderProgram = alphaTestShader; Cocos2d内置了一些Shader,详细可以看代码: 其中,CCShaderCache缓存了一些Shader实例,而GLProgram则对gl的api做了简单的封装让接口更友好. 需要注意的是,使用GLProgram编译shader程序时,cocos2d会自动加入了一些参数. _compileShader: