1
\$\begingroup\$

I'm making a game in OpenGL with C++.

I have a problem with my vertices or texture coordinates - there's a seam visible on the sphere where the texture wraps around:

Seam visible on sphere

If I use "nearest" filtering, the result is better, but it does not completely fix the issue:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

A few pixels of the wrong colour are still visible on the seam

The line is thinner with this, but not fixed. In debug mode, I can see the issue with the blue line that seems to be the start of the texture before:

error

I can bypass the issue using a isophere, but this doesn't fix anything. I want to use all blender shapes. (I have the same issue with the torus shape)

In Blender, there is no visible issue:

error

I use textures of size 256*256, with a texture atlas:

error

I convert the texture coordinates with this code:

for (int x = textureStart ; x < textureSize; x++) {
    if (counterForWidth % 2 == 0) {
        shape.texturesCoordonateNoSorts.at(x) = (shape.texturesCoordonateNoSorts.at(x) + currentTextureId) / (GLfloat)bigTexture.pointsTextures.size();
    }
    counterForWidth++;
}

I modify the texture coordinate (Axis X), using the currentId of the texture, and divide by the total amount of textures.

How can I fix this?

\$\endgroup\$
4
  • \$\begingroup\$ Do you observe the same issue if you use a power of two number of textures and texture size for your atlas? Dividing by 13 is not perfectly representable in floating point, so you may be getting a small rounding error here. \$\endgroup\$
    – DMGregory
    Dec 28, 2023 at 14:24
  • \$\begingroup\$ I thinks you right about the rouding error but have power of two, doesn't seem to fix the issue, i have try with 14. If i try to use double and not float do you think that can work ? Have you another ideas for fixing this ? \$\endgroup\$
    – Gaëtan S
    Dec 28, 2023 at 15:05
  • \$\begingroup\$ 14 is not a power of two — it includes a factor of 7, which also doesn't divide neatly in binary. Powers of two are 0, 1, 2, 4, 8, 16, 32, 64... \$\endgroup\$
    – DMGregory
    Dec 28, 2023 at 17:06
  • \$\begingroup\$ That seems to have no effect \$\endgroup\$
    – Gaëtan S
    Dec 28, 2023 at 17:30

2 Answers 2

1
\$\begingroup\$

Texture atlases aren't ideal for 3D models - you tend to get artefacts like the one you've seen if you need to wrap or clamp the texture coordinates. Supporting that requires some careful shader modification to handle them correctly.

What's probably happening along your seam is that you have two vertices with very different UVs right next to each other. This will cause the GPU to pick the smallest possible mipmap for a few pixels along that seam (because of the huge UV gradient), and the smallest mip map won't be a sensible colour.

Also note that you can run into similar problems with bilinear texture filtering too, because that can cause texture samples to read into adjacent atlas textures for UVs that are close to the edge.

Possible solutions:

  • Avoid using a texture atlas for cases where the texture needs to wrap or clamp. Note that most 3D modelling programs assume that textures wrap.
  • As you're using a 1D texture atlas, you could make the seam align with the top and bottom of the texture, and not the left and right, and enable wrapping / clamping in that direction. This won't help if you need to wrap / clamp in both directions though.
  • To alleviate some of the issues with mip maps, you can reduce the number of mips for the texture to 8, so the smallest mip has a height of 1, and a width of 13 in this case. Mips smaller than that won't contain useful data. This won't completely fix the problem on it's own though.
  • You could even remove all of the mip maps, but that will cause aliasing and hurt performance.
  • You can modify the pixel shader to do wrapping / clamping on the UVs. To get it to look correct at the seams, you'll need to make use of the ddx and ddy functions along with SampleGrad.

See https://download.nvidia.com/developer/NVTextureSuite/Atlas_Tools/Texture_Atlas_Whitepaper.pdf for more detailed discussion on making texture atlases work nicely.

\$\endgroup\$
0
\$\begingroup\$

I had solve this issue using the method of Adam, avoid using a texture atlas.

Of course this need few changes to work, but i think it's better to do this for lots of things, like the issue encounter here and for me when i was using texture atlas, the max size of a texture limits me (texture with sfml), growing very quickly if i want to use 4k texture.

So now i use one texture per shape, all shapes are in a object.

Thanks you for all your answers.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .