1
\$\begingroup\$

All of a sudden, I started having this problem. I've used libGDX + Photoshop before and never had this problem. One of my textures is showing up with a white border/glow around.

enter image description here

The texture is the black blob on the middle, which is a 256 pixels png with a few black brushstrokes I created with Photoshop, just to test it.

Everything in libGDX is on default. I haven't changed the blending function, I'm just using a SpriteBatch to render the image without any changes.

The weird thing is, some other textures I created with Photoshop, same size, RBG 8 bit color mode (just like my blob image), look fine. These are temporary textures I created by downloading a png from the web, pasting it into Photoshop, applying a solid color overlay effect to it and saving it back as a png.

Any idea what's causing this?

Edit: Here's how I'm loading my textures:

private static Texture createTexture(String fileName, boolean maxQuality, Texture.TextureWrap textureWrap) {
    Texture result = new Texture(Gdx.files.internal(fileName), true);
    result.setFilter(maxQuality ? Texture.TextureFilter.MipMapLinearLinear : Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Linear); // TODO: Are these the best?
    if(textureWrap != null)
        result.setWrap(textureWrap, textureWrap);
    return result;
}

texture = new TextureRegion(createTexture("data/blob.png"));

I just found out using this technique that the transparent pixels in my texture are white (1, 1, 1, 0). So I'm pretty sure the cause is a combination of this, the linear resizing and probably the blending function. Not sure what's the right way to fix it though. Don't want to change the resizing to nearest.

\$\endgroup\$
  • \$\begingroup\$ Is the texture coming from a packed spritesheet? Are you using a TextureAtlas? \$\endgroup\$ – bornander Feb 25 '16 at 12:26
  • \$\begingroup\$ Probably because you have some alpha blending pixels at the edge of your sprite. \$\endgroup\$ – jgallant Feb 25 '16 at 12:31
  • \$\begingroup\$ @bornander No atlas. See my edit. \$\endgroup\$ – Juan Feb 25 '16 at 12:47
  • \$\begingroup\$ Change the pixels to 0,0,0,0. When additive blending is used- the white pixels will be added to the background and result in that white border. \$\endgroup\$ – Felsir Feb 26 '16 at 8:12
2
\$\begingroup\$

So I figured it out and found a couple of ways to solve it.

Cause:

Photoshop, for some reason, will produce white transparent pixels. And when libGDX resizes the pictures it seems to average the pixels, so if a pixel is {1, 1, 1, 0} (transparent white) and another is {1, 0, 0, 1} (red), the average would be {1, .5, .5, .5}, which is a semi transparent mix of white and red and looks whitish on a dark background:

white borders

Solution 1:

One way is to premultiply the image, which turns transparent pixels black, using Texture Packer or some other program. This solves the white border on a dark background problem:

enter image description here

But it'll create another problem when using a bright background. Since the default blending functions are GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA, which tells OpenGL to multiply the source image's value times its alpha and add it to the background's value times one minus the source's alpha, blending a mix or red and transparent black caused by image resizing {.5, 0, 0, .5} with a white background {1, 1, 1, 1} will produce {.75, .5, .5, .75}, which is a mix of red, black and white, and looks like a dark border around the texture:

premultiplied GL_SRC_ALPHA

The solution here is to change the blending functions to GL_ONE and GL_ONE_MINUS_SRC_ALPHA (using setBlendFunction is you're using a SpriteBatch). This tells OpenGL to multiply the source's value by one, which will produce {1, .5, .5, 1}, an actual mix of red and white, when blending the mix of red and transparent black {.5, 0, 0, .5} with the white background {1, 1, 1, 1}:

premultiplied GL_ONE

Solution 2:

What I ended up doing is using Texture Packer to reduce border artifacts. This will replace each transparent pixel with the color of a neighbor non-transparent pixel and will work fine with the default blending function on any background.

The reason I used this solution is simply because I already use the default blending mode on every other place. I guess the way to go is to pick one solution and stick to it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.