参考文献:《unity shader入门精要》
纹理动画
序列帧动画
Shader "Unlit/Chapter11-ImageSequenceAnimation"
{
Properties
{
_Color("Color Tint", Color) = (1,1,1,1)
_MainTex("Image Sequence",2D) = "white" {}
_HorizontalAmount("Horizontal Amount",Float)=4 //水平方向包含的关键帧图像的个数
_VerticalAmount("Vertical Amount",Float)=4 //竖直方向包含的关键帧图像的个数
_Speed("Speed",Range(1,100))=30
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass
{
Tags { "LightMode"="ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _HorizontalAmount;
float _VerticalAmount;
float _Speed;
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=UnityObjectToClipPos(v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex); //存储顶点纹理坐标
return o;
}
/*
要播放帧动画,需要计算出每个时刻需要播放的关键帧在纹理中的位置,也就是该关键帧所在的行列索引数
*/
fixed4 frag(v2f i):SV_Target{
float time=floor(_Time.y*_Speed); //_Time.y是自该场景加载以来所经过的时间,和速度相乘来得到模拟的时间(floor函数是对结果取整)
float row=floor(time/_HorizontalAmount); //得到行索引
float column=time-row*_HorizontalAmount; //得到列索引
half2 uv=i.uv+half2(column,-row); //将原纹理按行列数等分,得到每个子图像的纹理坐标范围
//使用当前行列数对上面的结果进行偏移,得到当前子图像的纹理坐标
uv.x/=_HorizontalAmount;
uv.y/=_VerticalAmount;
fixed4 c=tex2D(_MainTex,uv);
c.rgb*=_Color;
return c;
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
滚动的背景
Shader "Unlit/Chapter11-ScrollingBackground"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_DetailTex("2nd Later (RGB)", 2D) = "white" {}
_ScrollX("Base layer Scroll Speed", Float) = 1.0
_Scroll2X("2nd layer Scroll Speed",Float) = 1.0
_Multiplier("Layer Multiplier",Float)=1
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass
{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex; //较远的背景纹理
sampler2D _DetailTex; //较近的背景纹理
float4 _MainTex_ST;
float4 _DetailTex_ST;
float _ScrollX; //对应较远背景纹理的滚动速度
float _Scroll2X; //对应较近背景纹理的滚动速度
float _Multiplier; //控制纹理的整体亮度
struct a2v{
float4 vertex:POSITION;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float4 uv:TEXCOORD0;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
/*
利用TRANSFORM_TEX来得到初始的纹理坐标,然后利用Time.y来在水平方向上进行平移,
以此来达到滚动的效果
*/
o.uv.xy=TRANSFORM_TEX(v.texcoord,_MainTex)+frac(float2(_ScrollX,0.0)*_Time.y);
o.uv.zw=TRANSFORM_TEX(v.texcoord,_DetailTex)+frac(float2(_Scroll2X,0.0)*_Time.y);
return o;
}
fixed4 frag (v2f i):SV_Target{
//对两层背景纹理进行采样
fixed4 firstLayer=tex2D(_MainTex,i.uv.xy);
fixed4 secondLayer=tex2D(_DetailTex,i.uv.zw);
//使用lerp函数来用第二层纹理的透明通道来混合两张纹理
fixed4 c=lerp(firstLayer,secondLayer,secondLayer.a);
c.rgb*=_Multiplier;
return c;
}
ENDCG
}
}
FallBack "VertexLit"
}
顶点动画
流动的河流
Shader "Unlit/Chapter11-Water"
{
Properties
{
_MainTex ("Main Tex", 2D) = "white" {} //河流纹理
_Color("Color Tint", Color)=(1,1,1,1) //控制整体颜色
_Magnitude("Distortion Magnitude", Float)=1 //控制水流波动幅度
_Frequency("Distortion Frequency",Float)=1 //控制波动的频率
_InvWaveLength("Distortion Inverse Wave Length",FLoat)=10 //控制波长的倒数
_Speed("Speed",FLoat)=0.5 //控制河流纹理的移动速度
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True" }
Pass
{
Tags{"LightMode"="ForwardBase"}
//开启深度写入,开启混合模式,关闭剔除功能,为了让水流的每个面都能显示
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
struct a2v{
float4 vertex:POSITION;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(a2v v){
v2f o;
//首先计算顶点位移量
float4 offset;
offset.yzw=float3(0.0,0.0,0.0);
//x方向做正弦位移,利用_Frequency和_Time.y来控制正弦函数的频率,一个正弦函数
offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
//offset.x=sin(_Frequency*_Time.y+v.vertex.x*_InvWaveLength+v.vertex.y*_InvWaveLength+v.vertex.z*_InvWaveLength)*_Magnitude;
o.pos=UnityObjectToClipPos(v.vertex+offset);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv+=float2(0.0,_Time.y*_Speed);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed4 c=tex2D(_MainTex,i.uv);
c.rgb*=_Color.rgb;
return c;
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}