Monitoring or controlling the mipmap level?

Started by
1 comment, last by WizardOfOzzz 16 years, 3 months ago
Hi guys, Imagine I have a 256x256 repeating texture but wish to avoid sampling the texels round the edge of the texture. Using a shader I can compress the texture coordinates from the range 0.0-1.0 to a slightly smaller range using code like the following:
//First make sure texture coordinates are in the range 0.0 - 1.0
IN.TexCoords.x = frac(IN.TexCoords.x);
IN.TexCoords.y = frac(IN.TexCoords.y);
	
//Avoid sampling the texels at the edge of each texture. To do this, compress the range of texture coordinates.
IN.TexCoords *= 255;
IN.TexCoords += 0.5f;
IN.TexCoords /= 256;
This actually works pretty well if I disable mipmaping, but starts to look ugly if mipmapping is enabled. This is because I have assumed a fixed texture size of 256 and a fixed fiddle-factor of 0.5. One or both of these needs to change based on the mipmap level. Is there a way to know which mipmap levels are being used when a sample is taken? Alternatively is there a way I can control which mipmap level is used based on my own calculations? How might I do this? This may seem a slightly contrived problem - obviously it is possible to give textures borders. But I'm using a texture atlas which makes things more difficult. In the worst case I could give each texture in the atlas it's own border but then I have to carefully manage the generation of mipmap levels to ensure that every texture in every mipmap level maintains it border. I think this is possible - but measuring or controlling the mipmap level in the shader seems easier... Any ideas?
Advertisement
Hi there,

Firstly, I don't know what your exact case is but first try to solve it with the texture address mode (eg. CLAMP_TO_EDGE). If that isn't your problem here is some info about the mip-level:

Normally it is choosen automatically based on the gradient of the texture coordinates you pass in. This is calculated on 2x2 pixel squares during rendering. You can get at this derivative yourself using the ddx/ddy or dFdx/dFdy in HLSL/GLSL. In a simple 1D case, the mip level is choosen using something like:

mipLevel = lg ( ddx(coord.x) * textureWidth )

Now, if you want to choose the mip level yourself you can use the LOD instructions in GLSL or HLSL ( eg. texture2DLod or tex2Dlod ) or even specify a derivative yourself using texture2DGrad/tex2DGrad.

To manage a custom border, the border will keep getting wider and wider as you move up the mip-chain so if you want to avoid sampling the edge pixel you will need to scale your offset by powers of two as your mip level increases.

offset = onePixel * 2^mipLevel

Cheers!

Eric

P.S. This issue becomes a major pain when using texture atlases. If you don't leave enough padding then the textures will start to bleed into eachother a high mip levels
Just a quick note here. Log2 is undefined or -INF for log2(0). You can simply add an epsilon, or if you want to keep your mip level above 0 clamp to one pixel width.

mipLevel = lg ( max( 1, ddx(coord.x) * textureWidth ) );

Cheers!

This topic is closed to new replies.

Advertisement