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\$
8
  • 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 '19 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 '19 at 6:42
  • \$\begingroup\$ @Bálint back culling was on in both screenshots. \$\endgroup\$
    – GigaNova
    May 9 '19 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\$ May 9 '19 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 '19 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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .