- Home /
Runtime generated mesh is not shaded right,only grey?
Hello to all,
I am trying to draw a cube at runtime but I am getting a result something like in the image. What would be the possible reasons for that? Thank you.
Edit: Ok I am giving some code too. This is how I create meshes.
var l = new List<Vector3>();
var bh = new BuildingHolder(center, l,buildingHeight);
for (int i = 0; i < l.Count; i++)
{
l[i] = l[i] - bh.Center;
}
BuildingDictionary.Add(center, bh);
var m = bh.CreateModel();
m.name = "building";
m.transform.parent = this.transform;
m.transform.localPosition = center;
BuildingHolder.cs
public class BuildingHolder
{
public GameObject GameObject { get; set; }
public Vector3 Center { get; set; }
public float Rotation { get; set; }
public bool IsModelCreated;
private List<Vector3> _verts;
private float buildingHeight;
public BuildingHolder(Vector3 center, List<Vector3> verts, float height)
{
IsModelCreated = false;
Center = center;
_verts = verts;
buildingHeight = height;
}
public GameObject CreateModel()
{
if (IsModelCreated)
return null;
var m = new GameObject().AddComponent<BuildingPolygon>();
m.gameObject.transform.position = Center;
m.Initialize(_verts,buildingHeight);
IsModelCreated = true;
return m.gameObject;
}
}
BuildingPolygon.cs
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
class BuildingPolygon : MonoBehaviour
{
private static float buildingHeight;
public void Initialize(List<Vector3> verts, float height)
{
GetComponent<MeshFilter>().mesh = CreateMesh(verts);
GetComponent<MeshRenderer>().material = Resources.Load("BuildingMat") as Material;
buildingHeight = height;
}
private static Mesh CreateMesh(List<Vector3> verts)
{
var tris = new Triangulator(verts.Select(x => x.ToVector2xz()).ToArray());
var mesh = new Mesh();
var vertices = verts.Select(x => new Vector3(x.x, 0, x.z)).ToList();
var indices = tris.Triangulate().ToList();
//var uv = new List<Vector2>();
var n = vertices.Count;
for (int index = 0; index < n; index++)
{
var v = vertices[index];
vertices.Add(new Vector3(v.x, buildingHeight, v.z));
}
for (int i = 0; i < n - 1; i++)
{
indices.Add(i);
indices.Add(i + n);
indices.Add(i + n + 1);
indices.Add(i);
indices.Add(i + n + 1);
indices.Add(i + 1);
}
indices.Add(n - 1);
indices.Add(n);
indices.Add(0);
indices.Add(n - 1);
indices.Add(n + n - 1);
indices.Add(n);
mesh.vertices = vertices.ToArray();
mesh.triangles = indices.ToArray();
mesh.RecalculateNormals();
mesh.RecalculateBounds();
return mesh;
}
}
Answer by tanoshimi · Jul 26, 2016 at 11:33 AM
You've not assigned any normals to the mesh. Take a look at the wiki for an example how: http://wiki.unity3d.com/index.php/ProceduralPrimitives#C.23_-_Box
Well, he does mesh.RecalculateNormals();
which should take care of that. I guess that he's not splitting the vertices at the corners. A cube needs 24 vertices not 8. If you use only 8 vertices your cube would be shaded like a sphere as the normals at each corner would just point outward from the cube center.
To get a flat-shaded face / triangle all vertex normals need to point in the same direction. If you only use 8 vertices each corner would be shared by 3 faces but the vertex can only have one normal. You have to duplicate each vertex 2 times so each face can have it's own normal vector.
Thank you Bunny83. But I didn't understand, what do you mean by 8 vertices. Can you give the line number about this.
That's hard to explain on your code example as it's not clear where exactly your vertices come from and how they look like.
As example have a look at this image:
The left mesh has shared vertices everywhere. So only 10 vertices in total. However as you can see at each corner there meet 3 different "faces". Each vertex of each face need a specific normal vector (the green lines). However since we only have one vertex at a corner we can only have one normal and also one set of UV coordinates in case you want texture it.
In the second case i draw an exploded view with proper vertices. As you can see now we have 30 vertices for the same mesh. However each face has it's own set of vertices. So the vertices "1, 10, 26" are actually at the same position. That's true for all the others as well. "2, 3, 27" "4, 5, 28" or "12, 13, 22". Now we can specify a seperate normal vector for each vertex and have the normal be the same across a face. If the normals aren't the same the surface of the face would appear "curved" when under lighting.
Your image also looks like you used an "unlit" shader. You should use a lit one as an unlit shader would shade everything with the same color, regardless of the vertex normal.
Here's the complete mapping of the vertices from the left figure to the right figure just to be clear what i mean.
left fig. right fig
1 - 1,10,26
2 - 2, 3,27
3 - 4, 5,28
4 - 6, 7,29
5 - 8, 9,30
6 - 11,20,21
7 - 12,13,22
8 - 14,15,23
9 - 16,17,24
10 - 18,19,25
That's the reason why a cube which has "8 logical" vertices needs "24" == 3 * 8. It's not always "3 times". Simply each face which is considered a seperate face that meet at a corner need it's own vertex at that corner.
Your answer
Follow this Question
Related Questions
How to fix a object intersection problem? 0 Answers
Modifying a Mesh at Runtime 1 Answer
How to determine shader center? 0 Answers