TextureAtlas Bleeding

Hello,

I am working on creating a tile-based map editor. I am attempting to use the TextureAtlas class to allow the tiles to all share the same material in order to merge all the tiles together into one geometry that I can then export to use in another application.

The problem is that the empty (black) part of the texture atlas causes bleeding in the form of black lines. This happens regardless of mip-map settings and even when the tile textures are the exact same color. Is there anyway to fix this problem? I thought I read somewhere that bleeding shouldn’t occur when using this class as long as I didn’t try to use repeating / wrapped textures.

Here is a test case to demonstrates the problem:

[java]
public class TextureAtlasTestApp extends SimpleApplication {

public static void main(final String[] args) {
    TextureAtlasTestApp app = new TextureAtlasTestApp();
    app.start();
}

@Override
public void simpleInitApp() {
    flyCam.setMoveSpeed(25f);

    Quad quadAMesh = new Quad(1f, 1f);
    Quad quadBMesh = new Quad(1f, 1f);

    /* Create a geometry for each 'tile' */
    Geometry tileA = new Geometry("TileA", quadAMesh);
    Geometry tileB = new Geometry("TileB", quadBMesh);
    
    tileA.rotate(-90f * FastMath.DEG_TO_RAD, 0f, 0f);
    tileB.rotate(-90f * FastMath.DEG_TO_RAD, 0f, 0f);
    
    tileB.setLocalTranslation(1f, 0f, 0f);
    
    TextureAtlas textureAtlas = new TextureAtlas(32, 64);

    /* Load the texture for each tile and add it to the TextureAtlas */
    textureAtlas.addTexture(assetManager.loadTexture("Textures/tileAtex.png"), "ColorMap");
    textureAtlas.addTexture(assetManager.loadTexture("Textures/tileBtex.png"), "ColorMap");
    
    /* Create a material and set its ColorMap to the texture from the TextureAtlas */
    Material atlasMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    textureAtlas.getAtlasTexture("ColorMap").setMinFilter(MinFilter.Trilinear);
    
    atlasMaterial.setTexture("ColorMap", textureAtlas.getAtlasTexture("ColorMap"));

    tileA.setMaterial(atlasMaterial);
    tileB.setMaterial(atlasMaterial);

    /* Apply the proper coordinates for each texture to the tile meshes */
    textureAtlas.getAtlasTile(assetManager.loadTexture("Textures/tileAtex.png")).transformTextureCoords(quadAMesh.getFloatBuffer(Type.TexCoord), 0, quadAMesh.getFloatBuffer(Type.TexCoord));
    textureAtlas.getAtlasTile(assetManager.loadTexture("Textures/tileBtex.png")).transformTextureCoords(quadBMesh.getFloatBuffer(Type.TexCoord), 0, quadBMesh.getFloatBuffer(Type.TexCoord));

    rootNode.attachChild(tileA);
    rootNode.attachChild(tileB);
}

}
[/java]
Note: You’ll have to provide your own 32x32 textures in order to run it. I used two identical solid-pink colored textures and this is the result:

That is probaly not bleeding, as it can only occur if there are differnet colord textures. With two identical ones it should not be possible(or better visible) at all.

Hmm could it be that the coordinates generated by the TextureAtlasTile are slightly off? This is still a problem even if I use the exact same texture from the atlas on both quads.

This is mipmapping / blurring and expected behavior, you’d need a border around the single textures or disable mipmapping.

1 Like
<cite>@normen said:</cite> This is mipmapping / blurring and expected behavior, you'd need a border around the single textures or disable mipmapping.

Thanks for the reply. I’m not sure I know how to disable MipMaps in order to fix the problem. I have tried:

    textureAtlas.getAtlasTexture("ColorMap").setMinFilter(MinFilter.BilinearNoMipMaps);
    textureAtlas.getAtlasTexture("ColorMap").setMinFilter(MinFilter.NearestNoMipMaps);
    textureAtlas.getAtlasTexture("ColorMap").setMagFilter(MagFilter.Nearest);
    textureAtlas.getAtlasTexture("ColorMap").setAnisotropicFilter(0);

But the result is the same. Not sure what I’m doing wrong.

What I don’t understand is if the size of the texture atlas is 32x64 and the two textures are 32x32 the entire atlas image should be pink (because both textures are solid pink). How is it that the MipMap sampling could come up with any result other than solid pink? It seems to me that no matter what, regardless of MipMap level, it should always sample a solid pink pixel (because every pixel in the texture atlas is pink). I’m obviously nowhere near an expert on this so if you could help me understand it a little better I would be very grateful.

Also, when you say "add a border around the single textures? Does this mean I need to add it programmatically to the texture atlas? I assume that if I add the border to the actual images that will just change the coordinates generated by the texture atlas and I’d still have the same problem.

You create a new texture each time you call getAtlasTexture(). The atlas is only pink where a texture is placed.

1 Like
<cite>@normen said:</cite> You create a new texture each time you call getAtlasTexture(). The atlas is only pink where a texture is placed.

I get it now.

I stored the Texture object returned from getAtlasTexture(“ColorMap”) and set the MinFilter to BilinearNoMipMaps and the MagFilter to Nearest which fixed the problem.

Thanks for clearing that up Norman.