unity UI shader:uv序列帧的实现——支持mask、rect mask 2d以及image的alpha

在内置shader(UI/default)基础上实现的循环序列帧效果。

说明:

  • [PerRendererData]
    只是修改Editor的显示行为的。
    当你通过MaterialPropertyBlock改变了某个Material的texture之后,只有加上了这个,才能在预览对应的Material面板上看到这个新texture。
  • Stencil(模版测试)mask组件实现原理
Stencil
{
     Ref [_Stencil]
     Comp [_StencilComp]
     Pass [_StencilOp]
     ReadMask [_StencilReadMask]
     WriteMask [_StencilWriteMask]
 }

这篇博客将的挺详细的
简单来说就是有个 每像素8bit的stencil buffer用来存放待比较的数值,将ref和buffer中的值(&ReadMask后)进行Comp比较,通过后执行pass操作(mask组件的操作是replace,将ref的值替换stencil buffer的值)。

  • ColorMask(R|G|B|A)通道遮罩
    输出指定通道的颜色,默认是15,即二进制的(1111);
  • shader中toggle的使用
    [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 1
  • UNITY_VERTEX_INPUT_INSTANCE_ID 和 UNITY_VERTEX_OUTPUT_STEREO: GPU instancing 所需
  • _TextureSampleAdd :Added for font color support
    This is set automatically by the engine based on whether the texture being used for the UI is in Alpha8 format or not. If it is, it’s set to (1,1,1,0), otherwise it’s (0,0,0,0).
    这个float4是由引擎去传值的。如果UI的tex是Alpha8 ,那么这个值就是 (1,1,1,0),否则就是(0,0,0,0).
  • UnityObjectToClipPos 坐标转换接口,就是以前的 mul(UNITY_MATRIX_MVP,v.vertex) 类似的还有UnityWorldToClipPosUnityViewToClipPos (头文件 #include “UnityCG.cginc” )
  • TRANSFORM_TEX
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的uv

  • UnityGet2DClipping
    判断一个点是否在矩形区域内,如果是返回的是1,否则返回0
inline float UnityGet2DClipping (in float2 position, in float4 clipRect)
{
    float2 inside = step(clipRect.xy, position.xy) * step(position.xy, clipRect.zw);
    return inside.x * inside.y;
}
//step(a, x)	Returns (x >= a) ? 1 : 0

注意:使用本shader,图片要设置为repeat模式(没有限制取值范围)。

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Custom/UVFrameAdditive"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

        _HorizontalAmount("Horizontal Amount", float) = 4    // 行数
        _VerticalAmount("Vertical Amount", float) = 4        // 列数
        _Speed("Speed", Range(1, 100)) = 30    // 播放速度

        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 1
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend SrcAlpha One
        ColorMask [_ColorMask]

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            #pragma multi_compile __ UNITY_UI_CLIP_RECT
            #pragma multi_compile __ UNITY_UI_ALPHACLIP

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            sampler2D _MainTex;
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;
            float4 _MainTex_ST;
            float _HorizontalAmount;
            float _VerticalAmount;
            float _Speed;

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                OUT.worldPosition = v.vertex;
                OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

                OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                OUT.color = v.color * _Color;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                float time = floor(_Time.y * _Speed);         //所经过的时间
                float row = floor(time / _HorizontalAmount);    // 第几行图片 (和行数不能对应起来)
                float column = (time - row * _HorizontalAmount) ; // 第几列图片

                //将所显示的图片缩放至应有的大小 (即一个关键帧图像的大小)
                half2 uv = float2(IN.texcoord.x /_HorizontalAmount, IN.texcoord.y / _VerticalAmount);

                uv.x += column / _HorizontalAmount; // 更换序列帧
                uv.y -= row / _VerticalAmount;      //等价于uv.y += 1.0 - row / 

                half4 color = (tex2D(_MainTex, uv) + _TextureSampleAdd) * IN.color;

                #ifdef UNITY_UI_CLIP_RECT
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif

                #ifdef UNITY_UI_ALPHACLIP
                clip (color.a - 0.001);
                #endif

                return color;
            }
        ENDCG
        }
    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值