UnityShader使用Plane實(shí)現(xiàn)翻書效果
本文實(shí)例為大家分享了UnityShader使用Plane實(shí)現(xiàn)翻書效果的具體代碼,供大家參考,具體內(nèi)容如下
之前在網(wǎng)上看到一個(gè)Shadr可以實(shí)現(xiàn)旋轉(zhuǎn)效果,就拿來(lái)實(shí)現(xiàn)一個(gè)翻書效果。解決辦法是用不同模型的顯示與隱藏,像序列幀一樣,為了實(shí)現(xiàn)效果感覺(jué)實(shí)現(xiàn)起來(lái)很繁瑣且占用資源,后期優(yōu)化可考慮用對(duì)象池解決。今天就試著用vertex shader來(lái)實(shí)現(xiàn)一下,互相交流學(xué)習(xí),大神勿噴。
實(shí)現(xiàn)簡(jiǎn)單的翻書效果大概需要三步:
1.Plane的扭曲
2.Plane的旋轉(zhuǎn)
3.正反面的采樣
Plane的扭曲:
翻書的效果大概是,中間向外突出,X軸方向的正方向會(huì)向后偏移。
X軸負(fù)方向邊沿是保持不動(dòng)的,且扭曲程度跟隨旋轉(zhuǎn)角度增加又減小,90度為最大值。

Plane的旋轉(zhuǎn):
根據(jù)Plane的頂點(diǎn)X的范圍(-5,5)

Plane的貼圖采樣:
用了兩個(gè)Pass通道來(lái)實(shí)現(xiàn),一個(gè)是后面剔除,一個(gè)是前面剔除。分別對(duì)兩個(gè)圖片采樣。
下面是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
}
}
}
動(dòng)態(tài)修改這個(gè)值就可以達(dá)到Plan的翻轉(zhuǎn)

下面我們實(shí)現(xiàn)翻書效果
我們接下來(lái)要用DOTween,不明白DOTween可百度下來(lái)了解使用這里就不詳解;
創(chuàng)建Resources文件夾 在內(nèi)創(chuàng)建子文件夾FrontTextur(正面)和VersoTextur(反面)用來(lái)存放一本書的正反面圖片 把自己準(zhǔn)備的圖片導(dǎo)入 為了方面動(dòng)態(tài)加載我都用數(shù)字代替第幾頁(yè)

接下來(lái)我們創(chuàng)建一個(gè)Plan位置歸零
創(chuàng)建材質(zhì)球PageTurning2

然后再?gòu)?fù)制一個(gè)改名PageTurning3
把剛才創(chuàng)建的Plan添加材質(zhì)球PageTurning3
然后將Plan作為預(yù)設(shè)拖入Resources。
刪除Plan,然后重新創(chuàng)建一個(gè)Plan添加材質(zhì)球PageTurning2。
接下來(lái)用下面代碼實(shí)現(xiàn)翻書
using UnityEngine;
using DG.Tweening;
public class PageTurning : MonoBehaviour
{
private Material m_Material;
private int nowPage = 1; //最下面頁(yè)碼
private int lastPage; //已經(jīng)翻過(guò)的
private int allPage = 10; //所有的頁(yè)數(shù)
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) //設(shè)置閾值
{
nowPage = 1;
}
lastPage = nowPage - 1;
if (lastPage < 1)
{
lastPage = allPage;
}
#region 翻動(dòng)的頁(yè)面
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做旋轉(zhuǎn)動(dòng)畫
m_Material2.DOFloat(180, "_Angle", 2);
//m_Material2.name = "當(dāng)前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); //更改材質(zhì)的正面
m_Material2.SetTexture("_SecTex", ShowVersoLast); //更改材質(zhì)球的反面
#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); //更改材質(zhì)求的正面
m_Material.SetTexture("_SecTex", ShowVerso); //更改材質(zhì)球的反面
//m_Material.name = "當(dāng)前Material"+nowPage.ToString();
}
}
把這個(gè)代碼掛載到剛創(chuàng)建的Plan上
創(chuàng)建一個(gè) UI的Button綁定腳本PageTurning上的 Turning方法。這樣就實(shí)現(xiàn)了翻書的效果。
現(xiàn)在只做了往后翻書效果,如果想做往前翻的效果可把每次創(chuàng)建的Plan加載到集合中然后從集合中修改他們的材質(zhì)球
m_Material.SetFloat("_Angle", value)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#通過(guò)實(shí)現(xiàn)winmm枚舉音頻設(shè)備
使用C#做音頻錄制時(shí)需要獲取音頻設(shè)備信息,其中比較簡(jiǎn)單的就是使用winmm,所以本文就為大家介紹一下C#如何通過(guò)實(shí)現(xiàn)winmm枚舉音頻設(shè)備,需要的可以參考下2023-10-10
C#利用LINQ實(shí)現(xiàn)一個(gè)文件拆分成多個(gè)文件的示例詳解
在日常開發(fā)過(guò)程中,我們可能會(huì)遇到需要將一個(gè)大型文件拆分成多個(gè)小文件的需求,例如,為了便于傳輸、處理或備份,在C#中,我們可以利用LINQ技術(shù)來(lái)實(shí)現(xiàn)這一功能,下面我將詳細(xì)介紹如何使用LINQ拆分文件,需要的朋友可以參考下2024-08-08
c#使用FreeSql生產(chǎn)環(huán)境時(shí)自動(dòng)升級(jí)備份數(shù)據(jù)庫(kù)
使用FreeSql,包含所有的ORM數(shù)據(jù)庫(kù),都會(huì)存在這樣的問(wèn)題。在codefirst模式下,根據(jù)代碼自動(dòng)更新數(shù)據(jù)庫(kù),都建議不要在生產(chǎn)環(huán)境使用。因?yàn)槿菀讈G失數(shù)據(jù),本文提供一種自動(dòng)更新數(shù)據(jù)庫(kù)的解決的思路:在判斷需要升級(jí)時(shí),才自動(dòng)升級(jí),同時(shí)升級(jí)前先備份數(shù)據(jù)庫(kù)2021-06-06

