三十年河东,三十年河西|

自动机

园龄:1年10个月粉丝:2关注:4

Shader实现翻书效果

原理

翻书这个过程可以看成是平面上的点都绕z轴旋转,但是直接这样写的话会出现问题。因为旋转轴是在中间的,所以我们在旋转之前要把点向左偏移5个单位这样旋转轴就到了最左边,然后再乘上旋转矩阵得到旋转之后的位置,再向右边偏移5个单位还原一下。这样实现的太生硬了,所以带入正弦函数改变一下顶点的高度,让书页有点弧度。需要注意的是Plane默认是单面的,所以在渲染的时候要双面渲染,不然背面是透明的。

代码

Shader "Custom/Test"
{
	Properties {
		_MainTex("Main Tex", 2D) = "white"{}
        _SecTex("Sec Tex", 2D) = "white"{}
        _Angle("Angle", range(0, 180)) = 0
        _WaveLength("WaveLength", range(-1, 1)) = 1
	}
	SubShader {
       Pass
       {
           Cull Back
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #include "Lighting.cginc"
           
           sampler2D _MainTex;
           float4 _MainTex_ST;
           float _Angle;
           float _WaveLength;
           struct a2v
           {
               float4 vertex : POSITION;
               float4 texcoord : TEXCOORD0;
           };

           struct v2f
           {

               float4 pos : SV_POSITION;
               float2 uv : TEXCOORD2;
           };

           v2f vert(a2v v)
           {
               v2f o;
               v.vertex -= float4(5, 0, 0, 0);
               float s;
               float c;
               sincos(radians(_Angle), s, c);
               float4x4 rotation = {
                   c, s, 0, 0,
                   -s, c, 0, 0,
                   0, 0, 1, 0,
                   0, 0, 0, 1
               }; // 绕Z轴旋转的矩阵

               v.vertex.y = s * sin(v.vertex.x * _WaveLength);
               v.vertex = mul(rotation, v.vertex);


               v.vertex += float4(5, 0, 0, 0);
               o.pos = UnityObjectToClipPos(v.vertex);
               o.uv = v.texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
               return o;
           }

           fixed4 frag(v2f i) : SV_TARGET0
           {
               return tex2D(_MainTex, i.uv);
           }
         
           ENDCG
       }

       Pass
       {
           Cull Front
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           #include "Lighting.cginc"
           
           float _Angle;
           float _WaveLength;
           sampler2D _SecTex;
           float4 _SecTex_ST;
           struct a2v
           {
               float4 vertex : POSITION;
               float4 texcoord : TEXCOORD0;
           };

           struct v2f
           {

               float4 pos : SV_POSITION;
               float2 uv : TEXCOORD2;
           };

           v2f vert(a2v v)
           {
               v2f o;
               v.vertex -= float4(5, 0, 0, 0);
               float s;
               float c;
               sincos(radians(_Angle), s, c); // 输入的是弧度制
               float4x4 rotation = {
                   c, s, 0, 0,
                   -s, c, 0, 0,
                   0, 0, 1, 0,
                   0, 0, 0, 1
               }; // 绕Z轴旋转的矩阵

               v.vertex.y = s * sin(v.vertex.x * _WaveLength);
               v.vertex = mul(rotation, v.vertex);


               v.vertex += float4(5, 0, 0, 0);
               o.pos = UnityObjectToClipPos(v.vertex);
               o.uv = v.texcoord * _SecTex_ST.xy + _SecTex_ST.zw;
               return o;
           }

           // 不考虑光照,所以就直接采样纹理颜色输出就行了
           fixed4 frag(v2f i) : SV_TARGET0
           {
               return tex2D(_SecTex, i.uv);
           }
         
           ENDCG
       }

	} 
	FallBack "Diffuse"
}

参考

https://blog.csdn.net/qq_28299311/article/details/103267750

本文作者:自动机

本文链接:https://www.cnblogs.com/monituihuo/p/17986954

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   自动机  阅读(84)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起