Grey Lines Around the Edges of Transparent Images

edited September 2016 in GLSL / Shaders

When I draw an image with transparent edges, the renderer (I am using P3D) is drawing a thin grey line around the border of the image, which is visible despite the fact that the edges of the image are transparent. There are also some other wierd grey lines around various images. Does anyone know how to fix this?

I have found other posts about this issue on the processing forum: https://forum.processing.org/one/topic/transparent-png-issue.html And of this and similar issues on openGl forums: https://opengl.org/discussion_boards/showthread.php/167808-2D-texture-problem-lines-between-textures https://opengl.org/discussion_boards/showthread.php/178038-Black-lines-at-edges-of-textures

The post on the processing forum does not have a solution (and isn't really the same problem). It seems there might be a way to fix this by adjusting OpenGL settings, but I don't know how to do that with processing. I am using OpenGL because I have to render a very large number of pixels in 3D space every frame, and I doubt other renderers will work as well. Here are some images (I scaled some of these up to show the problem, the lines are all exactly 1 pixel in the original (they seem to actual be one pixel on my retina display, not one processing pixel):

Screen Shot 2016-09-19 at 6.21.35 PM

Screen Shot 2016-09-19 at 6.31.56 PM

The lines in the middle of these images are added by the renderer, they are at the edge of a partially transparent image.

Screen Shot 2016-09-19 at 6.17.20 PM

This is the border between two images (each drawn on a textured polygon, with uv mapping). The black line in the middle is not part of either image. That line is not on the edge of where the image is being drawn, but on the edge of the opaque part of an image. This image also has a line on the very edge.

Screen Shot 2016-09-19 at 6.21.35 PM copy

The borders between some textures without any transparency still get weird lines.

Answers

  • edited September 2016

    Can you please post some code that we can run to see the problem on our own machines? (Preferably as an MCVE). Please include the image file we need as well.

  • I tried to make an MCVE, and I finally figured out how to replicate this. The lines are cause by textureWrap being set to repeat, which will add one pixel from the opposite edge of the image to the other side when it is drawn at non-integer co-ordinates. I don't know why textureWrap() should affect drawing an image, but it does. Here is the code:

    PImage background;
    PImage testImage;
    void setup() {
      size(200, 200, P3D);
      surface.setResizable(true);
      background = loadImage("Back.png");
      testImage = loadImage("Test1.png");
    }
    void draw() {
      textureWrap(REPEAT);
      pushMatrix();
      translate(-100, -100, -100);
      scale(4, 4);
      image(background, 0, 0);
      popMatrix();
      image(testImage, 50, 50.5);
    }
    

    The images I am using are this one for the background "Back.png"

    Back

    And the image I used "Test1.png"

    Test1

    When the code is run, a black line appears above the image.

    Screen Shot 2016-09-21 at 7.20.39 PM

    This does not resolve the problem with textured images:

    PImage background;
    PImage testImage;
    void setup() {
      size(200, 200, P3D);
      surface.setResizable(true);
      background = loadImage("Back.png");
      testImage = loadImage("Test1.png");
    }
    void draw() {
      textureWrap(REPEAT);
      pushMatrix();
      translate(-100, -100, -100);
      scale(4, 4);
      image(background, 0, 0);
      popMatrix();
      image(testImage, 50, 50);
      beginShape();
      texture(testImage);
      vertex(70, 60, 0, 0);
      vertex(100, 60, 30, 0);
      vertex(100, 110, 30, 50);
      vertex(70, 110, 0, 50);
      endShape();
    }
    

    The image used as a texture still has lines around it, regardless of textureWrap.

  • Thanks for the MCVE.

    Like you pointed out, this is caused by using a non-int variable for your image coordinates. So the simplest fix is to just convert them to int values:

    image(testImage, int(50), int(50.5));
    

    If you're trying to change render settings, the first place to look would be the not-very-documented hint() function. The values you can pass into this function are defined at the bottom of the PConstants class. I doubt any of these will fix the problem, but it's the first place you should check.

    If you need to dive deeper into the OpenGL settings, then you're going to have to import classes from the com.jogamp.opengl package and use the jogl api to change the low-level settings. Here is a little example that changes the settings based on one of the links you included in your post:

    //at top of sketch
    import com.jogamp.opengl.GL3;
    import com.jogamp.opengl.GLContext;
    
     //in setup()
     GL3 gl3 = ((PSurfaceJOGL)surface).pgl.gl.getGL3();
    
      gl3.glTexParameteri( GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE );
      gl3.glTexParameteri( GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE );
    

    Note that this doesn't seem to fix your problem, but it at least shows you how to change the OpenGL settings. Finding the correct setting might involve going through the JOGL API.

    I also came across this forum post and this guide on advanced OpenGL in Processing that might help you.

    But if I were you, I'd just do the int conversion and call it a day.

  • edited September 2016

    Yah, that seems like the easiest thing to do. I think those opengl commands are specifically for the textured image problem, so I will try that as well.

  • I found that using

    ((PGraphicsOpenGL)g).textureSampling(2);

    Fixed the problems with textured images, but it changed the way everything else was working. I tried to turn it off with

    ((PGraphicsOpenGL)g).textureSampling(5);

    when I didn't want it. But that made the grey lines appear again. I guess changing the texture mode repeatedly just doesn't work. (I think it renders with whatever renderer is on at the end of draw()) So I tried to draw all the things that need the different texture sampling in a different pgraphics object, but I can't find a way to change the textureSampling mode of that pgraphics. If anyone knows how to do this, the help would be appreciated.

Sign In or Register to comment.