Fixing seams between quads on a custom mesh

I’m building a custom meshes for 2D tiled terrain and Fog of War, the mesh is generated as a collection of quads, and the texture coordinates are modified to reflect which tile the quad is supposed to be. I’m using three such meshes, one for the actual layer of tiles, one for a layer of tiles that was last seen through the fog of war (uses a transparent texture to reveal sprites between this layer and the tile layer), and one for a top layer which is either black, half alpha black or clear depending on if the player has ever seen though it before, or is seeing through it now. Unfortunately at some zoom levels, seams appear in the top layer(s) and the lower layers are visible through pixel-wide gaps. My initial reaction was to make the tiles slightly larger (0.1-1%), and this works perfectly for the tile layer itself (and the middle layer) but on the top layer, it causes double the alpha blending on some tile boundaries, which looks almost opposite as a revealing pixel, a darker line of pixels.

What would the best way to fix these problems be? I can post code, but I have a lot of it and pruning it to just the problem may be difficult, or screenshots if my description isn’t clear, let me know.

So many things could be happening here. I don’t even know where to start.

How are your quads constructed?

How is your scene constructed?

How are your materials constructed?

It could be one of about 20 different things, really.

I’m confused about why you are using scaling…

Are you saying that the camera is able to zoom and you see the artifacting based on distance to camera?

If so, likely is just the clamping method you chose or how close the sprites are in the texture. i.e. If your transparent sprite is right beside your non transparent sprite(s), you’re likely seeing the edges of the adjacents just due to how texture sampling works.

If I missed the boat on this (which happens often)… sorry =)

…unless he’s actually got separate Quad geometries, all locally 0,0,0 based and then translated into position… there will be all kinds of rounding errors.

I wasn’t kidding when I said I could think of 20 things that could cause this. Just not enough info yet.

So, pruning did not go well, My project is not too large, but it’s several inter-related classes and several assets that are required to get it working, so I zipped the whole project and uploaded it HERE. (EDIT: zip has been updated) The related mesh is generated in matrixpeckham.zombiegame.map.MapChunk.generateMesh(). Which I will paste below, because I assume it’s the most relevant thing.

The things in the matrixpeckham.zombiegame.sprites package can be ignored as they are not relevant. I hope my code is commented enough to follow, and I do apologize for its size.

@t0neg0d The scaling I mention is not scaling in the normal geometric sense, during my initial test it was just one the tiles, when the seams appeared, I changed from generating a tile in model coordinates as (-tileSize/2 + tileCoordX,0,-tileSize/2+tileCoordZ) through (tileSize/2 + tileCoordX,0,tileSize/2+tileCoordZ) which I changed to this : (-tileSize/2 * eps + tileCoordX,0,-tileSize/2eps+tileCoordZ) through (tileSize/2eps + tileCoordX,0,tileSize/2*eps+tileCoordZ) where eps = 1.01 this causes the tiles to overlap very, slightly, and on solid tiles it does cause issues, but with semitransparent tiles it does.

It is true the problem could be in a number of places, it could possibly be between two of the chunks of my map. Unfortunately I don’t see a way to share vertices between quads in this scenario because two adjoining quads can have very different texture coordinates. Here is the actual mesh creation code:
[java] private Mesh generateMesh(float len){
Mesh mesh = new Mesh();
final int VERTS_PER_TILE = 4;
final int NUM_PER_VERT = 3;
final int NUM_PER_TEXT = 2;
final int INDS_PER_TILE = 6;
int numTiles = chunkSizechunkSize;//field for tiles per side of chunk
FloatBuffer verts = BufferUtils.createFloatBuffer(numTiles
VERTS_PER_TILENUM_PER_VERT);
FloatBuffer norms = BufferUtils.createFloatBuffer(numTiles
VERTS_PER_TILENUM_PER_VERT);
FloatBuffer texts = BufferUtils.createFloatBuffer(numTiles
VERTS_PER_TILENUM_PER_TEXT);
IntBuffer inds = BufferUtils.createIntBuffer(numTiles
INDS_PER_TILE);

    int vertInd = 0;
    int normInd = 0;
    int indInd = 0;
    int uvInd = 0;
    int indAdd = 0;
    float eps = 1.00f;//EPS OF 1.01 causes opposite problem
    float xf = 0;
    for(int xi = 0; xi<chunkSize; xi++){
        float yf = 0;
        for(int yi = 0; yi<chunkSize; yi++){
            //VERT 1
            verts.put(vertInd++, xf);
            verts.put(vertInd++, 0);
            verts.put(vertInd++, yf);
            //VERT 2
            verts.put(vertInd++, xf);
            verts.put(vertInd++, 0);
            verts.put(vertInd++, yf+len*eps);
            //VERT 3
            verts.put(vertInd++, xf+len*eps);
            verts.put(vertInd++, 0);
            verts.put(vertInd++, yf+len*eps);
            //VERT 4
            verts.put(vertInd++, xf+len*eps);
            verts.put(vertInd++, 0);
            verts.put(vertInd++, yf);

            //NORM1
            norms.put(normInd++,0);
            norms.put(normInd++,1);
            norms.put(normInd++,0);
            //NORM2
            norms.put(normInd++,0);
            norms.put(normInd++,1);
            norms.put(normInd++,0);
            //NORM3
            norms.put(normInd++,0);
            norms.put(normInd++,1);
            norms.put(normInd++,0);
            //NORM4
            norms.put(normInd++,0);
            norms.put(normInd++,1);
            norms.put(normInd++,0);
            
            //UV1
            texts.put(uvInd++,0);
            texts.put(uvInd++,0);
            //UV2
            texts.put(uvInd++,0);
            texts.put(uvInd++,1);
            //UV3
            texts.put(uvInd++,1);
            texts.put(uvInd++,1);
            //UV4
            texts.put(uvInd++,1);
            texts.put(uvInd++,0);
            
            inds.put(indInd++,0+indAdd);
            inds.put(indInd++,1+indAdd);
            inds.put(indInd++,2+indAdd);
            inds.put(indInd++,0+indAdd);
            inds.put(indInd++,2+indAdd);
            inds.put(indInd++,3+indAdd);
            
            indAdd+=4;
            
            yf+=len;
        }
        xf+=len;
    }
    
    mesh.setBuffer(VertexBuffer.Type.Position, 3, verts);
    mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, texts);
    mesh.setBuffer(VertexBuffer.Type.Index, 3, inds);
    mesh.setBuffer(VertexBuffer.Type.Normal, 3, norms);
    mesh.updateBound();
    return mesh;
}

[/java]

Again sorry about the large amount of code in the project, I’m hoping that someone can give me some pointers for what to look for. Thanks for taking the time to help me out.

EDIT: I realized that I had not included the JSON parsing stuff. In order to run the project you will need to remove the dependency to a project named BasicJSON. This project was simply the http://json.org/java/ implementation I threw into a project. I updated the .zip file and now the sources from http://json.org/java/ are included directly, however I did not remove the dependency. Sorry about the mistake.