1

I'm working on an implementation of the Marching Cubes algorithm in Unity. I just implemented smooth shading to my mesh and now I'm getting some weird lighting effects. I'm new to this algorithm and I admit I don't really know what I'm doing to well however, I am pretty experienced with perlin noise. Here's my marching cube class that does everything (I REMOVED THE TRIANGULATION TABLE FOR THIS EXAMPLE):

    public bool smoothTerrain;
    public bool flatShaded;

    private List<Vector3> vertices = new List<Vector3>();
    private List<int> triangles = new List<int>();

    private MeshFilter meshFilter;

    private float terrainSurface = 0.5f;
    private float noiseScale = 0.09f;
    private int size = 30;

    private void Awake() {

        meshFilter = GetComponent<MeshFilter>();
        CreateMeshData();
        BuildMesh();

    }

    void CreateMeshData() {

        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {
                for (int z = 0; z < size; z++) {

                    float[] cube = new float[8];
                    for (int i = 0; i < 8; i++) {
                            
                        Vector3Int corner = new Vector3Int(x, y, z) + CornerTable[i];
                        cube[i] = Noise.Perlin3D(corner.x * noiseScale + 100000f, corner.y * noiseScale + 300000f, corner.z * noiseScale + 500000f);

                    }

                    MarchCube(new Vector3Int(x, y, z), cube);

                }
            }
        }

    }

    int GetCubeConfiguration(float[] cube) {

        int configurationIndex = 0;
        for (int i = 0; i < 8; i++) {

            if (cube[i] > terrainSurface)
                configurationIndex |= 1 << i;

        }

        return configurationIndex;

    }

    int VertForIndice(Vector3 vert) {

        for (int i = 0; i < vertices.Count; i++) {

            if (vertices[i] == vert)
                return i;

        }

        vertices.Add(vert);
        return vertices.Count - 1;

    }

    void MarchCube(Vector3Int position, float[] cube) {

        int configIndex = GetCubeConfiguration(cube);
        
        if (configIndex == 0 || configIndex == 255)
            return;

        int edgeIndex = 0;
        for (int i = 0; i < 5; i++) {
            for (int p = 0; p < 3; p++) {

                int indice = TriangleTable[configIndex, edgeIndex];

                if (indice == -1)
                    return;

                Vector3 vert1 = position + CornerTable[EdgeIndexes[indice, 0]];
                Vector3 vert2 = position + CornerTable[EdgeIndexes[indice, 1]];
                
                Vector3 vertPosition;
                if (smoothTerrain) {
                    
                    float vert1Sample = cube[EdgeIndexes[indice, 0]];
                    float vert2Sample = cube[EdgeIndexes[indice, 1]];

                    float difference = vert2Sample - vert1Sample;

                    if (difference == 0)
                        difference = terrainSurface;
                    else
                        difference = (terrainSurface - vert1Sample) / difference;

                    vertPosition = vert1 + ((vert2 - vert1) * difference);
                } else {

                    vertPosition = (vert1 + vert2) / 2f;

                }

                if (flatShaded) {
                    vertices.Add(vertPosition);
                    triangles.Add(vertices.Count - 1);
                } else {
                    triangles.Add(VertForIndice(vertPosition));
                }
                
                edgeIndex++;

            }
        }

    }

    void ClearMeshData() {
        
        vertices.Clear();
        triangles.Clear();

    }

    void BuildMesh() {

        Mesh mesh = new Mesh();
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.RecalculateNormals();
        meshFilter.mesh = mesh;

    }

    Vector3Int[] CornerTable = new Vector3Int[8] {

        new Vector3Int(0, 0, 0),
        new Vector3Int(1, 0, 0),
        new Vector3Int(1, 1, 0),
        new Vector3Int(0, 1, 0),
        new Vector3Int(0, 0, 1),
        new Vector3Int(1, 0, 1),
        new Vector3Int(1, 1, 1),
        new Vector3Int(0, 1, 1)

    };

    int[,] EdgeIndexes = new int[12, 2] {

        {0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6}, {7, 6}, {4, 7}, {0, 4}, {1, 5}, {2, 6}, {3, 7}

    };

If anyone would be able to help or at least send me off with some ideas in the right direction on why I'm having these lighting issues it would be great. I'll leave some screenshots to show you what's going on.weird lightingentire meshwireframe

Dr Rob Lang
  • 6,659
  • 5
  • 40
  • 60
cooldev
  • 41
  • 4
  • 1
    Where you have sharp changes in lighting, that usually means that you have two vertices at exactly the same position when you only need one. – Dr Rob Lang Apr 14 '23 at 09:35
  • @DrRobLang I checked I have no duplicate vertices. I also have a function now that limits how close a vertex can be to another vertex but I still get weird lighting. On my directional light I played with the Bias and Normal Bias but, nothing works. Maybe would you know of any good tutorials for marching cubes in Unity? – cooldev Apr 14 '23 at 14:19

0 Answers0