Unity Shader入门教程(十五):纹理动画
发表于2018-06-07
在游戏中对于纹理动画的使用是非常多的,尤其是在各种资源都比较局限的移动平台上,我们往往会使用纹理动画来代替复杂的粒子系统等模拟各种动画效果。


一、序列帧实现爆炸效果
1、思路
使用一个nXn的序列图,通过floor操作;
每隔一段时间改变一次time,替换当前展示的单元图,计算uv时,先将顶点着色器中传入的uv映射到单元图的uv格子中;
再将映射好的uv映射到正确行、列上;
最后对纹理采样输出。
2、代码实践
Shader "Custom/Edu/ImgSeqAnim" {
Properties {
_MainTex("Main Tex",2D) = "white"{}
_HAmount("HAmount",float) = 8
_VAmount("VAmount",float) = 8
_Speed("Speed",Range(1,100)) =30
_Color("Color Tint",Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType"="Opaque" }
Pass
{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
half _HAmount;
half _VAmount;
half _Speed;
fixed4 _Color;
struct a2v
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv = v.texcoord;
return o;
}
fixed4 frag(v2f i):SV_Target
{
//这里要对时间取整!!!
//错误写法
//half time = _Time.y * _Speed;
//导致的后果是前后图片横向滑动而不是隔一段时间替换一次
half time = floor(_Time.y * _Speed);
half row = floor(time/_HAmount);
half column = time - row * _HAmount;
//将当前uv点映射到更小的单元序列图像上
half2 uv = half2(i.uv.x/_HAmount,i.uv.y/_VAmount);
//将当前uv映射到正确的序列图上
uv.x += column/_HAmount;
//Unity中纹理坐标的竖直方向上从下到上递增
//而序列帧纹理的播放顺序是从上到下的
uv.y -= row/_VAmount;
return tex2D(_MainTex,uv) * _Color;
}
ENDCG
}
}
FallBack "
3、效果图

二、滚动背景效果实现
1、基本思路
随着时间连续的横向改变采样的uv坐标,又结合前景与后景做不同的滚动速率以达到更加真实的背景效果。
2、代码实践
Shader "Custom/Edu/BgSroll" {
Properties {
_FrontTex("前景",2D) = "white"{}
_BackTex("后景",2D) = "white"{}
_ScrollSpeed1("前景滚动速度",Range(-10,10)) =1.0
_ScrollSpeed2("后景滚动速度",Range(-10,10)) =1.0
}
SubShader {
Tags { "RenderType"="BackGround" "Queue" = "BackGround"}
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _FrontTex;
float4 _FrontTex_ST;
sampler2D _BackTex;
float4 _BackTex_ST;
half _ScrollSpeed1;
half _ScrollSpeed2;
struct a2v
{
float4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
};
struct v2f
{
float4 pos:SV_POSITION;
float4 uv:TEXCOORD0;
};
v2f vert(a2v v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv.xy = TRANSFORM_TEX(v.texcoord,_FrontTex);
//frac函数将会截获取得各个分量的小数部分
o.uv.xy += frac(float2(_ScrollSpeed1*_Time.y,0.0));
o.uv.zw = TRANSFORM_TEX(v.texcoord,_BackTex);
o.uv.zw += frac(float2(_ScrollSpeed2*_Time.y,0.0));
return o;
}
fixed4 frag(v2f i):SV_Target
{
fixed4 frontColor = tex2D(_FrontTex,i.uv.xy);
fixed4 backColor = tex2D(_BackTex,i.uv.zw);
return lerp(backColor,frontColor,frontColor.a);
}
ENDCG
}
}
FallBack "Diffuse"
}
3、效果图

Unity Shader入门教程:
(一)渲染流水线
(二)数学知识
(四)光照模型理论
(七)基础纹理之单张纹理
(八)基础纹理之凹凸映射
(十)透明效果(上)
(十一)透明效果(下)
(十二)渲染路径与光源类型
(十三)立方体纹理
(十四)渲染纹理
(十六)顶点动画
(十七)均值模糊与高斯模糊
(十八)卷积与边缘检测
(十九)运动模糊
(二十)深度纹理和法线纹理
