原图
思路, 按行与列,根据时间在uv中依次取样对应的小图进行渲染即可。
效果
实现
Shader "Custom/ImageSquenceAnimation" {
Properties {
_Color ("Color", Color) = (1,1,1,1) //颜色修正
_MainTex("Image", 2D) = "white"{} //帧动画主图
_HorizontalAmount ("_HorizontalAmount",Float) = 8 //帧动画横向图片张数
_VerticalAmount ("_VerticalAmount", Float) = 8 //帧动画纵向图片张数
_Speed ("Speed", Range(2,400)) = 40 //播放速度
}
SubShader {
//由于包含了透明通道, 因此使用 半透明的标配 ——> 队列设置为半透明,渲染类型设置半透明, 忽视投射
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"= "Transparent" }
Pass{
Tags { "LightMode" = "ForwardBase" }//前向渲染
ZWrite Off //深度写入关闭
Blend SrcAlpha OneMinusSrcAlpha //透明度混合
CGPROGRAM
//引入函数,定义函数
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
//设置变量的类型
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _HorizontalAmount;
float _VerticalAmount;
float _Speed;
//v f 结构体定义
struct a2v {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
//顶点函数中,转换裁剪空间, 读取图片uv信息
v2f vert (a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX( v.texcoord, _MainTex);//计算uv信息
return o;
};
fixed4 frag ( v2f i) : SV_Target{
float time = floor(_Time.y * _Speed );// 计算当前时间
float row = floor( time/_HorizontalAmount);//根据时间计算当前行索引
float column = time - row * _HorizontalAmount; //根据时间计算当前列索引
half2 uv = i.uv + half2(column, -row);//先计算出整体的uv位置, 前面的逐顶点的小数点(范围是0-1),加上后面当前的偏移量(整数,1-8,代表当前处于纹理中的位置),
uv.x /= _HorizontalAmount;//按比例缩放uv坐标的x轴
uv.y /= _VerticalAmount;//按比例缩放uv坐标的y轴
//上面的思路来看, 假定column, row,都是定值, 比如 3,5, 也就是要取样 第3行,第5列的小图
//这时候 顶点片元中处理的uv, 是0-1,
// uv.x = ( 3.0 + (0-1)) / 8 = ( 0.375 - 0.5)
// uv.y = ( 5.0 + (0-1)) /8 = ( 0.625 - 0.75)
// 这两个值在 大图中的位置, 就对应了两个区间, 也就是需要取样的小图的区间
fixed4 c = tex2D (_MainTex,uv );//纹理取样
c.rgb *= _Color.rgb;
return c;
};
ENDCG
}
}
FallBack "Diffuse"
}