Unityshader uses plane to turn over books

Time:2021-8-17

This example shares the specific code of unityshader using plane to realize the book flipping effect for your reference. The specific contents are as follows

I saw a shadr on the Internet that can realize the rotation effect, so I used it to realize a Book flipping effect. The solution is to display and hide different models. Like sequence frames, in order to achieve the effect, it feels cumbersome and takes up resources. In the later optimization, object pool can be considered. Today, try to use vertex shader to realize it. Exchange and learn from each other. Don’t spray.

It takes about three steps to achieve a simple book turning effect:

1. Distortion of plane

2. Rotation of plane

3. Front and back sampling

Plane twist:

The effect of turning a book is that the middle protrudes outward, and the positive direction of the x-axis will offset backward.

The negative edge of the x-axis remains stationary, and the degree of distortion increases and decreases with the rotation angle, and 90 degrees is the maximum.

Rotation of plane:

According to the range of vertex x of plane (- 5, 5)

Map sampling for plane:

Two pass channels are used to realize, one is the back elimination and the other is the front elimination. Sample two pictures respectively.

Here is the 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
  }
 }
}

By dynamically modifying this value, the plan can be flipped

Let’s turn the book

We’re going to use dotween next. I don’t understand dotween, but Baidu comes down to understand and use it. I won’t explain it in detail here;

Create a Resources folder and create sub folders fronttextur (front) and versotextur (back) to store the front and back pictures of a book. Import the pictures prepared by myself. For dynamic loading, I use numbers instead of the page

Next, we create a plan to zero the position

Create shader pageturning2

Then copy another one, renamed pageturning3

Add the plan you just created to shader pageturning3

Then drag the plan as a preset into resources.

Delete the plan and recreate it. Add shader pageturning2.

Next, turn the book with the following code

using UnityEngine;
using DG.Tweening;
 
public class PageTurning : MonoBehaviour
{
    private Material m_Material;
    private int nowPage = 1; // Bottom page
    private int lastPage;   // Already turned
    private int allPage = 10;   // All pages
    private float Thickness = 0; // Book thickness
 
    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) // set the threshold
        {
            nowPage = 1;
        }
        lastPage = nowPage - 1;
        if (lastPage < 1)
        {
            lastPage = allPage;
        }
        #Region flipped page
 
        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 does rotation animation
        m_Material2.DOFloat(180, "_Angle", 2);
        
        //m_ Material2.name = "current material" + lastpage;
        Texture ShowFrontLast = Resources.Load("AllTextur/FrontTextur/" + lastPage.ToString(), typeof(Texture)) as Texture;  // Resources load front image
        Texture ShowVersoLast = Resources.Load("AllTextur/VersoTextur/" + lastPage.ToString(), typeof(Texture)) as Texture;  // Resources load reverse image
        m_ Material2.SetTexture("_ MainTex", ShowFrontLast);   // Change the front face of the material 
        m_ Material2.SetTexture("_ SecTex", ShowVersoLast);    // Change the reverse side of the shader
 
        #endregion
 
        Texture ShowFront = Resources.Load("AllTextur/FrontTextur/" + nowPage.ToString(), typeof(Texture)) as Texture;    // Resources load front image
        Texture ShowVerso = Resources.Load("AllTextur/VersoTextur/" + nowPage.ToString(), typeof(Texture)) as Texture;   // Resources load reverse image
        m_ Material.SetTexture("_ MainTex", ShowFront);       // Change the front face of the material
        m_ Material.SetTexture("_ SecTex", ShowVerso);       // Change the reverse side of the shader
        //m_ Material. Name = "current material" + nowpage. Tostring();
 
       
    }
}

Mount this code on the newly created plan

Create a button binding script of the UI and the turning method on pageturning. In this way, the effect of turning the book is realized.

Now we only have the effect of turning back the book. If you want to turn forward, you can load the plans created each time into the collection, and then modify their shaders from the collection


m_Material.SetFloat("_Angle", value)

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.