最近项目压力不大,抽时间看了些关于shader和游戏引擎的书籍,准备开始shader的学习。
在网上看到这位前辈(http://blog.sina.com.cn/s/articlelist_2312702844_6_1.html)写的博客,觉得很不错,学习曲线应该很适合自己,所以决定也从头一篇一篇每个shader自己实现一下,并加入自己的理解。今天就是调试的第一篇,很简单的逐帧动画shader。
这个shader的原理就是根据时间,变化uv的值,使得纹理映射时取的uv范围本应是0到1,变化为根据子图片数量切割成的区间。比如序列帧图片为两行四列,在纹理映射时,x和y的范围本应是0到1,但是经过处理,会变成在不同的时间段内,映射范围为不同的区间,比如x轴分别为0-0.25,0.25-0.50,0.50-0.75,0.75-1;y轴为0-0.5,0.5-1.这样,在不同的时间段内就可以取出对应的子图片。
Shader "Stutdy/1_FrameAnimation"
{Properties{_Color("Main Color", Color) = (1,1,1,1)_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}_SizeX("列", Float) = 4_SizeY("行", Float) = 2_Speed("播放速度", Float) = 150}SubShader{// 这里使用Unity3d自带光照模型Lambert// 不用做顶点处理,只需要一个表面处理函数surfCGPROGRAM#pragma surface surf Lambert alpha //开启Alpha透明// 声明参数fixed4 _Color;sampler2D _MainTex;uniform fixed _SizeX;uniform fixed _SizeY;uniform fixed _Speed;// 获取_MainTex的UV信息定义输入结构体struct Input{// 在贴图变量前加上uv表示提取uv值(二维坐标)float2 uv_MainTex;};void surf(Input IN, inout SurfaceOutput o){// 获取单元格UVfloat2 cellUV = float2(IN.uv_MainTex.x / _SizeX, IN.uv_MainTex.y / _SizeY); //这步首先把范围缩小为初始为0的区间// UV坐标值范围为0-1,获取单元格宽度float deltaX = 1 / _SizeX; // 每个区间宽度float deltaY = 1 / _SizeY; // 每个区间高度// 当前播放总索引int index = _Time * _Speed;// 求列索引int col = fmod(index, _SizeX);// 求行索引int row = fmod(index / _SizeX, _SizeY); //这步多加了取余数操作,可以循环播放动画// 原始UV + 当前格增量cellUV.x += col * deltaX; //确定x的区间cellUV.y += row * deltaY; //确定y的区间 // 创建tex2d(材质,uv)*主色fixed4 c = tex2D(_MainTex, cellUV) * _Color;// RGBo.Albedo = c.rgb;// 透明度o.Alpha = c.a;}ENDCG}
}
附上工程链接:http://download.csdn.net/detail/yinfourever/9563256