Use Unity Shader and Mesh to make a dynamic paper tearing effect. - bosssu/shader_Funny GitHub Wiki
First, let's briefly introduce the principle:
Mainly divided into two parts - mesh animation part and shader part:
Mesh part : you can read my other article for detail : https://github.com/bosssu/Imagination-and-creativity/wiki/Make-a-paper-airplane-with-Unity
Shader part: The shader effect is mainly divided into two layers. The background layer is used to render the torn effect, and the foreground layer is used to render the part to be torn off. The key to controlling the content of the two-layer display is to use a Mask map.
a simple mask picture drawn with Photoshop
The background shows the opaque area of the mask image, and the foreground shows the transparent area of the mask image (just the opposite), so that when the foreground and background are stacked together, it is a complete piece of paper. And when we roll up the grid in the foreground, the effect of tearing paper appears. Keep it simple.
And using this scheme of Mask makes the tearing paper highly customizable. If you want to switch between different effects, just change the Mask picture, so easy!
As shown in the figure, you can get two effects with two simple mask picture:
After understanding the principle mentioned above, in fact, there is not much to say about this effect. But let me briefly mention two points :
-
The transparent processing of the background and foreground will not be discussed, it is a conventional practice. Some friends here may be curious: how did the white tear marks between the two sheets of paper get made? In fact, it is very simple, that is, when the alpha is in a certain interval, simply and rudely assigning its color to white is ok. And this rough method will produce a rustling texture at the tear mark, which is very real.
-
For the mesh animation part, you can read my other article for detail.
Of course, the mesh animation can also be done in the shader, the principle is exactly the same, and the efficiency is higher. core code :
` public void OnAngleSliderValueChanged(float value) {
linePoints[0] = new Vector3(value, linePoints[0].y, linePoints[0].z);
linePoints[1] = new Vector3(value, linePoints[1].y, linePoints[1].z);
Vector3[] newVertexs = new Vector3[orginVertexs.Length];
Vector3 lstart = linePoints[0];
Vector3 lend = linePoints[1];
// The vertical vector from origin point to line.
Vector3 offset = Point2LineVec(Vector3.zero, lstart, lend);
Vector3 axis = (lend - lstart).normalized;
for (int i = 0; i < orginVertexs.Length; i++)
{
if (IsVertexOnMarkLineRight(orginVertexs[i], lstart, lend))
{
Vector3 vtemp = new Vector3(orginVertexs[i].x,0,0);
Vector3 vertexOffset = Point2LineVec(vtemp, lstart, lend);
//offset the vertices first
Vector3 temp = orginVertexs[i] + offset;
//recover the vertices offset after rotate vertices finished
newVertexs[i] = Quaternion.AngleAxis(angle * Mathf.Abs(vertexOffset.x) * curve.Evaluate(angle / 180f), axis) * temp - offset;
}
else
{
newVertexs[i] = orginVertexs[i];
}
}
mesh.vertices = newVertexs;
mesh.RecalculateNormals();
}
// the vertical vector from a point to a line in 3D space
//targetPoint: the point ;lstart,lend:two points on a line
private Vector3 Point2LineVec(Vector3 targetPoint, Vector3 lstart, Vector3 lend)
{
Vector3 p = targetPoint - lstart;
Vector3 l = lend - lstart;
//The projection vector of the target vertex onto the line
Vector3 projectVec = Vector3.Dot(p, l) * l.normalized + lstart;
//The vertical vector of the target vertex on the line
Vector3 p2lineVec = p - projectVec;
return p2lineVec;
}
private bool IsVertexOnMarkLineRight(Vector3 vertex, Vector3 lstart, Vector3 lend)
{
Vector3 point2LineVec = Point2LineVec(vertex, lstart, lend);
Vector3 lineVec = lend - lstart;
return Vector3.Cross(lineVec, point2LineVec).y > 0;
}`