how to prevent banding?

Started by
5 comments, last by Matt Aufderheide 15 years, 1 month ago
Im useless seemless textures, which look great, but when you get a certain distance away, the illusion is blown, and am getting horrible banding, making it seem very obvious that the textures are tiled. Im using tiled textures for items like terrian and water. Where i have a mesh specified in meter units, and textures designed to be one meter in size. So 100 meters of land is the Uvs * 100. But the banding shows when looking into the distance. Are there any ways around this sort of problem?
Advertisement
I think there are a few techniques for this. A simple one is just to have textures of various detail levels and then combine them. Search for megatexture and uh, I think clipmapping or something like that. Never done it myself, so hopefully an expert will show and give you more info. =)
While there are many ways to solve the problem of visible tiling on terrains, most involve using multi-texturing to reduce the effect.

An easy way: just sample your texture twice in a pixel shader: once at normal size and once at a much larger size, then combine (lerp) them based on a distance value. It looks better than you'd think.

Or use a macro texture (a big texture that doesnt repeat) and combine it with the tiled texture, fading out detail textures at a distance, just as above.

You can also use some noise, like multiple octaves of perlin noise, to add non-tiling structure.

I dont reccomend trying to implement clipmaps or megatextures as you need special tools to generate such large textures...
Thanks for the replies guys.

Im currently using multitexturing, but the banding is still visible.

Quote:An easy way: just sample your texture twice in a pixel shader: once at normal size and once at a much larger size, then combine (lerp) them based on a distance value. It looks better than you'd think.


Is there a name to this technique, ie some example i can have a look at? When you say one samller and one larger, are you refering to the mip map levels?
I don't think there is a name for the lerping technique, and yes you can do it using mip-maps (tex2dlod() iirc) but you may want to use two different textures to give you more control.

As an aside, I don't think you can really solve this without using detail textures (my personal favourite) or Matt Aufderheide's suggestions. Based on the pure theory, you're going to hit upon the resolution/frequency issue and there is relatively little you can do about it except use one of these techniques to try and hide it. Essentially all the techniques mentioned thus far aim to blend/merge texture information of different frequencies to fake the illusion of a single high-frequency texture.


hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

you can also try running the texture through a low frequency filter in photoshop or whichever software you use. It is the low frequency variations that make tiling obvious at a distance. You'll be left with high frequency details up close, and the texture mipmaps will tend to merge to a single color rather than an obvious light/dark pattern. When combined with lighting/shadows, this can be a realistic look for distant terrain.

I'm not sure if it was already mentioned, but you could also try modulating the detail texture that you're tiling with a low detail, stretched color map to give subtle color and shade variations. Using perlin noise is a good way to accomplish this, it has the effect of masking the tiling.
Quote:Original post by wforl
Is there a name to this technique, ie some example i can have a look at? When you say one samller and one larger, are you refering to the mip map levels?


I don't think it has a specific name, it's just a shader method. To do it, here is some simple code:

//sample each texture twice
float3 grasssmall = tex2D(grass_tex,texCoord*scalefactor); //normal scale
float3 grassbig = tex2D(grass_tex,texCoord*scalefactor*0.2); //larger scale
....
//lerp them using a saturated and scaled distance ...
float3 finalgrass = lerp(grasssmall,grassbig,scaled_distance);
....

//to get the distance value I do something like this:
float scaled_distance=saturate(In.dist*0.00005);
//where In.dist is length(worldpos-viewpos)

This topic is closed to new replies.

Advertisement