1.前面的心情
上班看shader我也是醉了。写完这篇看代码去了,不过看着看着恐怕就会困....
还有就是上天,我该怎么做,下一步,大懒;
2.参考源头
http://blog.csdn.net/candycat1992/article/details/18662601
http://www.cppblog.com/lai3d/archive/2008/10/23/64889.html
群里问大神
3.实现效果和代码
实现效果:猴子的animation动画;16张小图顺序变化;但由于此图并未对齐,结果不理想,没有人行走的那张效果好
代码:两部分,1.cs部分,实现时间time,获取每张小图的x、y的index下标,并传入shader值, 2.shader中根据index下标,偏移值,来计算一种映射关系,使(0,0)-(1,1,)映射到每个小块上;
(1).cs部分:
public class AnimationTest : MonoBehaviour { public float speed = 5.0f; public int _CellAmountX = 8; float timeValue = 0.0f; float timeOffsetY = 0.0f; private bool bIsUp_Bottom = true; void Start () { transform.renderer.material.SetFloat("_CellAmountX", _CellAmountX); } // Update is called once per frame void FixedUpdate () { timeValue = Mathf.Ceil(Time.time * speed % _CellAmountX); Debug.Log("timeValue:" + timeValue);//上log图,显示x的index if (timeValue==_CellAmountX) { if (bIsUp_Bottom) { timeOffsetY = Mathf.Abs(timeOffsetY - 1.0f);//当达到x最右侧,进行上下Y的index切换 } bIsUp_Bottom = false; } else { bIsUp_Bottom = true; } transform.renderer.material.SetFloat("_TimeValue", timeValue); transform.renderer.material.SetFloat("_TimeOffsetY", timeOffsetY); } }
(2).shader部分,进行纹理坐标的映射关系;
Shader "Custom/AnimateSprites" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} // Create the properties below _CellAmountX ("Cell Amount", float) = 8 _TimeValue ("Time Value", float) = 0.0 _TimeOffsetY("_TimeOffsetY",float ) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; //Create the connection to the properties inside of the //CG program float _CellAmountX; float _TimeValue; float _TimeOffsetY; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { //Lets store our UVs in a seperate variable float2 spriteUV = IN.uv_MainTex; //Lets calculate the width of a singe cell in our //sprite sheet and get a uv percentage that each cel takes up. float cellUVPercentage = 1.0/_CellAmountX; //Animate the uv's forward by the width precentage of //each cell float xValue = spriteUV.x; xValue += _TimeValue; xValue *= cellUVPercentage; float cellUVPercentage_Y = 1.0/2.0f; float yValue = spriteUV.y; yValue += _TimeOffsetY; yValue*=cellUVPercentage_Y; spriteUV = float2(xValue, yValue); half4 c = tex2D (_MainTex, spriteUV); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
4.学到什么:
(1). shader内置函数
float timeVal = fmod(_Time.y * _Speed, _CellAmount);
fmod : 带小数的余数
fmod fmod(x, y)Returns the floating point remainder of x/y. remainder余数
ceil(x) Returns the smallest integer which is greater than or equal to x.
其实从字面意思也好理解: ceil天花板 floor地板
(2)、纹理映射关系;
首先:考虑书中第一个图例子,小人的走动:9个小人,纹理0-1根据时间映射到(0-1/9);(1/9-2/9);............(8/9,1);
(0+index)/9----> index分别为0,1,2到9,到9的话,其实是(0-1/9);而从前面log图看出,当index为0是非常少的次数,这是因为ceil的原因导致的;也就是说,其实第一张图片的显示时间要多几帧。
(1+index)/9---->
其次:猴子那张图
x还是那个x;y和x类似,判断的时候,在cs文件里,进行y的一个跳变;
(3)cs和shader的数据关联
transform.renderer.material.SetFloat("_CellAmount", cellAmount);
(4)心得;
昨天在shader群里被蓝色大神教会一番:
把内置函数都看看;
主要是第一个教诲,路好长好远;