Sunday, June 11, 2017

opengl - How to avoid texture bleeding in a texture atlas?


In my game there is a Minecraft-like terrain made out of cubes. I generate a vertex buffer from the voxel data and use a texture atlas for looks of different blocks:


texture atlas for voxel based terrain



The problem is that the texture of distant cubes interpolates with adjacent tiles in the texture atlas. That results in lines of wrong colors between cubes (you may need to view the screenshot below at its full size to see the graphical flaws):


screenshot of terrain with stripes of the wrong color


For now I use these interpolation settings but I tried every combination and even GL_NEAREST without mipmapping doesn't provide better results.


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

I also tried added an offset in the texture coordinates to pick a slightly smaller area of the tile but since the unwanted effect depends on the distance to the camera this cannot solve the problem completely. At far distances the stripes occur anyway.


How can I solve this texture bleeding? Since using a texture atlas is popular technique there might be a common approach. Sadly, for some reasons explained in the comments, I cannot change to different textures or texture arrays.




Answer



After struggling a lot with this issue, I finally came up with a solution.


To use both, a texture atlas and mipmapping, I need to perform the downsampling myself, because OpenGL would otherwise interpolate over the boundaries of tiles in the atlas. Moreover I needed to set the right texture parameters, because interpolating between mipmaps would also cause texture bleeding.


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

With these parameters, no bleeding occurs.


There is one thing you have to notice when providing custom mipmaps. Since it doesn't make sense to shrink the atlas even if each tile is already 1x1, the maximal mipmap level must be set according to what you provide.


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); // pick mipmap level 7 or lower


Thanks for all other answers and very helpful comments! By the way I still do not know how to use linear up scaling, but I guess there is no way.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...