• ShaderLab实现序列帧动画


    序列帧动画介绍

    序列帧动画的原理比较简单,依次播放一系列关键帧图像,当播放速度达到一定数值时,看起来就是一个连续的动画。
    序列帧动画有很多实现方式,而通过Shader来实现是性能比较好的一种,是由GPU来进行计算。
    效果如下

    请添加图片描述

    我们使用一张8x8的纹理图片来实现帧动画
    请添加图片描述

    步骤

    1、在场景中新建一个Quad;
    2、然后再创建一个材质,命名为SequenceAnimation,把材质拖到Quad上;
    3、再创建一个Shader文件,命名为SequenceAnimation,把Shader拖到上面的材质上
    在这里插入图片描述

    Shader程序

    Shader1 通过单帧来控制图像显示

    Shader "Unlit/SequenceAnimationFrame"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}//贴图
            _Color("Color", Color) = (1, 1, 1, 1)   // 颜色
             _HorizontalAmount("Horizontal Amount", float) = 8 // 行数
             _VerticalAmount("Vertical Amount", float) = 8  // 列数
             _Frame("Frame", Range(1, 100)) = 30 // 播放到多少帧
        }
        SubShader
        {
    //        由于序列帧图像通常包含了透明通道,因此可以被当成是一个半透明对象。
    //        在这里我们使用半透明的“标配”来设置它的SubShader标签,即把Queue和RenderType设置成Transparent,把IgnoreProjector设置为True
           Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"  }
            LOD 100
    
            Pass
            {
    //            使用Blend命令来开启并设置混合模式,同时关闭了深度写入
                Tags{"LightMode"="ForwardBase"}
                 ZWrite Off
                 Blend SrcAlpha OneMinusSrcAlpha
                
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
               
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                fixed4 _Color;
                float _HorizontalAmount;
                float _VerticalAmount;
                float _Frame;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    // sample the texture
                    float y = floor(_Frame/_HorizontalAmount);
                    float x = _Frame-y*_VerticalAmount;
                    half2 uv = i.uv+half2(x,-y);
                    uv.x /= _HorizontalAmount;
                    uv.y/=_VerticalAmount;
                    fixed4 col = tex2D(_MainTex, uv);
                    return col;
                }
                ENDCG
            }
        }
              FallBack  "Transparent/VertexLit"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    _Frame为第几帧。_HorizontalAmount代表有多少行,_VerticalAmount代表有多少列。

    y轴偏移:由帧数除以行数,并向下取整获得。由于UV坐标原点在坐下角,而序列帧图是从左上角开始计算,所以下面计算y时要取反。y=-floor(_Frame/_HorizontalAmount)

    x轴偏移:由_Frame作为被减数,减去上面计算的y与列数的乘积:x=_Frame-y*_VerticalAmount。这里自己可以推到一下。
    当帧数_Frame为0,1,2,3,4,5,6,7时,y值为0,而x的值为0,1,2,3,4,5,6,7,获得第一行的帧动画,
    当帧数_Frame为8,9,10…15时,此时y的值为1,x依然为0到7,获得第二行的帧动画。

    这里可以拖动Frame的滑动条查看不同帧实现的效果。
    在这里插入图片描述

    Shader2 加入时间,自动播放帧动画

    Shader "Unlit/zhenDongHua"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}//贴图
            _Color("Color", Color) = (1, 1, 1, 1)   // 颜色
             _HorizontalAmount("Horizontal Amount", float) = 8 // 行数
             _VerticalAmount("Vertical Amount", float) = 8  // 列数
             _Speed("Speed", Range(1, 100)) = 30 // 播放速度
        }
        SubShader
        {
        
           Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"  }
            LOD 100
    
            Pass
            {
                Tags{"LightMode"="ForwardBase"}
                 ZWrite Off
                 Blend SrcAlpha OneMinusSrcAlpha
                
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
               
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                fixed4 _Color;
                float _HorizontalAmount;
                float _VerticalAmount;
                float _Speed;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    // 就是自该场景加载后所经过的时间,_Time.y和_Speed相乘得到模拟的时间,可控制帧动画播放速度
                    float time = floor(_Time.y*_Speed);
                    float y = floor(time/_HorizontalAmount);
                    float x = time-y*_VerticalAmount;
                    half2 uv = i.uv+half2(x,-y);
                    uv.x /= _HorizontalAmount;
                    uv.y/=_VerticalAmount;
                    fixed4 col = tex2D(_MainTex, uv);
                    return col;
                }
                ENDCG
            }
        }
              FallBack  "Transparent/VertexLit"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    这里调整Speed的值,可控制动画的播放速度。
    在这里插入图片描述

    获取源码

    公众号,回复shader,获取源码

  • 相关阅读:
    轻松实现文件按大小归类保存,高效管理你的文件库!
    1053 Path of Equal Weight
    【直播回顾】战码先锋首期8节直播完美落幕,下期敬请期待!
    AJAX的Promise(原理)
    【观察】数字化转型的“下半场”,华为加速行业智能化升级
    Asp .Net Core 系列:详解鉴权(身份验证)以及实现 Cookie、JWT、自定义三种鉴权 (含源码解析)
    微服务架构
    01-http概述
    MongoDB聚合运算符:$week
    专访中欧财富伍春兰:财富管理行业数字化转型升级,数据库如何选型?
  • 原文地址:https://blog.csdn.net/u014196765/article/details/128144257