Home>

I just use a texture here.Let's call it "turning the boards", haha.

Implementation process:

In fact, this effect is quite simple to achieve,Probably the idea is actuallyRotate all vertices around the z axis and make them a little radian with sine and cosine.

Let's start step by step to achieve this effect.

First open Unity to create a new project,Scene, and create a shader file named openbookeffect, delete the original redundant code.

first step,Let's make it rotate around the z-axis first

A rotation matrix is ​​used here,Multiply the vertices by the matrix,You can get the position after rotation.(Ps:I won't explain in detail how the rotation matrix is ​​derived here.Those interested can go to Baidu to find out.)

There are three types of rotation matrices:

1. Rotate around the x axis:

2. Rotate around the y-axis

3. Rotate around the z axis

Obviously, we need to use the thirdMatrix rotated around z axis. Below we use code to build a rotation matrix and rotate it by a certain angle:

properties
 {
 _maintex ("texture", 2d)="white" {}
 //Rotation angle
 _angle ("angle", range (0,180))=0
 }
 ....
 sampler2d _maintex;
 //angle
 float _angle;
 //vertex shader
 v2f vert (appdata v)
 {
 v2f o;
 float s;
 float c;
 //This method can calculate the sine and cosine of the angle
 sincos (radians (_angle), s, c);
 //rotation matrix
 float4x4 rotatematrix={
  c, s, 0,0,  -s, c, 0,0,  0, 0,1,0,  0, 0,0,1
 };
 //left vertex multiplied by rotation matrix
 v.vertex=mul (rotatematrix, v.vertex);
 //Convert model space to crop space
 o.vertex=unityobjecttoclippos (v.vertex);
 o.uv=v.uv;
 return o;
 }
 ....

Edit_angleto rotate the plane,As shown in the figure:

Through testing,This rotation is not the effect we want,The axis of rotation is now in the center,We want its axis of rotation to be on the far left,At this point, you need to put all vertices in theSpinBeforeLeft offset by 5 units,After the rotation is completedGo toOffset 5 units to the rightWe can achieve the effect we want,code show as below:

v2f vert (appdata v)
  {
  v2f o;
  //Offset 5 units to the left before rotation
 v.vertex-= float4 (5,0,0,0);
  float s;
  float c;
  //This method can calculate the sine and cosine of the angle
  sincos (radians (_angle), s, c);
  //rotation matrix
  float4x4 rotatematrix={
   c, s, 0,0,   -s, c, 0,0,   0, 0,1,0,   0, 0,0,1
  };
  //left vertex multiplied by rotation matrix
  v.vertex=mul (rotatematrix, v.vertex);
  //Offset back after rotation
 v.vertex +=float4 (5,0,0,0);
  //Convert model space to crop space
  o.vertex=unityobjecttoclippos (v.vertex);
  o.uv=v.uv;
  return o;
  }

Now it looks a little like a book,But now the flip book effect is too blunt,In order to get close to the real flipbook effect,We need to passSine cosine functionModify theof a vertexy coordinateto reach aradian.

v2f vert (appdata v)
 {
 v2f o;
 //Offset 5 units to the right before rotation
 v.vertex-= float4 (5,0,0,0);
 float s;
 float c;
 //This method can calculate the sine and cosine of the angle
 sincos (radians (_angle), s, c);
 //rotation matrix
 float4x4 rotatematrix={
  c, s, 0,0,  -s, c, 0,0,  0, 0,1,0,  0, 0,0,1
 };
 //Calculate the sine value of the y coordinate by the sine function according to the x coordinate, _wavelength controls the wavelength, The amplitude changes dynamically with the sine of the angle
 v.vertex.y=sin (v.vertex.x * _wavelength) * s;
 //left vertex multiplied by rotation matrix
 v.vertex=mul (rotatematrix, v.vertex);
 //Offset back after rotation
 v.vertex +=float4 (5,0,0,0);
 //Convert model space to crop space
 o.vertex=unityobjecttoclippos (v.vertex);
 o.uv=v.uv;
 return o;
 }

The effect is as follows:

Now look at the effect is not widened.It feels pretty good,But it's not over yet,If we look carefully, we will find that the process of "turning the book" is a bit unreal on the backShould not be the opposite of the texture,But another new texture,What should we do now?

it's actually really easy,Just need to render the front and back separately.One pass renders the front,A pass renders the back.

First we need to pass thecullThe instruction removes the side that does not need to be rendered.

The complete code is as follows:

shader "learn unity shader/openbook"
{
  properties
  {
    //front texture
    _maintex ("texture", 2d)="white" {}
    //Back texture
 _sectex ("sectex", 2d)="white" {}
    //Rotation angle
    _angle ("angle", range (0,180))=0
    //wavelength
    _wavelength ("wavelength", range (-1,1))=0
  }
  subshader
  {
    pass
    {
      //Remove the back
  cull back
      cgprogram
      #pragma vertex vert
      #pragma fragment frag
      #include "unitycg.cginc"
      struct appdata
      {
        float4 vertex:position;
        float2 uv:texcoord0;
      };
      struct v2f
      {
        float2 uv:texcoord0;
        float4 vertex:sv_position;
      };
      sampler2d _maintex;
  float4 _maintex_st;
      //angle
      float _angle;
      //wavelength
      float _wavelength;
      v2f vert (appdata v)
      {
        v2f o;
        //Offset 5 units to the right before rotation
        v.vertex-= float4 (5,0,0,0);
        float s;
        float c;
        //This method can calculate the sine and cosine of the angle
        sincos (radians (_angle), s, c);
        //rotation matrix
        float4x4 rotatematrix={
          c, s, 0,0,          -s, c, 0,0,          0, 0,1,0,          0, 0,0,1
        };
        //Calculate the sine value of the y coordinate by the sine function according to the x coordinate, _wavelength controls the wavelength, The amplitude changes dynamically with the sine of the angle
        v.vertex.y=sin (v.vertex.x * _wavelength) * s;
        //left vertex multiplied by rotation matrix
        v.vertex=mul (rotatematrix, v.vertex);
        //Offset back after rotation
        v.vertex +=float4 (5,0,0,0);
        //Convert model space to crop space
        o.vertex=unityobjecttoclippos (v.vertex);
        o.uv=v.uv;
        return o;
      }
      fixed4 frag (v2f i):sv_target
      {
        fixed4 col=tex2d (_maintex, i.uv);
        return col;
      }
      endcg
    }
     pass
    {
      //Reject positive
  cull front
      cgprogram
      #pragma vertex vert
      #pragma fragment frag
      #include "unitycg.cginc"
      struct appdata
      {
        float4 vertex:position;
        float2 uv:texcoord0;
      };
      struct v2f
      {
        float2 uv:texcoord0;
        float4 vertex:sv_position;
      };
      //angle
      float _angle;
      //wavelength
      float _wavelength;
      sampler2d _sectex;
  float4 _sectex_st;
      v2f vert (appdata v)
      {
        v2f o;
        //Offset 5 units to the right before rotation
        v.vertex-= float4 (5,0,0,0);
        float s;
        float c;
        //This method can calculate the sine and cosine of the angle
        sincos (radians (_angle), s, c);
        //rotation matrix
        float4x4 rotatematrix={
          c, s, 0,0,          -s, c, 0,0,          0, 0,1,0,          0, 0,0,1
        };
        //Calculate the sine value of the y coordinate by the sine function according to the x coordinate
 _wavelength controls the wavelength, The amplitude changes dynamically with the sine of the angle
        v.vertex.y=sin (v.vertex.x * _wavelength) * s;
        //left vertex multiplied by rotation matrix
        v.vertex=mul (rotatematrix, v.vertex);
        //Offset back after rotation
        v.vertex +=float4 (5,0,0,0);
        //Convert model space to crop space
        o.vertex=unityobjecttoclippos (v.vertex);
        o.uv=v.uv;
        return o;
      }
      fixed4 frag (v2f i):sv_target
      {
        fixed4 col=tex2d (_sectex, i.uv);
        return col;
      }
      endcg
    }
  }
}

final effect:

c
  • Previous Python list comprehensions
  • Next ADONET practical experience summary