# OpenGL - white edges on cubes

In a minecraft-like game I'm making, I get white edges on my cubes:

It is much more noticeable in darker textures. The textures are being setup like this: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Any help?

• Can you show some code on how you render each cube and how you place cubes? Dec 19 '12 at 2:03
• Does wrapping the textures do anything different? What does the texture look like/size that you're binding to? Dec 19 '12 at 2:34
• I just wanted to point out that I've seen this also take place in large texture atlases, that use small tiles. As an example, say you have a 1024*1024 tileset/atlas, and your using tiles of 32*32. You get rounding errors because the decimal point that maps to said tile is a very small double. This makes precision near impossible. A solution? Break up the tile atlas into individual tiles. This is what Minecraft does, or used to do. They had one big tileset, and at runtime they chopped it up into individual textures. Apr 9 '19 at 7:55

There are two possible causes for this type of problem, depending on exactly which problem it is. I'll list both:

### 1. You are seeing other colors from your texture along the edges of the tiles.

This looks to me like the problem in this case, because all of the edge pixels are one of three colors which are plausibly in your texture: white, black, and brown.

If you are using multiple tile images right next to each other in a single texture (a texture atlas), as I assume you are doing, this is inevitable. It occurs because the GPU does not perfectly match up interpolation along the edge of a triangle with interpolation along the texture, and you get little bits of the adjacent texture.

There are a number of things you can do.

• Use an array texture instead of a texture atlas. An array texture is made up of “layers” that are (in this case) 2D images of the same size, and you specify a third coordinate to select one; it is intended exactly as a replacement for texture atlases without the filtering problem.

Caveat: if you want to use many tiles, you may find that your GPU may not support large enough array textures to use them without any atlasing at all.

• Generate a 1-pixel border in each of your texture tiles, which replicates the color of the adjacent regular pixel. (This is essentially reimplementing GL's CLAMP[_TO_EDGE], but in a way which is aware of texture atlases — your use thereof has no effect because most of your tile edges are not at the edge of the texture.) This is the solution I use in my own entry in the genre, All is Cubes (combined with array texturing for maximum capacity).

Caveat: Mipmapping, if you use it, effectively blurs the texture, so texels even further outside of the tile than 1 pixel will be sampled and you will see artifacts. This effect can be reduced by using even larger borders, at the cost of more texture memory, or you can manually generate and upload mipmaps that don't cross tile boundaries.

• Very slightly inset your texture coordinates, so that they do not go all the way to the edge of the texture tile. Doing this too much will lead to a noticeable thinness of the edges of the texture compared to pixels in the middle. It also does not help with mipmapping.

• Use a single texture per tile type. This imposes texture-switching costs.

### 2. You are seeing through gaps between tiles.

I don't think this is the problem in this case, since there is no green ground seen through the gaps, but I'm including it for completeness.

This can occur when you are not providing exactly the same coordinates for the vertices of the meeting edges of adjacent tiles, which usually arises due to floating-point error. For example, if you have tiles of size 0.6 and compute the right edge of the tile at x=100 with (100*0.6) + 0.6, and the left edge of the tile at x=101 with (100*0.6), you will not get the exact same answer, and the difference can be visible as little specks of gaps.

The solution is to ensure that your arithmetic is consistent; some ways to do this are:

• Make sure you are not (even indirectly) computing index*size + size, but only (index+1)*size.
• Make sure that your arithmetic is exact; the easiest way to do this is to make your tile size exactly 1.0, which will result in exact integer arithmetic even if you do your calculations with 32-bit floats (up to 16 million blocks from the origin, anyway). Any power of 2 (1, 2, 4, 8, … or 0.5, 0.25, 0.125, …) will also be exact in this way.
• Use actual integers for vertex coordinate calculations; this gets you even more range.
• Looks like gaps to me - no texture bleeding (unless it's quite some high res texture) considering the tiny and sharp bits. Dec 19 '12 at 10:34
• Thanks, insetting the texture coordinates by a bit seems to fix it. Dec 19 '12 at 12:52
• @Mario I assume this is with NEAREST magnification - note the sharp border on the interior of the tile. So for that perspective, it's an infinite resolution texture. Dec 19 '12 at 17:44