# OpenGL Lines between triangles?

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;
}


#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;
}


#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

Below

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.

EDIT 2 Without glEnable(GL_CULL_FACE)

With glEnable(GL_CULL_FACE)

• 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? May 9, 2019 at 0:29
• There could be extra geometry there. Is it possible that faces have been created using the points on the line?
– Jay
May 9, 2019 at 6:42
• @Bálint back culling was on in both screenshots. May 9, 2019 at 8:02
• 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. May 9, 2019 at 12:38
• @Maximus Minimus I have rendered to a flat color but this seems just fine. See the example screenshot above. May 9, 2019 at 15:21

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;


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.