Texture atlas through texture indirection issues

Okay, I have a uniform grid of vertices in the typical bruteforce heightmap fashion, each vertex has only one set of attributes. That is, vertices are not unique on a per-cell basis. Now, what I do is map a texture onto this grid that exactly maps one texel to one cell. The texture uses GL_NEAREST sampling to achieve this. This texture then assigns a sub texture ID on a per-cell basis, this ID is then used to fetch from a texture atlas (so it is dependent texture fetch). Now, I’m running into issues with this, whenever the fraction for the subtexture is 0.0 (or 1.0 perhaps) I’m getting totally unrelated texture fetches, causing a “border” to render around each cell. I’ve tried EXPLICITLY clamping texture coordinates to fall within a tiny part of the sub texture without success. Is what I’m trying to do even possible?

Yes, it is possible. It’s called tile based texture mapping.
There are two issues you have to be aware of. First, and this is related to texture atlas in general, you have to arrange your subtextures so there is minimal bleeding between them. Otherwise sampling close to the edge of one tile will use texels from adjacent tiles for filtering, and this gets worse the smaller the mipmap. EXT_texture_array will mostly solve this problem in the future.

Second, you have to make sure you’re sampling from the right mipmap level. Since you do a texture fetch depending on the sub-texture ID, you get discontinuity edges for the texture coordinates. I.e. wherever the ID changes the texture coordinates “jump” from one tile to another. Usually the hardware uses the texcoord gradients to calculate the LOD, which means that at tile edges you often get one of the low-res mipmaps which causes artifacts.

You have to calculate the LOD in the shader using the derivatives (dFdx() and dFdy()) of the original, continuous texcoords. Then you can use that with texture2DLod()

Thanks for the reply.

I was getting borders between the same subtexture repeating, or even when making all the subtextures the same. I’ve managed to hack around the first issue (the same subtexture repeating), so that part works flawlessly with mipmapping.

So the issue now is clearly the discontinuity with the subtextures’ texture coordinates. I will certainly try using the derivates, although this seems awfully painful to fix such a “minor” graphical artifact. Perhaps there is a better way to handle this (like rendering transition regions over the discontinuity) ?

Oh, isn’t texture2DLod() only available in the vertex shader?

Oh, right, completely forgot about that.

ARB_shader_texture_lod and EXT_gpu_shader4 get rid of this limitation and also add a gradient lookup, texture2DGrad(), which is equivalent to texldd in D3D. Unfortunately the latter extension is only available on SM4 GPUs, and the former has not been released yet.

With unextended GLSL you could calculate the “real” and “virtual” LOD and use the difference as bias.

A better solution that fixes yet another problem (aliasing when tiles become smaller than a pixel) would be to pre-calculate a small version of your tiled texture. Then whenever you would access a low-res mipmap from your texture atlas, you use the precalculated tiled texture instead. This can be done by making the lower mip levels of the atlas/tileset texture transparent, and blending it with the precalculated texture. The downside is that this method needs more texture memory.

There are other methods that may be useful in specific circumstances (some mentioned in ShaderX5).

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.