top level mipmap with FBO and GENERATE_MIPMAP

Hi guys, new to using FBOs, could use some help. I’m doing some GPGPU work and need to read back the top level mipmap (1x1) after drawing into an FBO attached float texture and calling glGenerateMipmapEXT. Everything looks fine except the top level mipmap. It always comes back as junk. This is how I initialize the texture:

glBindTexture(GL_TEXTURE_2D, ID);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, width, height, 0, GL_RGB, GL_FLOAT, 0);

After I attach it to the FBO and draw a quad, I call

glBindTexture(GL_TEXTURE_2D, ID);
glGenerateMipmapEXT(GL_TEXTURE_2D);

and then read back the texture using glGetTexImage. Like I said, every mipmap level looks fine except the top pixel, which is always garbled. Seems like it might be a problem with the filter that’s doing the minification, but I’m not sure. I’m using a GeForce 6800. Any advice is much appreciated!

Are you sure you actually read the top, and not “above the top” ? Try reading top-1 for example.

I don’t think there is a 1x1 mipmap, at least there is no need for one when using bilinear or trilinear filtering since you always filter between 4 textels and thus there is no need for the last mipmap level.

Either way, if you can’t generate it or read it normaly, then just read the 4 pixels at the 2x2 mipmap level and just average them together yourself.

Originally posted by ZbuffeR:
Are you sure you actually read the top, and not “above the top” ? Try reading top-1 for example.
I’m pretty sure I’m reading from the top. I’m using the formula from the NPOT doc, level = floor(log(max(w, h))). Level - 1 reads back a 4x4 texture that looks just fine. Level by itself reads back a 1x1 texture that’s messed up.

Originally posted by zeoverlord:
[b] I don’t think there is a 1x1 mipmap, at least there is no need for one when using bilinear or trilinear filtering since you always filter between 4 textels and thus there is no need for the last mipmap level.

Either way, if you can’t generate it or read it normaly, then just read the 4 pixels at the 2x2 mipmap level and just average them together yourself. [/b]
I wondered the same thing about bilinearly filtering a 4x4 texture. As you said, it seems like whatever is there after that operation wouldn’t make much sense. However, I changed my border type to CLAMP_TO_EDGE, hoping that would fix the problem of it trying to filter a texture that small, but it didn’t work. I’d also thought to average the 4x4, but it felt like a hack at the time. I had hoped I could get hardware to do it for me. :slight_smile:

level = floor(log(max(w, h)))

If plug in 1010, I get 3.
If log is suppose to be ln, then I get 6
that means the highest mipmap is 32 pixels

There is no 1x1 mipmap.

Originally posted by V-man:
[b] level = floor(log(max(w, h)))

If plug in 1010, I get 3.
If log is suppose to be ln, then I get 6
that means the highest mipmap is 32 pixels

There is no 1x1 mipmap. [/b]
Whoops, didn’t specify that. It’s log base 2. So if you’re doing it on a calculator it’s level = floor(log(max(w, h))/log(2.0)). With 1010 I get 9 levels.

0-1024
1-512
2-256
3-128
4-64
5-32
6-16
7-8
8-4
9-2

1x1 mipmap doesn’t exist

As far as i know, specification tells us quite exact words about mip-chain:

– BEGIN COPYPASTE glspec21.pdf –
A mipmap is an ordered set of arrays representing the same image; each array has a resolution lower than the previous one. If the image array of level levelbase, excluding its border, has dimensions wb × hb × db, then there are floor(log2(max(wb, hb, db))) + 1 image arrays in the mipmap.
– END OF COPYPASTE –

So, for 1024*1024 texture i’m getting log2(1024)+1=11 image arrays in mip-map.

– BEGIN COPYPASTE glspec21.pdf –
Numbering the levels such that level levelbase is the 0th level, the ith array has dimensions max(1, floor(wb/2^i)) × max(1, floor(hb/2^i)) × max(1, floor(db/2^i)), until the last array is reached with dimension 1×1×1.
– END OF COPYPASTE –

Originally posted by V-man:
[b] 0-1024
1-512
2-256
3-128
4-64
5-32
6-16
7-8
8-4
9-2

1x1 mipmap doesn’t exist [/b]
The NPOT doc says:

Each successively smaller mipmap level is half the size of the previous level, but if this half value is a fractional value, you should round down to the next largest integer. Essentially:

    max(1, floor(w_b / 2^i)) x
       max(1, floor(h_b / 2^i)) x
          max(1, floor(d_b / 2^i))

where i is the ith level beyond the 0th level (the base level)

As I said, I get 10 levels, since numLevels = 1 + floor(log2(max(w, h, d))). So for 1010, I get floor(1010 / 2^9) = 1, since starting from zero, 9 would be the top level. So level 9 is 1x1x1.