Calculate mipmap level in a loop with varying iteration?

How can I calculate the correct mipmap level in a shader? It needs to be used in a loop which runs a variable number of times so the compiler will not allow me to use Sample or the derivative functions, instead I have to use SampleLevel and manually specify a level. I tried a simple distance based one but that doesn't look very good and doesn't fix all the problems (such as looking at them at a sharp angle), I thought I could use the dot product of the normal with the direction the pixel is going but I'm still not sure on the correct thresholds etc or if there's a better way.

• What kind of effect are you trying to implement? Commented Jul 22, 2013 at 21:14
• @sarahm Mipmapping in a GPU voxel ray tracer. Most approaches to fix it with raytracing use multiple samples per pixel, but it'll cost too much to do multiple samples per pixel to 'fix' it and to run at a reasonable speed. Commented Jul 23, 2013 at 1:40
• "I thought I could use the dot product of the normal with the direction the pixel is going". If you mean you used the dot product to calculate the mip level, that's not right - the mip level should be the log2 of the ratio of pixel size to texel size, roughly speaking. Commented Jul 26, 2013 at 17:42

Quote

I tried a simple distance based one but that doesn't look very good and doesn't fix all the problems (such as looking at them at a sharp angle)

this implies that you need Anisotropic filter and it needs the derivaives...

So you need to calculate the derivatives manually.

One apprach is to render the texture coordinates into a texture and calculate the derivative from that (you need to render the object id in a texure too and use it to differenciate between the objects in the derivative calculation).

See here and GPU-Gems for some appraches how to filter anisotroph.

Since you're running this in a loop, and since it runs a variable number of times, you may be able to do something like the following:

• Sample from all mipmap levels before entering the loop, and store them in an array of float4s.
• Enter the loop.
• Calculate the mipmap level you wish to use inside the loop.
• Use that as an index into the array; the integral part of the level gives the array index to use, and the fractional part can be used as an interpolation factor between that and the next level down if you wish.

This may even be faster than the theoretical case where you may be allowed to sample inside a loop. Say, if your texture has 10 mip levels and your loop runs on average more than 10 times; you're able to get the desired result with only 10 texture lookups rather than an average of more than 10.

Of course it will break down if you don't know how many mip levels you're going to have in advance, but you should tune your content so that doesn't happen.

• That's assuming there's only one sample point and it's known before you enter the loop...seems unlikely in a raytracer. Commented Jul 26, 2013 at 17:21