How to stop edge artifacts when using a spritesheet / textureatlas

edited January 2018 in Library Questions

As the title says, i'm using one big texture and using tex coords for each face of a block. However there are some artifacts along the edges of each face. I've been trying to figure out this problem for a while now. I've tried offsetting the texture index by a small margin which slightly fixed the problem but at a far enough render distance the problem appears again.

and a closer view:

Here is my code that handles where to get the coordinates from the texture atlas. https://github.com/Xenthera/AlphaBlock/blob/testBranch/src/com/bobby/TextureManager.java

Also to get the texture to appear crisp i'm disabling texture sampling.

Here's what it looks like with texture sampling which is curious because you can still see the "artifact" being interpolated across the edge of the face.

Help :P

Tagged:

Answers

  • edited January 2018

    To whomever moved this thread to Library Questions please move it back as this does not deal with any external libraries to processing.

    Thanks -X

  • can you edit the image to highlight exactly what you're talking about. because 'the artifact' doesn't really tell us what the problem is.

  • Sure thing...

  • On an Nvidia card it's much worse :( Enlarge the image to see what i'm talking about

  • given the complete lack of code, i tried recreating it

    import peasy.*;
    
    PeasyCam cam;
    PImage tex;
    
    void setup() {
      size(1200, 800, P3D);
      cam = new PeasyCam(this, 500);
      // image is 256 x 768
      tex = loadImage("texture.png");
      noStroke();
    }
    
    final static int S = 100; // length of side
    final static int T = 256; // texture size
    
    // three adjacent quads, each using a 1/3 of the texture
    void draw() {
      background(0);
      beginShape(QUAD);
      texture(tex);
      vertex(S * 1.5, S * .5, 0, 0, 0);
      vertex(S * 1.5, -S * .5, 0, 0, T);
      vertex(S * 0.5, -S * .5, 0, T, T);
      vertex(S * 0.5, S * .5, 0, T, 0);
      endShape(CLOSE);
      beginShape(QUAD);
      texture(tex);
      vertex(S * 0.5, S * .5, 0, T, 0);
      vertex(S * 0.5, -S * .5, 0, T, T);
      vertex(-S * 0.5, -S * .5, 0, 2 * T, T);
      vertex(-S * 0.5, S * .5, 0, 2 * T, 0);
      endShape(CLOSE);
      beginShape(QUAD);
      texture(tex);
      vertex(-S * 0.5, S * .5, 0, 2 * T, 0);
      vertex(-S * 0.5, -S * .5, 0, 2 * T, T);
      vertex(-S * 1.5, -S * .5, 0, 3 * T, T);
      vertex(-S * 1.5, S * .5, 0, 3 * T, 0);
      endShape(CLOSE);
    }
    

    no artifacts at all

    Untitled

  • if i had to guess at the difference between my code and yours i'd go for noStroke() as the insulting first guess and the float rounding of the texture coords for second.

  • edited January 2018

    Please look at my code here: https://github.com/Xenthera/AlphaBlock/blob/testBranch/src/com/bobby/blocks/construction/BlockGeometry.java

    and here

    https://github.com/Xenthera/AlphaBlock/blob/testBranch/src/com/bobby/TextureManager.java

    I'm using TRIANGLE mode to draw the textures do you think if I re-wrote that part of my code to use quad rendering that it would remove the issue?

    Also this is where I determine the faces to construct

    https://github.com/Xenthera/AlphaBlock/blob/testBranch/src/com/bobby/Chunk.java#L171-L214

  • I'll try to write a simple demo to reproduce the artifacts i'm seeing as my minecraft clone project is getting a little large to sift through..

  • edited January 2018
    individualTextureSize = imageSize/16;
    

    what's imageSize? is this just an integer division problem?

  • image size is the size of the spritesheet which is 256. 256/16 = 16... So no problem there...

    appreciate the troubleshooting help though

  • edited January 2018

    This demonstrates is quite nicely

    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;
    
    
    PShape s;
    PImage spriteSheet;
    PeasyCam cam;
    
    void setup() {
      cam = new PeasyCam(this, 500);
      size(600, 600, P3D);
      ((PGraphicsOpenGL)g).textureSampling(2);
      spriteSheet = loadImage("terrain.png");
      s = createShape();
      s.beginShape(TRIANGLE);
      s.texture(spriteSheet);
      s.noStroke();
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          constructFace(i, j,2,1);
        }
      }
      s.endShape();
    }
    
    void draw() { 
      background(255);  
    
      scale(50);
      translate(-4, -4);
      shape(s);
    }
    
    void constructFace(int x, int y, int texX, int texY) {
      s.vertex(x    , y    , 0,  0 + (texX * 16),  0 + (texY * 16));    
      s.vertex(x + 1, y    , 0, 16 + (texX * 16),  0 + (texY * 16)); 
      s.vertex(x + 1, y + 1, 0, 16 + (texX * 16), 16 + (texY * 16)); 
      s.vertex(x    , y    , 0,  0 + (texX * 16),  0 + (texY * 16));    
      s.vertex(x + 1, y + 1, 0, 16 + (texX * 16), 16 + (texY * 16));
      s.vertex(x    , y + 1, 0,  0 + (texX * 16), 16 + (texY * 16));
    }
    

    Does the same exact thing with QUAD instead of TRIANGLE

    import peasy.*;
    import peasy.org.apache.commons.math.*;
    import peasy.org.apache.commons.math.geometry.*;
    
    
    PShape s;
    PImage spriteSheet;
    PeasyCam cam;
    
    void setup() {
      cam = new PeasyCam(this, 500);
      size(600, 600, P3D);
      ((PGraphicsOpenGL)g).textureSampling(2);
      spriteSheet = loadImage("terrain.png");
      s = createShape();
      s.beginShape(QUAD);
      s.texture(spriteSheet);
      s.noStroke();
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
          constructFace(i, j,2,1);
        }
      }
      s.endShape();
    }
    
    void draw() { 
      background(255);  
    
      scale(50);
      translate(-4, -4);
      shape(s);
    }
    
    void constructFace(int x, int y, int texX, int texY) {
      s.vertex(x    , y    , 0,  0 + (texX * 16),  0 + (texY * 16));    
      s.vertex(x + 1, y    , 0, 16 + (texX * 16),  0 + (texY * 16)); 
      s.vertex(x + 1, y + 1, 0, 16 + (texX * 16), 16 + (texY * 16));    
      s.vertex(x    , y + 1, 0,  0 + (texX * 16), 16 + (texY * 16));
    
    }
    

  • add noSmooth(); to setup()

  • it's the antialiasing that's applied by default, partially transparent pixels between the quads.

  • Right after I made that demo I realized I didn't have AA off. I thought it fixed the problem for a second but then realized it still has some artifacts showing at shallower angles, which in the voxel game itself still looks rather bad.

  • edited January 2018

    noSmooth() at the end of setup() appears to work for me

    with noSmooth():

    frame511

    without:

    frame438

  • With noSmooth() on do the same test and look at the plane at a shallow angle you still get this:

  • Answer ✓

    looks ok. this is a different computer (and operating system) from last night but i'm pretty sure that i didn't see anything last night either, and i did swing it around a lot.

    terrain

    i think this is getting into the realms of system differences - hardware, operating systems, drivers, global settings...

  • Well i'm sure there's some obscure opengl setting I can tweak to make it perfect but for now it looks much better. Thanks for the help! :)

  • Those links appear to be about images with alpha channel, which none of these do.

  • edited January 2018

    @koogs he? the articles are about tile maps, mine craft and PNGs, pixel perfect aliment . but yes probability disable the mip map filtering will to the trick.

    http://mikolalysenko.github.io/voxel-mipmap-demo/

    just brainstorming.

    useless comment, im sorry

Sign In or Register to comment.