1
\$\begingroup\$

I'm currently using marching cubes to generate a mesh, and have encountered this incredibly weird problem.

Looking from below the terrain, these weird fully lit lines appear between every triangle. And from above, these are black. Moving closer does not remove these lines.

What could be causing these artifacts?

Marching Cubes

std::vector<glm::vec3> triangles;

glm::vec3 pos(0, 0, 0);
for (int x = 0; x < t_width - 1; x++)
for (int y = 0; y < t_height - 1; y++)
for (int z = 0; z < t_depth - 1; z++)
{
    glm::float4 cubeCorners[8] = {
        m_scalar_field[x][y][z],
        m_scalar_field[x + 1][y][z],
        m_scalar_field[x + 1][y][z + 1],
        m_scalar_field[x][y][z + 1],
        m_scalar_field[x][y + 1][z],
        m_scalar_field[x + 1][y + 1][z],
        m_scalar_field[x + 1][y + 1][z + 1],
        m_scalar_field[x][y + 1][z + 1]
    };

    int cubeindex = 0;
    for (int i = 0; i < 8; i++)
    {
        if (cubeCorners[i].w <= m_scalar_median)
        {
            cubeindex |= 1 << i;
        }
    }

    if (m_edge_table[cubeindex] != 0)
    {
        glm::float3 vertexList[12];
        if (m_edge_table[cubeindex] & 1)
            vertexList[0] =
            linearInterp(m_scalar_median, cubeCorners[0], cubeCorners[1]);
        if (m_edge_table[cubeindex] & 2)
            vertexList[1] =
            linearInterp(m_scalar_median, cubeCorners[1], cubeCorners[2]);
        if (m_edge_table[cubeindex] & 4)
            vertexList[2] =
            linearInterp(m_scalar_median, cubeCorners[2], cubeCorners[3]);
        if (m_edge_table[cubeindex] & 8)
            vertexList[3] =
            linearInterp(m_scalar_median, cubeCorners[3], cubeCorners[0]);
        if (m_edge_table[cubeindex] & 16)
            vertexList[4] =
            linearInterp(m_scalar_median, cubeCorners[4], cubeCorners[5]);
        if (m_edge_table[cubeindex] & 32)
            vertexList[5] =
            linearInterp(m_scalar_median, cubeCorners[5], cubeCorners[6]);
        if (m_edge_table[cubeindex] & 64)
            vertexList[6] =
            linearInterp(m_scalar_median, cubeCorners[6], cubeCorners[7]);
        if (m_edge_table[cubeindex] & 128)
            vertexList[7] =
            linearInterp(m_scalar_median, cubeCorners[7], cubeCorners[4]);
        if (m_edge_table[cubeindex] & 256)
            vertexList[8] =
            linearInterp(m_scalar_median, cubeCorners[0], cubeCorners[4]);
        if (m_edge_table[cubeindex] & 512)
            vertexList[9] =
            linearInterp(m_scalar_median, cubeCorners[1], cubeCorners[5]);
        if (m_edge_table[cubeindex] & 1024)
            vertexList[10] =
            linearInterp(m_scalar_median, cubeCorners[2], cubeCorners[6]);
        if (m_edge_table[cubeindex] & 2048)
            vertexList[11] =
            linearInterp(m_scalar_median, cubeCorners[3], cubeCorners[7]);

        for (int i = 0; m_tri_table[cubeindex][i] != -1; i += 3) {
            triangles.push_back(vertexList[m_tri_table[cubeindex][i]]);
            triangles.push_back(vertexList[m_tri_table[cubeindex][i + 1]]);
            triangles.push_back(vertexList[m_tri_table[cubeindex][i + 2]]);
        }
    }
}

return triangles;

Calculate Normals

