本文已参与[新人创作礼]活动,一起开启掘金创作之路
原理简述: 在物体顶点着色器中控制顶点旋转,并且通过正弦函数控制每一页书的弯曲程度,因为每一页书正反面是不一样的,因此要用两个Pass去渲染正反面。
后续可以加一个C#脚本去控制页签何时翻页。
Shader "ShaderPath/OpenBookShader"//shader的选择路径
{
Properties {
//正面纹理
_MainTex ("Texture", 2D) = "white" {}
//背面纹理
_SecTex("SecTex",2D)="White"{}
//旋转角度
_Angle("Angle",Range(0,180))=0
//转速
_Speed("_Speed", float) =3
//波长
_WaveLength("WaveLength",Range(-1,1))=0
}
CGINCLUDE
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _SecTex;
float4 _SecTex_ST;
//角度
float _Angle;
//转速
float _Speed;
//波长
float _WaveLength;
v2f vert (appdata v)
{
v2f o;
//旋转之前向右偏移5个单位(Unity自带的plane网格是10*10的)
v.vertex -= float4(5,0,0,0);
float s;
float c;
//通过该方法可以计算出该角度的正余弦值
sincos(radians((_Angle+_Time.y*_Speed)%180),s,c);
//旋转矩阵(绕
float4x4 rotateMatrix={
c ,s,0,0,
-s,c,0,0,
0 ,0,1,0,
0 ,0,0,1 };
//根据x坐标,通过正弦函数计算出 y坐标的正弦值, _WaveLength 控制波长, 振幅就跟随角度正弦值动态变化
v.vertex.y = sin(v.vertex.x*_WaveLength) * s ;
//顶点左乘以旋转矩阵
v.vertex = mul(rotateMatrix,v.vertex);
//旋转之后偏移回来(这样可以让物体的中心不发生偏移)
v.vertex += float4(5,0,0,0);
//模型空间转换到裁剪空间
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag1 (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
fixed4 frag2 (v2f i) : SV_Target
{
fixed4 col = tex2D(_SecTex, i.uv);
return col;
}
ENDCG
SubShader
{
Pass
{
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag1
#include "UnityCG.cginc"
ENDCG
}
Pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag2
#include "UnityCG.cginc"
ENDCG
}
}
}
下面是关于Z轴旋转的四位齐次坐标矩阵,详细可以去看我之前整理的一些基础知识
坐标的基础知识
最后是效果图,配上翻页的音效就更棒了!