Fast Mipmap Level Of Detail Computation

Altair/ODDS entertainment

When scanconverting polygon there must be computed gradients du/dx and dv/dx which represent steps taken in uv-texture space when moving along x-axel in screen space. For polygon segments which have constant z-value, these gradients are constant. When texture mapping polygons which are assumed to have constant z over whole polygon we call this affine mapping. When polygon has non-constant z over the polygon and it has been taken account when texture mapping it, we call this perspective correct texture mapping.

Because mipmap LOD computation is purely based on the values of these two gradients, we can see that for affine mapped polygons, LOD computation is required to be done only once for whole polygon while for perspective mapped polygon it's required to be done for each pixel. Well now comes the traditional formula to compute the LOD (dux=du/dx, dvx=dv/dx):

To explain this formula: (dux^2+dvx^2)^(1/2) is euclidean length of the step taken on a texture, log2(...) is used to compute how many times the step can be divided in half so that length of the step is greater or equal to 1, and ...- is just round down operation.

As we can see, this isn't a nice function to be computed for each pixel. Well we can easily remove the squareroot from the function like follows:

Anyway, we still have that log2 spooking around which isn't fast to compute either. Now because we have this nice IEEE floating point format which happens to store numbers in logarithmical form, we can use it for fast log-computation and rounding. We just need to compute dux^2+dvx^2 as float and handle the value like an integer. Because the integer value needs to get shifted right (get rid of the 23-bit mantissa in 32-bit float), you can include dividing by 2 there which like comes for free. Note that you need to subtract 127 from the exponent to get the real value.

LOD bias can also be added for free, but you can try to solve that by yourself. And example follows:

 #include <stdio.h>
 void main(void)
 {
   double dux,dvx;
   float v;
   int LOD;

   dux=2; dvx=0;
   v=dux*dux+dvx*dvx;
   LOD=(((int &)v)-(127<<23))>>24;
   printf("%i\n",LOD);
 }

Pretty simple, eh? (:

- Altair/ODDS entertainment