std::vector<GLfloat> CubeMarcher::calculateNormals(const std::vector<glm::vec3> t_triangles)
{
    std::vector<GLfloat> normals;
    normals.resize(t_triangles.size() * 3);

    for(int i = 0; i < t_triangles.size(); i+= 3)
    {
        glm::vec3 normal = calulateNormal(
            t_triangles[i],
            t_triangles[i + 1],
            t_triangles[i + 2]
        );

        normals[i * 3] = normal.x;
        normals[i * 3 + 1] = normal.y;
        normals[i * 3 + 2] = normal.z;
    }

    return normals;
}

glm::vec3 CubeMarcher::calulateNormal(const glm::vec3 t_vertex1, const glm::vec3 t_vertex2, const glm::vec3 t_vertex3)
{
    glm::vec3 normal;

    glm::vec3 u = t_vertex2 - t_vertex1;
    glm::vec3 v = t_vertex3 - t_vertex1;

    normal = glm::cross(u, v);

    return normal;
}

Vertex Shader

#version 400 core

in vec3 position;
in vec3 normal;

out vec3 pass_Color;
out vec3 surface_normal;
out vec3 to_light;

uniform mat4 projectionMatrix;
uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
uniform vec3 color;

void main()
{
    vec4 worldPosition = transformationMatrix * vec4(position, 1.0);
    gl_Position = projectionMatrix * viewMatrix * worldPosition;
    pass_Color = color;
    surface_normal = (transformationMatrix * vec4(normal, 0.0)).xyz;
    to_light = lightPosition - worldPosition.xyz;
}

Fragment Shader

#version 400 core

in vec3 pass_Color;
in vec3 surface_normal;
in vec3 to_light;

out vec4 out_Color;

void main(void){

    vec3 ambient = vec3(0.1, 0.1, 0.1);
    vec3 normal = normalize(surface_normal);
    vec3 light = normalize(to_light);

    float dotP = dot(normal, light);
    float brightness = max(dotP, 0.0);
    vec3 diffuse = (brightness + ambient) * pass_Color;

    out_Color = vec4(diffuse, 1.0);
}

Above

enter image description here

Below

enter image description here

EDIT I decided to render to a flat color as recommended in the comments. But neither looking from above or below the mesh shows any seams.

enter image description here

EDIT 2 Without glEnable(GL_CULL_FACE) enter image description here

With glEnable(GL_CULL_FACE) https://i.imgur.com/nk2w11x.png

\$\endgroup\$
  • 1
    \$\begingroup\$ I get why the lines might appear black when looking at them from the top, there are simply small holes between the triangles, but the bright lines are strange. Do they still appear if you turn back face culling on? \$\endgroup\$ – Bálint May 9 at 0:29
  • \$\begingroup\$ There could be extra geometry there. Is it possible that faces have been created using the points on the line? \$\endgroup\$ – Jay May 9 at 6:42
  • \$\begingroup\$ @Bálint back culling was on in both screenshots. \$\endgroup\$ – GigaNova May 9 at 8:02
  • \$\begingroup\$ As @Bálint indicates, this problem is more likely with your source geometry than with your shaders. If you modify your fragment shader to just output a simple flat colour, you'd likely see the same issue occur. You'll need to review the code that generates your source geometry. \$\endgroup\$ – Maximus Minimus May 9 at 12:38
  • \$\begingroup\$ @Maximus Minimus I have rendered to a flat color but this seems just fine. See the example screenshot above. \$\endgroup\$ – GigaNova May 9 at 15:21
1
\$\begingroup\$

So, I looked through all my code again and again and noticed missing normals. Then it finally dawned on me:

normals[i * 3] = normal.x;
normals[i * 3 + 1] = normal.y;
normals[i * 3 + 2] = normal.z;

Had to be:

normals[i * 3] = normal.x;
normals[i * 3 + 1] = normal.y;
normals[i * 3 + 2] = normal.z;

normals[i * 3 + 3] = normal.x;
normals[i * 3 + 4] = normal.y;
normals[i * 3 + 5] = normal.z;

normals[i * 3 + 6] = normal.x;
normals[i * 3 + 7] = normal.y;
normals[i * 3 + 8] = normal.z;

So the ultimate problem was missing normals.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.