I’ve scripted following meshes:
how to make the shading of them smooth? I’ve calculated normals for the meshes in the script, but it didn’t help.
I’ve scripted following meshes:
how to make the shading of them smooth? I’ve calculated normals for the meshes in the script, but it didn’t help.
What Material are you using on them? The normal diffuse shader should look smooth.
mesh.RecalculateNormals() doesn’t support smoothing.
You need to find the vertices that have the same position, take their normals, find the average and replace all these normals with the average one.
PS
But since your mesh is procedurally generated, I think it’s better to reconsider the generation algorithm the way you had only one vertex with one normal in each position, not multiple vertices with different normals.
In the following script I’ve tried to calculate the average normals for shared vertices:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CreateSphere : MonoBehaviour {
public int sections,slices;
public float radius;
int[] Triangles;
float sectionAngle,sliceAngle;
List<int> triangles=new List<int>();
List<Vector3> vertices=new List<Vector3>();
List<Vector2> uvs=new List<Vector2>();
List<KeyValuePair<float,float>> subRadii=new List<KeyValuePair<float, float>>();
List<List<int>> sharedVertices=new List<List<int>>();
Vector3[] sphereVertices;
Vector2[] sphereUvs;
Vector3[] normals;
Vector3[] normals1;
Vector4[] tangents;
int triangleCount;
// Use this for initialization
void Start () {
sliceAngle=360.0f/(slices*2);
sectionAngle=360.0f/sections;
subRadii=InitializeSubRadii();
vertices=InitializeVertices();
sharedVertices=InitializeSharedVertices();
print (vertices.Count);
print (sectionAngle);
uvs=InitializeUvs();
print (uvs.Count);
sphereVertices=new Vector3[2*(sections*3)+((slices-2)*(sections*6))];
sphereVertices=InitializeSphereVertices();
sphereUvs=new Vector2[2*(sections*3)+((slices-2)*(sections*6))];
sphereUvs=InitializeSphereUvs();
triangles=InitializeTriangles();
Triangles=triangles.ToArray();
triangleCount=Triangles.Length/3;
print (triangleCount);
normals=new Vector3[sphereVertices.Length];
normals=InitializeNormals();
normals1=new Vector3[vertices.Count];
normals1=InitializeNormals1();
//InitializeSphere();
//MeshFilter filter= gameObject.AddComponent("MeshFilter");
//MeshRenderer renderer=gameObject.AddComponent("MeshRenderer");
Mesh mesh=GetComponent<MeshFilter>().sharedMesh;
mesh.Clear();
mesh.vertices=sphereVertices;
mesh.uv=sphereUvs;
mesh.triangles = Triangles;
mesh.normals=normals;
//mesh.RecalculateNormals();
mesh.Optimize();
mesh.normals=normals;
print (mesh.vertices.Length);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
renderer.material=Resources.Load("mat1",typeof(Material))as Material;
}
// Update is called once per frame
void Update () {
transform.Rotate(Vector3.up * Time.deltaTime*40);
}
List<Vector3> InitializeVertices()
{
List<Vector3> vertices1=new List<Vector3>();
Vector3 vertex=new Vector3(0,radius,0);
vertices1.Add(vertex);
for(int i=1;i<slices;i++){
for(int j=0;j<sections;j++){
float radius1=subRadii[i-1].Key;
float x=radius1*Mathf.Cos(Mathf.Deg2Rad*(sectionAngle*j));
float y=subRadii[i-1].Value;
float z=radius1*Mathf.Sin(Mathf.Deg2Rad*(sectionAngle*j));
vertex=new Vector3(x,y,z);
vertices1.Add(vertex);
}
}
vertex=new Vector3(0,-radius,0);
vertices1.Add(vertex);
return vertices1;
}
List<Vector2> InitializeUvs()
{
List<Vector2> uvs1=new List<Vector2>();
Vector2 uv1=new Vector2(0.5f,0.0f);
float a=1.0f/sections;
float k=1.0f/slices;
uvs1.Add(uv1);
for(int i=1;i<slices;i++){
for(int j=0;j<=sections;j++){
float b=subRadii[i-1].Key;
float d=b/radius;
float c=(1-(d))/2;
float x=1-(j*a);
uv1=new Vector2(x,i*k);
uvs1.Add(uv1);
}
}
uv1=new Vector2(0.5f,1.0f);
uvs1.Add(uv1);
return uvs1;
}
List<KeyValuePair<float,float>> InitializeSubRadii()
{
float subRadius;
float subHeight;
List<KeyValuePair<float,float>> subRadii1=new List<KeyValuePair<float,float>>();
for(int a=1;a<slices;a++)
{ subRadius=radius*Mathf.Cos(Mathf.Deg2Rad*(sliceAngle*-a+(((slices/2))*sliceAngle)));
subHeight=radius*Mathf.Sin(Mathf.Deg2Rad*(sliceAngle*-a+(((slices/2))*sliceAngle)));
subRadii1.Add(new KeyValuePair<float,float>(subRadius,subHeight));
}
return subRadii1;
}
List<int> InitializeTriangles()
{
List<int> triangles=new List<int>();
for(int i=0;i<sphereVertices.Length;i++)
{
triangles.Add(i);
}
return triangles;
}
List<List<int>> InitializeSharedVertices()
{
List<List<int>> sharedVertices=new List<List<int>>();
for(int i=0;i<vertices.Count;i++)
{
sharedVertices.Add(new List<int>());
}
return sharedVertices;
}
Vector3[] InitializeSphereVertices()
{
Vector3[] sphereVertices=new Vector3[2*(sections*3)+((slices-2)*(sections*6))];
int k=3;
int l=1;
int c=vertices.Count;
int cC=sphereVertices.Length;
int q=sections*k;
int r=6;
for(int i=1;i<slices;i++){
for(int j=0;j<sections;j++){
if(i==1){
sphereVertices[(j*k)+1]=vertices[0];
sharedVertices[0].Add((j*k)+1);
sphereVertices[(j*r)+q]=vertices[l];
sharedVertices[l].Add((j*r)+q);
sphereVertices[j*k]=vertices[l];
sharedVertices[l].Add(j*k);
if(j>0){
sphereVertices[j*k-1]=vertices[l];
sharedVertices[l].Add(j*k-1);
sphereVertices[q+((j-1)*r)+1]=vertices[l];
sharedVertices[l].Add(q+((j-1)*r)+1);
sphereVertices[q+((j-1)*r)+3]=vertices[l];
sharedVertices[l].Add(q+((j-1)*r)+3);
}
else if(j==0){
sphereVertices[q-1]=vertices[l];
sharedVertices[l].Add(q-1);
sphereVertices[3*q-5]=vertices[l];
sharedVertices[l].Add(3*q-5);
sphereVertices[3*q-3]=vertices[l];
sharedVertices[l].Add(3*q-3);
}
}
else if(i>1 i<(slices-1)){
sphereVertices[(j*r)+(q*2*(i-2))+(q-1)+3]=vertices[l];
sharedVertices[l].Add((j*r)+(q*2*(i-2))+(q-1)+3);
sphereVertices[(j*r)+(q*2*(i-2))+(q-1)+6]=vertices[l];
sharedVertices[l].Add((j*r)+(q*2*(i-2))+(q-1)+6);
sphereVertices[(j*r)+(q*2*(i-1))+(q-1)+1]=vertices[l];
sharedVertices[l].Add((j*r)+(q*2*(i-1))+(q-1)+1);
if(j>0){
sphereVertices[(j*r)+(q*2*(i-2))+(q-1)-1]=vertices[l];
sharedVertices[l].Add((j*r)+(q*2*(i-2))+(q-1)-1);
sphereVertices[((j-1)*r)+(q*2*(i-1))+(q-1)+2]=vertices[l];
sharedVertices[l].Add(((j-1)*r)+(q*2*(i-1))+(q-1)+2);
sphereVertices[((j-1)*r)+(q*2*(i-1))+(q-1)+4]=vertices[l];
sharedVertices[l].Add(((j-1)*r)+(q*2*(i-1))+(q-1)+4);
}
else if(j==0)
{
sphereVertices[(q*2*(i-1))+(q-1)-1]=vertices[l];
sharedVertices[l].Add((q*2*(i-1))+(q-1)-1);
sphereVertices[(q*2*i)+(q-1)-2]=vertices[l];
sharedVertices[l].Add((q*2*i)+(q-1)-2);
sphereVertices[(q*2*i)+(q-1)-4]=vertices[l];
sharedVertices[l].Add((q*2*i)+(q-1)-4);
}
}
else if (i>=(slices-1)){
sphereVertices[(q-1)+((i-1)*q*2+(j*k)+2)]=vertices[c-1];
sharedVertices[l].Add((q-1)+((i-1)*q*2+(j*k)+2));
sphereVertices[(q-1)+((i-1)*q*2+(j*k)+3)]=vertices[l];
sharedVertices[l].Add((q-1)+((i-1)*q*2+(j*k)+3));
sphereVertices[(q-1)+((i-2)*q*2)+(j*r)+3]=vertices[l];
sharedVertices[l].Add((q-1)+((i-2)*q*2)+(j*r)+3);
sphereVertices[(q-1)+((i-2)*q*2)+(j*r)+r]=vertices[l];
sharedVertices[l].Add((q-1)+((i-2)*q*2)+(j*r)+r);
if(j>0){
sphereVertices[(q-1)+((i-1)*q*2+(j*k)-2)]=vertices[l];
sharedVertices[l].Add((q-1)+((i-1)*q*2+(j*k)-2));
sphereVertices[(q-1)+((i-2)*q*2+(j*r)-1)]=vertices[l];
sharedVertices[l].Add((q-1)+((i-2)*q*2+(j*r)-1));
}
else if(j==0){
sphereVertices[cC-3]=vertices[l];
sharedVertices[l].Add(cC-3);
sphereVertices[(q-1)+((i-1)*q*2)-1]=vertices[l];
sharedVertices[l].Add((q-1)+((i-1)*q*2)-1);
}
}
l++;
}
}
return sphereVertices;
}
Vector2[] InitializeSphereUvs()
{
Vector2[] sphereUvs=new Vector2[2*(sections*3)+((slices-2)*(sections*6))];
int k=3;
int l=1;
int c=uvs.Count;
int cC=sphereVertices.Length;
int q=sections*k;
int r=6;
for(int i=1;i<slices;i++){
for(int j=0;j<=sections;j++){
if(i==1 j<sections){
sphereUvs[(j*k)+1]=uvs[0];
sphereUvs[(j*r)+q]=uvs[l];
sphereUvs[j*k]=uvs[l];
if(j>0 ){
sphereUvs[j*k-1]=uvs[l];
sphereUvs[q+((j-1)*r)+1]=uvs[l];
sphereUvs[q+((j-1)*r)+3]=uvs[l];
}
else if(j==0){
sphereUvs[q-1]=uvs[l+sections];
sphereUvs[3*q-5]=uvs[l+sections];
sphereUvs[3*q-3]=uvs[l+sections];
}
}
else if(i>1 i<(slices-1) j<sections){
sphereUvs[(j*r)+(q*2*(i-2))+(q-1)+3]=uvs[l];
sphereUvs[(j*r)+(q*2*(i-2))+(q-1)+6]=uvs[l];
sphereUvs[(j*r)+(q*2*(i-1))+(q-1)+1]=uvs[l];
if(j>0){
sphereUvs[(j*r)+(q*2*(i-2))+(q-1)-1]=uvs[l];
sphereUvs[((j-1)*r)+(q*2*(i-1))+(q-1)+2]=uvs[l];
sphereUvs[((j-1)*r)+(q*2*(i-1))+(q-1)+4]=uvs[l];
}
else if(j==0)
{
sphereUvs[(q*2*(i-1))+(q-1)-1]=uvs[l+sections];
sphereUvs[(q*2*i)+(q-1)-2]=uvs[l+sections];
sphereUvs[(q*2*i)+(q-1)-4]=uvs[l+sections];
}
}
else if (i>=(slices-1) j<sections){
sphereUvs[(q-1)+((i-1)*q*2+(j*k)+2)]=uvs[c-1];
sphereUvs[(q-1)+((i-1)*q*2+(j*k)+3)]=uvs[l];
sphereUvs[(q-1)+((i-2)*q*2)+(j*r)+3]=uvs[l];
sphereUvs[(q-1)+((i-2)*q*2)+(j*r)+r]=uvs[l];
if(j>0 j<sections){
sphereUvs[(q-1)+((i-1)*q*2+(j*k)-2)]=uvs[l];
sphereUvs[(q-1)+((i-2)*q*2+(j*r)-1)]=uvs[l];
}
else if(j==0){
sphereUvs[cC-3]=uvs[l+sections];
sphereUvs[(q-1)+((i-1)*q*2)-1]=uvs[l+sections];
}
}
l++;
}
}
return sphereUvs;
}
void Print(Vector3[] array)
{
for(int i=0;i<array.Length;i++){
print (array[i]);
print(i);
}
}
Vector3[] InitializeNormals()
{
Vector3[] normals= new Vector3[sphereVertices.Length];
Vector3[] normals1=new Vector3[vertices.Count];
for(int i=0;i<triangleCount;i+=3)
{
Vector3 A=sphereVertices[i];
Vector3 B=sphereVertices[i+1];
Vector3 C=sphereVertices[i+2];
Vector3 v1=B-A;
Vector3 v2=C-A;
Vector3 normal =Vector3.Cross(v1,v2);
normal.Normalize();
normals[i]=normal;
normals[i+1]=normal;
normals[i+2]=normal;
}
for(int i=0;i<sharedVertices.Count;i++)
{
for(int j=0;j<sharedVertices[i].Count;j++)
{
int index=sharedVertices[i][j];
normals1[i]+=normals[index];
}
}
int c=0;
for(int i=0;i<sharedVertices.Count;i++)
{
for(int j=0;j<sharedVertices[i].Count;j++)
{
normals[c]=normals1[i];
print(normals[c]);
c++;
}
}
return normals;
}
Vector3[] InitializeNormals1()
{
Vector3[] normals1=new Vector3[vertices.Count];
for(int i=0;i<sharedVertices.Count;i++)
{
for(int j=0;j<sharedVertices[i].Count;j++)
{
int index=sharedVertices[i][j];
normals1[i]+=normals[index];
}
//print (normals1[i]);
}
return normals1;
}
}
Is the calculation of normals done somehow wrong?
Ok, thanks alexzzzz, I erased recalculateNormals from the script and now my script works.
But now another error occurs. The meshes generated in the scipt don’t react properly to the lighting:
Your normals are either not-normalized or completely wrong.
If the center of the sphere lies in Vector3.zero, then proper normals calculation is trivial:
var normals = new Vector3[vertices.Length];
for (var i = 0; i < vertices.Length; i++)
{
normals[i] = vertices[i].normalized;
}
mesh.normals = normals;
PS
Some shaders also require tangents. If you use that kind of shader and don’t provide tangents, you’ll also get weird lighting.
Consider removing mesh.Optimize() too. It consumes time but the benefit is not obvious. I haven’t noticed any performance difference between optimized and not-optimized meshes (but of cause it doesn’t mean there is no difference it your case.)