UnityShader使用Plane实现翻书效果
作者:Cool-浩 发布时间:2022-05-19 14:46:14
本文实例为大家分享了UnityShader使用Plane实现翻书效果的具体代码,供大家参考,具体内容如下
之前在网上看到一个Shadr可以实现旋转效果,就拿来实现一个翻书效果。解决办法是用不同模型的显示与隐藏,像序列帧一样,为了实现效果感觉实现起来很繁琐且占用资源,后期优化可考虑用对象池解决。今天就试着用vertex shader来实现一下,互相交流学习,大神勿喷。
实现简单的翻书效果大概需要三步:
1.Plane的扭曲
2.Plane的旋转
3.正反面的采样
Plane的扭曲:
翻书的效果大概是,中间向外突出,X轴方向的正方向会向后偏移。
X轴负方向边沿是保持不动的,且扭曲程度跟随旋转角度增加又减小,90度为最大值。
Plane的旋转:
根据Plane的顶点X的范围(-5,5)
Plane的贴图采样:
用了两个Pass通道来实现,一个是后面剔除,一个是前面剔除。分别对两个图片采样。
下面是Shader
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Personal/PageTurning" {
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex("MainTex",2D)="White"{}
_SecTex("SecTex",2D)="White"{}
_Angle("Angle",Range(0,180))=0
_Warp("Warp",Range(0,10))=0
_WarpPos("WarpPos",Range(0,1))=0
_Downward("Downward",Range(0,1))=0
}
SubShader
{
pass
{
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
fixed4 _Color;
float _Angle;
float _Warp;
float _Downward;
float _WarpPos;
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_base v)
{
v2f o;
v.vertex += float4(5,0,0,0);
float s;
float c;
sincos(radians(-_Angle),s,c);
float4x4 rotate={
c,s,0,0,
-s,c,0,0,
0,0,1,0,
0,0,0,1};
float rangeF=saturate(1 - abs(90-_Angle)/90);
v.vertex.y += -_Warp*sin(v.vertex.x*0.4-_WarpPos* v.vertex.x)*rangeF;
v.vertex.x -= rangeF * v.vertex.x*_Downward;
v.vertex = mul(rotate,v.vertex);
v.vertex += float4(-5,0,0,0);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):COLOR
{
fixed4 color = tex2D(_MainTex,-i.uv);
return _Color * color;
}
ENDCG
}
pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
fixed4 _Color;
float _Angle;
float _Warp;
float _Downward;
float _WarpPos;
sampler2D _SecTex;
float4 _MainTex_ST;
v2f vert(appdata_base v)
{
v2f o;
v.vertex += float4(5,0,0,0);
float s;
float c;
sincos(radians(-_Angle),s,c);
float4x4 rotate={
c,s,0,0,
-s,c,0,0,
0,0,1,0,
0,0,0,1};
float rangeF=saturate(1 - abs(90-_Angle)/90);
v.vertex.y += -_Warp*sin(v.vertex.x*0.4-_WarpPos* v.vertex.x)*rangeF;
v.vertex.x -= rangeF * v.vertex.x*_Downward;
v.vertex = mul(rotate,v.vertex);
v.vertex += float4(-5,0,0,0);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):COLOR
{
float2 uv = i.uv;
uv.x = -uv.x;
fixed4 color = tex2D(_SecTex,-uv);
return _Color * color;
}
ENDCG
}
}
}
动态修改这个值就可以达到Plan的翻转
下面我们实现翻书效果
我们接下来要用DOTween,不明白DOTween可百度下来了解使用这里就不详解;
创建Resources文件夹 在内创建子文件夹FrontTextur(正面)和VersoTextur(反面)用来存放一本书的正反面图片 把自己准备的图片导入 为了方面动态加载我都用数字代替第几页
接下来我们创建一个Plan位置归零
创建材质球PageTurning2
然后再复制一个改名PageTurning3
把刚才创建的Plan添加材质球PageTurning3
然后将Plan作为预设拖入Resources。
删除Plan,然后重新创建一个Plan添加材质球PageTurning2。
接下来用下面代码实现翻书
using UnityEngine;
using DG.Tweening;
public class PageTurning : MonoBehaviour
{
private Material m_Material;
private int nowPage = 1; //最下面页码
private int lastPage; //已经翻过的
private int allPage = 10; //所有的页数
private float Thickness = 0; //书的厚度
void Start ()
{
m_Material = GetComponent<MeshRenderer>().material;
Texture ShowFront = Resources.Load("AllTextur/FrontTextur/" + nowPage.ToString(), typeof(Texture)) as Texture;
Texture ShowVerso = Resources.Load("AllTextur/VersoTextur/" + nowPage.ToString(), typeof(Texture)) as Texture;
m_Material.SetTexture("_MainTex", ShowFront);
m_Material.SetTexture("_SecTex", ShowVerso);
}
public void Turning()
{
nowPage += 1;
if (nowPage>10) //设置阈值
{
nowPage = 1;
}
lastPage = nowPage - 1;
if (lastPage < 1)
{
lastPage = allPage;
}
#region 翻动的页面
Material m_Material2 = (Instantiate(Resources.Load("Plane"),new Vector3(0, Thickness+=0.001f, 0), Quaternion.identity) as GameObject).GetComponent<MeshRenderer>().material;
m_Material2.SetFloat("_Angle", 0); //DoTween做旋转动画
m_Material2.DOFloat(180, "_Angle", 2);
//m_Material2.name = "当前Material"+ lastPage;
Texture ShowFrontLast = Resources.Load("AllTextur/FrontTextur/" + lastPage.ToString(), typeof(Texture)) as Texture; //Resources加载正面图片
Texture ShowVersoLast = Resources.Load("AllTextur/VersoTextur/" + lastPage.ToString(), typeof(Texture)) as Texture; //Resources加载反面图片
m_Material2.SetTexture("_MainTex", ShowFrontLast); //更改材质的正面
m_Material2.SetTexture("_SecTex", ShowVersoLast); //更改材质球的反面
#endregion
Texture ShowFront = Resources.Load("AllTextur/FrontTextur/" + nowPage.ToString(), typeof(Texture)) as Texture; //Resources加载正面图片
Texture ShowVerso = Resources.Load("AllTextur/VersoTextur/" + nowPage.ToString(), typeof(Texture)) as Texture; //Resources加载反面图片
m_Material.SetTexture("_MainTex", ShowFront); //更改材质求的正面
m_Material.SetTexture("_SecTex", ShowVerso); //更改材质球的反面
//m_Material.name = "当前Material"+nowPage.ToString();
}
}
把这个代码挂载到刚创建的Plan上
创建一个 UI的Button绑定脚本PageTurning上的 Turning方法。这样就实现了翻书的效果。
现在只做了往后翻书效果,如果想做往前翻的效果可把每次创建的Plan加载到集合中然后从集合中修改他们的材质球
m_Material.SetFloat("_Angle", value)
来源:https://blog.csdn.net/qq_39741605/article/details/80678229


