[Shader]对NGUI的UISprite和UITexture进行裁剪

由于最近比较忙,所以很多我在其它地方发布的博文都没有同步到这里。我会在后面慢慢重新补回来。对各位关注我博客的读者也表示抱歉!


版权所有,转载须注明出处!
喜欢火影、喜欢Java、喜欢unity3D、喜欢游戏开发的都可以加入木叶村Q群:379076227


0、随便聊

本人真正学习Shader的时间莫过于今年春节在家的两天时间,虽然短短两天。但是已经深深喜欢上Shader。深受其魅力吸引。
但是平常主要做的还是服务端和客户端的开发,偏逻辑向。所以好久也没碰Shader了。
但是昨天在一个群里有人讨论NGUI不能对Sprite进行裁剪。比如把一个方形的,显示成一个圆形的。如下图:

这个应该是挺常见的,或许你会说,美术直接帮你裁成圆的不就可以吗。有时候可以,有时候不行。什么时候不行呢?当你在游戏中有些地方使用方形的,有些地方使用圆形的。这时候就不能让美术帮你裁了。不然不就有两份资源了。

本文读者最好已经知道怎么使用NGUI创建图集,使用它的UISprite和UITexture。

本文编写测试环境为:
系统:Win7 X64引擎:Unity3D V4.3.3

插件:NGUI 3.5.7


1、开始动手

作为一个学习过两天Shader的人,我觉得,这应该难不倒我。因此,我立马在U3D的Project面板中噼里啪啦一阵狂搞。创建一个Shader。


2、编写第一版Shader。

双击我们上面创建的Shader。因为这个是给NGUI用的。然后我就依照NGUI的Shader命名,给我们的Shader命名为:Unlit/Transparent Colored Mask
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。

然后选择一个材质。用上我们上面的Shader。然后设置一个Mask。

这个Mask图片为

可以看到Alpha通道里面是一个白色的圆圈。
记得这个Mask图片的导入设置如下:

那么可以看看运行效果:


3、欢呼,庆祝?

貌似一切都挺顺利的。但是这个Shader能否对UISprite起效果呢?
我们来试试。
随便搞个图集。然后加个UISprite,

然后修改这个图集的材质使用我们的Shader。

额。。。效果咋成下面这样啦。。。不太对的赶脚


4、停一停想一想

难道这是NGUI的bug。。。啊!!!啊!!!!!
不行,我要想想看
。。。。。。。。。
1分钟过去了。
为什么col.a = col.a * tex2D(_Mask, i.texcoord).a这个公式对Sprite的效果是错误的呢。
难道i.texcoord的范围不是0~1.
这么一想,倒好像也有点道理。因为NGUI把要用到的图片做成了图集。因此,每次只是取图集中的一小个区域显示到UI的Mesh上。
那么,我只要把i.texcoord的范围重新映射到0~1。然后用于取Mask上面的颜色,不就OK了吗?
机智的我立马动起手来。

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

好了。那么怎么使用这个Shader。我们需要多一个脚本来设置这个shader的参数。

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

只要把这个脚本附在UISprite上即可。

可以发现现在正常了。NGUI图集的材质变成了

好了。这次真的可以好好庆祝下啦~~

整个效果其实只用上面的Shader和那个ScaleTexcoord.cs即可。

时间: 2024-10-06 23:27:01

[Shader]对NGUI的UISprite和UITexture进行裁剪的相关文章

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

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

unity游戏开发之NGUI的UISprite染色

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,我们致力于打造业内unity3d培训.学习第一品牌. 游戏的UI开发中经常会遇到染色问题.例如按钮失效变灰的效果,同一个道具通过策划表配的颜色值染上红绿蓝紫等颜色,效果如下 最笨最挫的方法当然是让美术多出几个资源图,这样的一个缺点是浪费资源,在手游上资源的大小显得尤为重要.而且不好维护和复用,修改一个资源需要同时修改其他颜色的多个同类资源.一种比较

NGUI-UISprite

今天做了一个得分板的效果,看图 结构 对应的依次是 个位 十位 百位 千位 写脚本: using UnityEngine; using System.Collections; using System; public class Number : MonoBehaviour { private UISprite[] sprites; private UIAtlas traceAtlas; public int num=0; // Use this for initialization void

NGUI的UISprite动态染色的一种方法

本文主要参考iwinterice 的 NGUI的UISprite动态染色的一种解决方案 文章. 参考参考,就是既参详又拷贝,-,-||| 相关理论依据,还请去移步 NGUI的UISprite动态染色的一种解决方案 里面去寻找.我这里只有提供一下源码,并对原博文进行了一点点修改,至于修改后的好坏,俺也不知道咯. 首先阐明一下需求,就是几个角色,打怪,扫怪,头像一直blingbling的闪,但是,duang,血量爆掉了,角色挂了,头像就得死灰死灰的样子了. 原博文是去改了UISprite的源码,虽然

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

效果: 变灰,过滤,流光 都是UI上常用效果. 比如: 1.按钮禁用时,变灰. 2.一张Icon要应付圆形背景框,又要应付矩形背景框.就要使用过滤的方式来裁剪. 避免了美术提供两张icon的麻烦,又节省了内存. 3.流光,呃……,策划就是要,你能怎么办. 实践: NGUI把要用到的图片做成了图集,它会记录每一张小图的信息. 包括:每一张小图在这张图集里面的位置,长,宽,padding,border.等等. 使用时只是采样这张小图所在区域,然后显示在UI的mesh上. 如果我们用这张小图的texc

(NGUI)UISprite 切换图集

UISprite是可以使用代码动态切换图集的 using UnityEngine; using System.Collections; public class SpriteAtlasTest : MonoBehaviour { private UISprite _sprite; public UIAtlas atlas; public UIAtlas atlas2; // Use this for initialization void Start () { _sprite = GetComp

NGUI与EasyTouch结合使用

用了EasyTouch插件一段时间了,小问题还是有一些,总体来说用起来还行.这篇文章我就来说说EasyTouch和NGUI的结合. 总体来说触摸屏幕也就三种情况. 1.触摸事件只响应NGUI部分,不响应3D部分. 2.触摸事件只响应3D部分,不响应NGUI部分. 3.触摸事件同时响应. 举个例子,在战斗场景我们希望通过手指滑动来控制摄像机的旋转.但是这时屏幕上可能还有一些UI的按钮,但是我们不希望用户点击UI按钮也影响到了摄像机的旋转.所以此时我们只希望触摸事件在3D部分响应. 1. 如下图所示

Unity3D 灰度shader(改编自NGUI)

原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 QQ群:[119706192] 本文链接地址: 灰度shader 废话不多说,直接图解流程: 1.原图 2.改动shader 打开NGUI自带的shader:(Unlit - Transparent Colored) 将代码A: fixed4 frag (v2f i) : COLOR { fixed4 col = tex2D(_MainTex, i.texcoord) * i.color; return col; } 改为代码B: f

unity3D游戏开发十四之NGUI一

转:http://blog.csdn.net/kuloveyouwei/article/details/23676039 在Unity中,可以使用代码控制其自身所携带的GUI来实现图形界面的搭建.但是这些组件的搭建效率很低,而且已经无法满足现在市场对图形用户界面美感的要求,所以,引入了NGUI来增加所要开发的图形用户界面的美感.NGUI是一个功能强大的UI系统,其事件处理通常由开发人员编写C#脚本完成,并且是一个严格遵循KISS原则的Unity框架,该框架具有干净.简约的代码. 现在NGUI的各