UnityShader使用Plane實現翻書效果

本文實例為大傢分享瞭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)

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: