background
Meshes that we create dynamically through code will not receive lighting because they have no normals.
Under normal circumstances, call the Mesh.RecalculateNormals method to regenerate the normal.
But under certain circumstances, the vertices calculated by this method are found to be (0, 0, 0). In this case, the normal can only be generated manually.
As shown in the figure below, the object on the left has the correct normal and can receive light information, while the object on the right cannot be normal and cannot receive light.
The reason for the abnormal calculation of RecalculateNormals
After testing, it is found that the calculation of Mesh.RecalculateNormals is abnormal:
if a certain vertex in the Mesh, in the triangle label array, draws both the front mesh and the reverse mesh, it will cause an error in the calculation of RecalculateNormals. The calculation result of the point normal is (0, 0, 0).
Solution 1
For double-sided meshes, the vertex array is doubled to draw the mesh on the opposite side, and put them into the triangle label array of Mesh to ensure that the normal calculation of each point is correct.
Solution 2
Use the Generate Vertex Normals algorithm below to manually calculate the desired normal array.
principle
Normal : A normal is a straight line that is always perpendicular to a plane. In geometry, a normal is a line on a plane perpendicular to the tangent to a curve at a point.
Grid normal array : the normal array stores the normal of each vertex of the Mesh, the size of the array corresponds to the vertex coordinates, and normals[i] corresponds to the normal of vertices[i].
In Max Wagner's "Generating Vertex Normals" article - Strictly speaking, points have no normals. The point's normal is used to calculate lighting when using Phone or Gouraud models. If all the normals on a face are the same, their lighting will be the same, which will produce a flatness effect; and if the normals of each vertex are set differently, it will be smoother.
The meshes we create through code are generally polygons, so assign each vertex the normal of the plane it is on.
Algorithm for generating vertex normals
Create a grid and set the eight points, triangle sequence, uv as shown above
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[8];
vertices[0] = new Vector3(0,0,0);
vertices[1] = new Vector3(0,1,0);
vertices[2] = new Vector3(1,0,0);
vertices[3] = new Vector3(1,1,0);
vertices[4] = new Vector3(1,0,0);
vertices[5] = new Vector3(1,1,0);
vertices[6] = new Vector3(2,0,1);
vertices[7] = new Vector3(2,1,1);
mesh.vertices = vertices;
int[] triangles = new int[12];
triangles[0] = 0;
triangles[1] = 1;
triangles[2] = 3;
triangles[3] = 2;
triangles[4] = 0;
triangles[5] = 3;
triangles[6] = 4;
triangles[7] = 5;
triangles[8] = 7;
triangles[9] = 6;
triangles[10] = 4;
triangles[11] = 7;
mesh.triangles = triangles;
Vector2[] uv = new Vector2[8];
uv[0] = new Vector2(0,0);
uv[1] = new Vector2(0,1);
uv[2] = new Vector2(1,0);
uv[3] = new Vector2(1,1);
uv[4] = new Vector2(0,0);
uv[5] = new Vector2(0,1);
uv[6] = new Vector2(1,0);
uv[7] = new Vector2(1,1);
mesh.uv = uv;
Generate normal array
Vector3[] normals = new Vector3[8];
Vector3 v1 = Vector3.Cross(vertices[0] - vertices[1], vertices[0] - vertices[3]);
normals[0] = v1;
normals[1] = v1;
normals[2] = v1;
normals[3] = v1;
Vector3 v2 = Vector3.Cross(vertices[4] - vertices[5], vertices[4] - vertices[7]);
normals[4] = v2;
normals[5] = v2;
normals[6] = v2;
normals[7] = v2;
mesh.normals = normals;
//mesh.RecalculateNormals();
final effect
(In this case, using Mesh.RecalculateNormal can also generate the correct normal.)
The complete code, added points, and the comment part is to add the back grid
public Mesh CreatMeshTest()
{
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[12];
vertices[0] = new Vector3(0,0,0);
vertices[1] = new Vector3(0,1,0);
vertices[2] = new Vector3(1,0,0);
vertices[3] = new Vector3(1,1,0);
vertices[4] = new Vector3(1,0,0);
vertices[5] = new Vector3(1,1,0);
vertices[6] = new Vector3(0.5f,0,1);
vertices[7] = new Vector3(0.5f,1,1);
vertices[8] = new Vector3(0.5f,0,1);
vertices[9] = new Vector3(0.5f,1,1);
vertices[10] = new Vector3(0,0,0);
vertices[11] = new Vector3(0,1,0);
mesh.vertices = vertices;
int[] triangles = new int[18];
triangles[0] = 0;
triangles[1] = 1;
triangles[2] = 3;
triangles[3] = 2;
triangles[4] = 0;
triangles[5] = 3;
triangles[6] = 4;
triangles[7] = 5;
triangles[8] = 7;
triangles[9] = 6;
triangles[10] = 4;
triangles[11] = 7;
triangles[12] = 8;
triangles[13] = 9;
triangles[14] = 11;
triangles[15] = 10;
triangles[16] = 8;
triangles[17] = 11;
// triangles[18] = 0;
// triangles[19] = 3;
// triangles[20] = 1;
//
// triangles[21] = 2;
// triangles[22] = 3;
// triangles[23] = 0;
//
// triangles[24] = 4;
// triangles[25] = 7;
// triangles[26] = 5;
//
// triangles[27] = 6;
// triangles[28] = 7;
// triangles[29] = 4;
//
// triangles[30] = 8;
// triangles[31] = 11;
// triangles[32] = 9;
//
// triangles[33] = 10;
// triangles[34] = 11;
// triangles[35] = 8;
mesh.triangles = triangles;
Vector2[] uv = new Vector2[12];
uv[0] = new Vector2(0,0);
uv[1] = new Vector2(0,1);
uv[2] = new Vector2(1,0);
uv[3] = new Vector2(1,1);
uv[4] = new Vector2(0,0);
uv[5] = new Vector2(0,1);
uv[6] = new Vector2(1,0);
uv[7] = new Vector2(1,1);
uv[8] = new Vector2(0,0);
uv[9] = new Vector2(0,1);
uv[10] = new Vector2(1,0);
uv[11] = new Vector2(1,1);
mesh.uv = uv;
Vector3[] normals = new Vector3[12];
Vector3 v1 = Vector3.Cross(vertices[0] - vertices[1], vertices[0] - vertices[3]);
normals[0] = v1;
normals[1] = v1;
normals[2] = v1;
normals[3] = v1;
Vector3 v2 = Vector3.Cross(vertices[4] - vertices[5], vertices[4] - vertices[7]);
normals[4] = v2;
normals[5] = v2;
normals[6] = v2;
normals[7] = v2;
Vector3 v3 = Vector3.Cross(vertices[8] - vertices[9], vertices[8] - vertices[11]);
normals[8] = v3;
normals[9] = v3;
normals[10] = v3;
normals[11] = v3;
mesh.normals = normals;
//mesh.RecalculateNormals();
return mesh;
}