Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

序列帧动画

一、分析利用纹理坐标制作序列帧动画

  1. 关键点:
    1. UV坐标范围0~1,原点为图片左下角
    2. 图集序列帧动画播放顺序为从左到右,从上往下
  2. 分析问题
    1. 如何得到当前应该播放哪一帧动画?
    2. 如何将采样规则从0~1修改为在指定范围内采样
  3. 问题解决思路
    1. 用时间内置参数 _Time.y 参与计算得到具体哪一帧
      时间是不停增长的数值,用它对总帧数取余,便可以循环得到当前帧数
    2. 利用时间得到哪一帧后
      我们只需要从当前小图片中,采样开始位置,采样范围即可
      采样开始位置,可以利用当前帧和行列一起计算
      采样范围可以将0~1的范围 缩放转换到 小图范围内 ## 二、使用Shader实现序列帧动画 ### 1. 实现思路
  4. 属性声明、属性映射
    主纹理、图集行列、序列帧切换速度
  5. 透明Shader
    1. 设置渲染标签
      Tags{"RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True"}
    2. 关闭深度写入、开启混合
      • ZWrite off
      • Blend SrcAlpha OneMinusSrcAlpha
  6. 结构体
    只需要顶点坐标、纹理坐标
  7. 顶点着色器
    只需要顶点坐标转换、纹理坐标赋值
  8. 片元着色器
    1. 利用时间计算帧数
    2. 利用帧数计算当前 uv采样起始位置(得到小图uv起始位置)
    3. 计算uv缩放比例(将01转换到01/n)
    4. 进行uv偏移计算(在小图片格子中采样)
    5. 采样

2.实现示例

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
Shader "Unlit/FrameAnimation"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
//图集的行列
_Rows("Rows",int) = 8
_Columns("Columns",int) = 8
//切换动画速度的变量
_Speed("Speed",float) = 1.0
}
SubShader
{
//设置透明Shader
Tags { "RenderType"="Trasparent" "Queue" = "Transparent" "IngnoreProjector" = "True" }

Pass
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"


struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
//属性映射
sampler2D _MainTex;
int _Rows;
int _Columns;
float _Speed;
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
//得到当前帧 利用时间变量计算
float frameIndex = floor(_Time.y * _Speed) % (_Rows*_Columns);
//计算小图片 采样时的起始位置计算(列,行)
//除以对应的行列 目的是将行列值 转换为 0-1 范围内
//1 - (floor(frameIndex / _Columns) + 1) / _Rows
//+1 的目的是把格子左上角转化为格子的左下角
//1- 的目的是UV坐标的采样是从左下角开始
float2 frameUV = float2(frameIndex % _Columns / _Columns , 1 - (floor(frameIndex / _Columns) + 1) / _Rows);
//得到UV缩放比例 相当于从0-1的大图 映射到0~1/n的小图
float2 size = float2(1.0 / _Columns , 1.0 / _Rows);
//计算最终的UV坐标采样信息
//乘以size 相当于把0~1范围 缩放到了 0~1/n范围内
//再加上frameUV 相当于把采样的起始位置 移动到了对应的小格子的起始位置
float2 uv = i.uv * size + frameUV;
return tex2D(_MainTex, uv);
}
ENDCG
}
}
}

评论