观前提示,写的比较啰嗦,能查到的信息都贴了一遍,主要是复习一下
效果如图
原理:
通过贝塞尔曲线世界空间位置生成一张RGBAHalf的asset文件儿,
在shader顶点着色器中采样颜色图片,获得偏移信息,再乘模型大小,
可以得到固定角度翻转的翻页效果.
相对矩阵计算的简单,但比GUI翻转的效果单一
x的偏移值为0时(初始状态),面片的形态与曲线一致,下文中把坐标转换到模型空间中,所以曲线的位移不影响面片的形态
详解:
1,需要绘制一条贝塞尔曲线,大概这个形状,因为我这个是需要从右往左翻,所以x-,y+,z-(这里是相对于坐标轴来理解的,实际上还有uv翻转的影响,比如我这个就不是x-,因为我的uv有翻转,具体细节需要自己去测试)
三阶贝塞尔曲线(三次贝塞尔方程 参考资料【Unity3d游戏开发】游戏中的贝塞尔曲线以及其在Unity中的实现 - 马三小伙儿 - 博客园)
我用的是一个插件,类似ps的钢笔工具,每两个点之间是一个三阶贝塞尔曲线
2,通过代码导出点的偏移位置
保存格式,RGBAHalf格式,Asset(我存的png,只取了0-1区间,大坑),
Texture2D tex = new Texture2D(sampleValue, 1, TextureFormat.RGBAHalf, false, false);
曲线需要取样数来输出图片,我这个是取样64次在for循环中除64就可.
由于我们的位置是在世界空间中取到的,需要把它放进模型空间中,做自身的偏移,否则可能导致翻页翻着翻着书走远了
转模型空间(不能应用全部情况)
//采样数
public int m_splineSamlpeValue = 64;
//起始位置,t=0时
Vector3 srcPos = spline.GetPoint(0);
for (int i = 0; i < sampleValue; i++)
{
float sv = i / (float)sampleValue;
//每一个采样位置归一化处理,
Vector3 p = (spline.GetPoint(sv) - srcPos) / length;
Vector3 ps = new Vector3(i / (float)sampleValue, 0, 0);
//模型空间偏移值
Vector3 offset = p - ps;
//根据位置写出一张图片儿
tex.SetPixel(i, 0, new Color(offset.x, offset.y, offset.z, 1.0f));
}
public Vector3 GetPoint(float t)
{
//贝塞尔曲线计算
}
当处于任意时间t上,p与ps的偏移值如图
3,shader绘制
_MainTex ("Texture", 2D) = "white" {}
//采样的颜色图
_SrcTex("SrcTex",2D) = "white"{}
//收缩程度
_Shrink("shrink",Range(-2,1))=0.3
//我这里翻转了uv,固定y轴,移动x,0.26是x的放大值控制倾斜程度
float2 offsetUV = 1-v.uv-float2(v.uv.y, 0)*0.26;
offsetUV.x += _Shrink;
//采样颜色图片
float3 offset = tex2Dlod(_SrcTex,float4(offsetUV.x, 0, 0, 0)).rgb;
//200是模型参数
v.vertex.x += offset.x * 200;
v.vertex.y+= offset.y*_YY * 100;
v.vertex.z+=offset.z/3*100;
4,当预制体显示给材质球设置参数(自动播放)
if (this.gameObject.activeInHierarchy == true)
{
pos = this.gameObject.GetComponent<Renderer>().material.GetFloat ("_Shrink");
if (pos>-1.31)
{
float finalPos = pos - Time.deltaTime * speed;
this.gameObject.GetComponent<Renderer>().material.SetFloat("_Shrink",finalPos);
}
else{}
}