Graphics Trick: MIP size

This one is all about MIP mapping. If that’s greek to you, go find another window and look it up. This time, how big is that MIP chain? Turns out there are closed form equations for a lot of the common cases.

Each level of a MIP chain is 1/4 the size of the next level up. So the first step is remembering how to find a closed form equation for an infinite sum. In terms of the original size, the rest MIP chain is about this fraction of the base level:

scale = 1/4 + 1/42 + 1/43 + … = 1/4*(1 + 1/4 + 1/42 + …)
scale = 1/4*(1 + scale)
scale = 1/3

So, the rest of the MIP chain is about 1/3 the original, or the whole thing is about 4/3 the original. Seems I remember learning that in grade school (well maybe not grade school, but a while ago). But what’s with the “about”? Well, this infinite sum overcounts by some fractional pixels after the last level. How many? All of the pseudo-MIP levels below the last level, or 1/3 of the size of the last level. Assuming a nice square texture where the last level is 1 pixel, it over counts by 1/3 pixel. In general, it’s

size = base*4/3 – last*1/3

or if you want something you can use integer math for

size = (4*base – last)/3

For example, for a 1024 x 1024 texture, it’s

size = (4*1024*1024 – 1)/3 = 4,194,303/3 = 1,398,101

All integers. I think that’s pretty cool. You’re welcome to do the sum by hand to be sure:

size = 1024*1024 + 512*512 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 = 1,398,101

But it gets even more fun. What if you pack all the levels of an X x Y MIP texture into a contiguous block of memory (How big? See the size equation). Where does level N start? Well, if you pack smallest level first, it’s just the size equation for level N-1. But if you pack base level first, it’s the size equation from the base through level N-1

Start(N) = (4*base – last)/3

Or avoiding potential problems for the very first level, you can rewrite it in terms of the size of the base level and the size of level N:

Start(N) = (base − next)*4/3

For that 1024 x 1024 texture, this is where it says the levels start

Start(0) = (1024*1024 – 1024*1024)*4/3 = 0
Start(1) = (1024*1024 – 512*512)*4/3 = 1,048,576 (= 1024*1024)
Start(2) = (1024*1024 – 256*256)*4/3 = 1,310,720 (= 1024*1024 + 512*512)
Start(3) = (1024*1024 – 128*128)*4/3 = 1,376,256 (= 1024*1024 + 512*512 + 256*256)

Just throw in a multiplier to handle different size texels, or cube faces if packed together.

A few caveats though. First, it works great for non-square textures or non-power of two textures if you stop when you hit the last full pixel. So, if your 1024×256 texture stops at 4×1, all is good, but not if you toss in an extra 2×1 level, since the equations think it should be a 2 x 1/2 level. Nobody likes half pixels. Also, textures formats like DXT that round up to 4×4 blocks work only as long as you stick to levels that don’t actually need any padding (powers of 2 down to 4×4 are OK, but 14×18 gets padded to 16×20 with those troublesome extra pixels)