猜你喜欢
- MD5加密简介哈希算法又称散列算法,是将任何数据转换成固定长度的算法的统称。 从本质上讲,MD5也是一种哈希算法,其输出是生成12
- Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map对集合按照单个属性分组、分组
- IDEA快速创建getter和setter方法找到generate我的是Mac,右击鼠标就可以打开,相信windows也不难。选择gette
- Lambda 表达式最早接触到 Lambda 表达式的时候,是在学习 python 的时候,当时就很好奇。后来,才发现 Java 也有这个方
- mybatis多层级collection嵌套json结构第一步查询第一层查询,将第一层的id传递到第二层当条件查询
- Spark_SQL性能调优众所周知,正确的参数配置对提升Spark的使用效率具有极大助力,帮助相关数据开发、分析人员更高效地使用Spark进
- 异步客户端套接字示例 下面的示例程序创建一个连接到服务器的客户端。该客户端是用异步套接字生成的,因此在等待服务器返回
- MyBatis添加记录后获取主键ID,这是一个很常见的需求。这个需求有分为两种情况:(1)添加单条记录时获取主键值;(2)获取批量添加记录时
- 学习内容Java I/O 项目案例内容管理java文件I/O实例----生成报表我们之前学习了两个重要的模块,一个就是Java I/O 另外
- 本文实例讲述了C#设计模式之Builder生成器模式解决带老婆配置电脑问题。分享给大家供大家参考,具体如下:一、理论定义生成器模式 又叫:建
- 问题描述设有n个会议的集合C={1,2,…,n},其中每个会议都要求使用同一个资源(如会议室),而在同一时间内只能有一
- 今天在做一个java调用windows的压缩命令时遇到一奇怪问题代码如下:String cmd ="C:/Program File
- jwt简介冒泡排序:(Bubble Sort)是一种简单的交换排序。之所以叫做冒泡排序,因为我们可以把每个元素当成一个小气泡,根据气泡大小,
- Spring security记住我基本原理:登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFil
- 序言因为之前在项目中使用看groovy对业务进行一些抽象,效果比较好,过程中踩过一些坑,所以简单记录分享一下自己如何一步一步去实现的为什么用
- 本文实例讲述了Android编程解析XML文件的方法。分享给大家供大家参考,具体如下:前言在学习Android的Framework层源码时,
- 事件监听其实我们并不陌生,简单来讲,当程序达到了某个特定的条件,程序就会自动执行一段指令。在spring 中也一样,我们可以使用spring
- 最近有一个项目要用到年份周期,用于数据统计图表展示使用,当中用到年份周期,以及年份周期所在的日期范围。当初设想通过已知数据来换算年份周期,经
- 前言最学习动态规划思想的路上,遇见了‘分割回文串问题',如临大敌啊,题目听起来蛮简单,思考起来却也没那么容易,比解决问题更头疼的是如
- PDF中的加数字签名是对文档权威性的有效证明。我们在向PDF文档添加签名时,需要准备可信任的签名证书。同时,对已有的签名,可验证签名是否有效