Unity shader character disappears to dissolve the invisibility effect

First two renderings

Insert picture description here
Insert picture description here

Realization principle

One sentence summary:
There is an invisible surface in the space, judge the relative position of the surface and the surface on the model, and hide the points above or below according to the needs.

The principle is as simple as that. How to implement it? First, determine the nature of the plane in mathematical geometry: the vector a formed from the origin to any point on the surface , and the normal ( n ) direction projection of this surface , are all equal, and the distance is d. Expressed by the mathematical formula:
ax + by + cz = d
it is easier to understand to draw a small picture:
Insert picture description here
the simplest plane is perpendicular to the Y axis. The projections of P1 and P2 in the normal direction are red dotted lines with the same length, which is d. P3 is the point below the surface, and the projection in the normal direction is less than d. From this, it is possible to compare the projection of the normal direction of the surface with the value of d by comparing the vector of any point in the space with the origin as the starting point to determine the relative relationship between this point and the surface. position. The direction of the normal is different, the way of judgment is also different.
PS: The origin is chosen because the coordinate value of a point is its vector, which is convenient for calculation. You can also choose another point in the space as the origin of the calculation.
Through the above explanation, it can be determined that before writing the shader, you need to get the normal vector and d, so choose any point on the surface, and then choose a normal vector. For the convenience of calculation, directly select n as transform.forward, any point P as transform.position, calculate d through C#, and pass the normal and d into the shader. In order to save variables, one should be selected in the shader vector. The xyz component is the normal xyz, and the w component is d (Of course, multiple variables are also possible). Then you can start writing the shader.

Vector3 point = transform.position;
Vector3 normal = transform.forward;
float dis = Vector3.Dot(point, normal.normalized);
material.SetVector("_Plane", new Vector4(normal.x, normal.y, normal.z, dis));
  • 1
  • 2
  • 3
  • 4

At this time, the problem becomes the projection of any point in any space (the coordinate is its vector) on the vector n and compare it with d.
Insert picture description here
As shown in the figure above, you only need to calculate the length of the blue dotted line, using the dot product of the dotvector, and the unit vector of the P point vector dot multiplying the normal line, which is directly the length of the blue dotted line.

float3 face_normal = _Plane.xyz;
float target_dis = _Plane.w;
float dis = dot(i.worldPos.xyz, normalize(face_normal));
clip(dis - target_dis);
  • 1
  • 2
  • 3
  • 4

Next, according to the direction of the normal or your own needs, you can use the cliptrimming to achieve the effect of removing the points that do not meet the requirements, as shown in the following figure:
Insert picture description here
In order to make the effect softer, add a noise map, and randomly offset the points that need the clip. Shift, modify the Tiling value of the noise map, change the sampling frequency, and achieve the effect of the beginning of the article.

fixed4 col = tex2D(_NoiseTex, TRANSFORM_TEX(i.uv, _NoiseTex));
float offset = (col.r * 2 - 1) * _Strength;
float3 w_pos = i.worldPos.xyz + float3(offset, offset, offset);
float3 face_normal = _Plane.xyz;
float target_dis = _Plane.w;
float dis = dot(w_pos, normalize(face_normal));
clip(dis - target_dis);

Guess you like

Origin blog.csdn.net/mango9126/article/details/109373590