# How should I fix a graphic glitch caused by t-junctions when using greedy meshing

As you might be able to see in the following image, a "graphic glitch" occurs between triangles. I know you are able to make this less visible by enabling anti-aliasing but i was wondering if there is another way to fix this issue.

This is how my wireframe looks (not the same area):

So the problem is caused by "T-junktions". But for my case, this isn't easy to fix. This is the way I create my meshes, it works as the greedy meshing algorithm but then my own version.

First I calculate the faces for each block.

if(current.front){//If this block has a front face continue
int x2 = x;
int y2 = y;

//while the next block in the x direction contains a front face and has equal properties, combine the faces
while(x2 < CHUNK_SIZE && m_pBlocks[x2][y][z].front && m_pBlocks[x2][y][z].getBlockType() == current.getBlockType() && m_pBlocks[x2][y][z].getBlockData() == current.getBlockData() && AOInfoPerBlock[x2][y][z].hasEqualAO(info, FRONT)){
m_pBlocks[x2][y][z].front = false;
x2++;
}
//while the next block in the y direction contains a front face and has equal properties, combine the faces
y2++;
while(y2 < CHUNK_HEIGHT){
int x3 = x;
while(x3 < x2){
if(m_pBlocks[x3][y2][z].front && m_pBlocks[x3][y2][z].getBlockType() == current.getBlockType() && m_pBlocks[x3][y][z].getBlockData() == current.getBlockData() && AOInfoPerBlock[x3][y2][z].hasEqualAO(info, FRONT)){
m_pBlocks[x3][y2][z].front = false;
x3++;
}else{
for(int x4 = x3-1; x4 >= x; x4--){
m_pBlocks[x4][y2][z].front = true;
}
break;
}
}
if(x3 == x2){
y2++;
}else{
break;
}
}
if(x2 > x){//If the mesh exists out of one x block, it has gone one to far
x2--;
}
if(y2 > y){//If the mesh exists out of one y block, it has gone one to far
y2--;
}

if(info.f1 + info.f3 > info.f0 + info.f2) { //If this block should be flipped for the screen space ambient occlusion, render in flipped order
/*1*/ vertPos.push_back(Vertex(x * BLOCK_RENDER_SIZE                        , y2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE , z * BLOCK_RENDER_SIZE                        , /*D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f1 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*2*/ vertPos.push_back(Vertex(x2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE   , y2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE , z * BLOCK_RENDER_SIZE                        , /*D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f2 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*3*/ vertPos.push_back(Vertex(x2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE   , y * BLOCK_RENDER_SIZE                     , z * BLOCK_RENDER_SIZE                     , /*D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f3 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*0*/ vertPos.push_back(Vertex(x * BLOCK_RENDER_SIZE                        , y * BLOCK_RENDER_SIZE                     , z * BLOCK_RENDER_SIZE                     , /*D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f0 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));

}else{
/*0*/ vertPos.push_back(Vertex(x * BLOCK_RENDER_SIZE                        , y * BLOCK_RENDER_SIZE                     , z * BLOCK_RENDER_SIZE                     , /*D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f0 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*1*/ vertPos.push_back(Vertex(x * BLOCK_RENDER_SIZE                        , y2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE , z * BLOCK_RENDER_SIZE                        , /*D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f1 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*2*/ vertPos.push_back(Vertex(x2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE   , y2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE , z * BLOCK_RENDER_SIZE                        , /*D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f2 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));
/*3*/ vertPos.push_back(Vertex(x2 * BLOCK_RENDER_SIZE + BLOCK_RENDER_SIZE   , y * BLOCK_RENDER_SIZE                     , z * BLOCK_RENDER_SIZE                     , /*D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f)/*/color * ((1.0f - 0.8f) + (info.f3 * 0.8f) / (float)3), D3DXVECTOR3(0.0f, 0.0f, -1.0f)));

}
indices.push_back(index++);
indices.push_back(index++);
indices.push_back(index++);
indices.push_back(index-3);
indices.push_back(index-1);
indices.push_back(index++);
}


The same thing is used for each face

• I'm no game dev (yet) but I would guess that you could put below a second texture which fills that gaps. – rekire Oct 26 '14 at 16:29
• @rekire yeah, the thing is, I don't use textures – Duckdoom5 Oct 26 '14 at 16:50
• Are you rendering using indexed vertices? If not two overlapping vertices could be creating these artifacts. – Soapy Oct 27 '14 at 12:26
• @Soapy Yes, that is indeed what causes it, that is because I can't combine those meshes. But I was wondering if there was something that could fix this issue. – Duckdoom5 Oct 28 '14 at 11:21
• @Duckdoom5 Can you provide a wireframe view of the image you posted? Do you know if any of your meshes have varying shapes for the plane with the artifacts? I suspect you have triangle edges with separate points that are logically collinear, but due to vertex snapping or rounding issues, result in slightly different sets of rasterized pixels. – MooseBoys Oct 30 '14 at 0:28

Ok, given the wireframe view, it is clear that your problem is T-junctions. Remove them and the artifacts will go away. If you provide information on how you get/generate the meshes, you could get help on how to remove them as well :)

• This is the right answer. Even if your vertices create triangle edges that are mathematically collinear, depending on where the endpoints land, they might be snapped to slightly different values, and every once in a while you'll end up with a pixel sample point missing on both sides. – MooseBoys Oct 31 '14 at 16:09
• I've added my meshing algorithm to the op. – Duckdoom5 Nov 5 '14 at 18:11
• The problem is not easy to fix because of the algorithm that you use. Use something standard and bug-free, and the t-junctions will go away. – Babis Nov 6 '14 at 8:21

Technically, that's a gap, not an overlap. An overlap would not result in the background colour. So, two of the vertices that are supposed to be in an identical position, are not.

If you can't combine the meshes, then make sure that the values are exactly the same (all bits equal). That means being very careful of what values you store in you vertex buffers and how you modify your vertices in the vertex/hull/domain/geometry shader (to any that applies to you).

• I would not advise trying to match vertices up, not only does the size of your buffer increase with duplicate values but it can cause other graphics glitches further down the line, one example I can think of is lighting where you would want the normals to be uniform. – Soapy Oct 29 '14 at 13:15
• if the vertices are bitwise identical and the normals are derived from the vertices, the normals will be identical too. Additionally, the normals looks pretty much the same; pointing upwards :) OP says can't combine the different meshes, so doing it properly (sharing the vertices) is apparently not an option. – Babis Oct 29 '14 at 17:27
• A very common reason for non-identical geometry in a Minecraft-like is instead of generating the geometry as a whole, there's a set of cube faces which are translated around the scene, leaving cracks all over the place. – Lars Viklund Oct 30 '14 at 15:11
• good point. Perhaps if the cubes are scaled by something like 1.00001, they would overlap and the gaps would go away – Babis Oct 30 '14 at 18:35