Issues with triangle seams


I’m having issues with triangle seams when rendering meshes. It seems that some triangle borders are being split when rendered as showin in the pictures.

This seems to be some king of rendering artifacts produced by number precision loss.

The meshes are built with independent triangles, which are then sent to the GPU through VBO assigned to a VAO, and then rendered in an array of single vertices using:

glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, 0);

this lines seem to disappear when I disable the antialisiang process (glRenderbufferStorageMultisample)

is there any known solution to this?


I’ve searched, and came across other people with this “pixel gap” issue, where the main cause seems to be having different vertex position between shared vertices.

but I’ve already solved this issue by stitching the vertices to the exactly sam position, but even then, this problem persists.

Averaging all the shared vertices position:

for(Vertex v: s.stitched) {
  1. Is the vertex shader doing anything which could result in identical input positions producing non-identical output positions?
  2. Are you using alpha-based anti-aliasing ( GL_POLYGON_SMOOTH) as well as multi-sampling?

Otherwise, I’d check that both vertices forming the edge really are identical. This will probably require adding some code to let you visually pick the triangles involved.

  1. Is the vertex shader doing anything which could result in identical input positions producing non-identical output positions?

Well, VS is just the regular VS there is doing the typical

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

  1. Are you using alpha-based anti-aliasing ( GL_POLYGON_SMOOTH) as well as multi-sampling?

I explicitly disabled it glDisable(GL_POLYGON_SMOOTH); but, I am using a multisamples Frame buffer, could it be because of that?

glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);

When using 0 samples, instead of 8, I find way more difficult to find any pixel gap, but when using antialised rendering, there are more gaps in the mesh.

Regarding your last observation, I’m explicitly setting the neighbour vertices to be the same value, but I’m afraid that with the transformations happening during the rendering that some of them could chage more than the other, no?

By the way, I’m scaling this mesh by 80x, could this have add to impact?

Well, it could be related, but multi-sampling doesn’t inherently create gaps. Is the fragment shader doing anything specific to multi-sampling? Is it doing anything for which sample locations exactly on the triangle’s edge would be problematic?

No. If you take identical values and apply an identical sequence of calculations to them, you get identical results.

Ok, so from debugging as you pointed out tracing the triangles, turns out its from the shader, I’m drawing the fog in the shader using the z buffer distance, so it turns out that the zbuffer is yielding out the maximum value but the fragment is returning a texture sample pixel color as if it is there.

here’s 2 cases, rendering with fog being drawn:

and without fog:

and a simple frag shader from the Z Buffer Intesified 10x to be clearer using the following:

float dz 	 = gl_FragCoord.z / gl_FragCoord.w;
gl_FragColor = pow(1.0/dz, 10.0);
gl_FragColor.a = 1.0;

and here, just a plain

gl_FragColor = vec4(0.0);
gl_FragColor.a = 1.0;

and no gaps, so my conclusion is that there’s something wrong with z-buffer? is is possible? or the real issus is masked somewhere

Is the upper triangle above the problematic edge edge-on to the viewpoint? Because I can see how that could cause this issue. The GLSL specification states:

If the sample point is outside the triangle, and the triangle is edge-on (meaning that ∂P/∂y is very large), the interpolated (or rather, extrapolated) depth at the sample location could be far from any value inside the triangle.

If that’s what’s happening, you should be able to fix the issue by storing in a vertex shader output variable, and adding the centroid qualifier to the corresponding fragment shader input variable. Variables with the centroid qualifier are required to be interpolated at a point which lies inside both the primitive and the pixel. From that, you can reconstruct the depth value (note that gl_FragCoord.z has been transformed from the [-1,1] range used by NDC to the [0,1] range used by depth values).