MipMaps

Hi All,

I am trying to avoid to call the gluBuild2DMipmaps() because is VERY SLOW. Don’t want even to call a specific glu 1.3 func missing on many machines (gluBuild2DMipmapLevels).

The question is: if I generate mipmaps manually like in the RedBook samples mipmaps.c can I stop the process earlier to go faster.

For example: if I have a texture of 1024x1024, can I make only 2 mipmaps levels to generate 512x512 and 256x256 mipmaps instead of going to 1x1?

Is this a good approach? Will I save time?

Thanks a lot,

Alberto

Not a good option, better store the mipmaps in the file, or generate ALL levels (with your own function or GLU), hardware is likely to need more than only the first few levels, especially if you use anisotropic filtering.

I remember someone (think it was Humus) said the hardware prefered to have all levels, even the 1x1 one…

Roderic,

So there is no way to go faster generating mipmaps than gluBuild2DMipmaps?

The only way is to provide square textures and with dimension power of two? We noticed that gluBuild2DMipmaps go faster if it is like this.

Mmm… in my opinion we are missing something…

Thanks,

Alberto

If you textures are not power-of-two, gluBuild2DMipmaps will rescale them to be power-of-two, that’s why it is slower.

Storing all mipmap-levels on disk (dds-file-format) can give you huge speed-ups, especially when they are additionally precompressed, so that you can read and upload them without any further processing (and need to read fewer data, since they are compressed).

Other than that, maybe automatic mipmap generation is faster than gluBuild2DMipmaps, but i am not sure about that.

Generating less mipmaps is possible, you can tell the driver, that it should only use mipmap-levels 0 to n, then n+1 … don’t need to be present. But this is a fragile feature, i would not depend on drivers implementing it correctly. And as mentioned above, some hardware might not like it that much, if some levels are missing.

Jan.

Jan,

>> Other than that, maybe automatic mipmap generation is faster than gluBuild2DMipmaps, but i am not sure about that.

What do you mena with “automatic mipmap generation”?

Thanks,

Alberto

I personally either use the automatic mipmap generation (seems to do a good enough job), or I generate mipmaps myself using the most basic of all methods… the box filter =). I find that generating mipmaps after loading the base image is actually quite a bit faster than storing them in a file (at least on the machines I’ve tried it on). Image quality is the best argument for storing mipmaps on disk, simply because you can use much more sophisticated filters than the box filter.

Automatic mipmap generation can be done with GL_SGIS_generate_mipmap (very widely supported at this point).

Kevin B

Kevin,

GL_SGIS_GENERATE_MIPMAP

I find it on my Graphics Card,

Can you provide a small c/c++ sample of the usage? So I can test performances?

Thanks,

Alberto

Get used to take a look into the extension registry:
http://opengl.org/registry/

The specification is here:
http://opengl.org/registry/specs/SGIS/generate_mipmap.txt

And google is your friend :slight_smile:

Actually for this extension it is very simple. Here is a snippet of my code:

if (GLEW_SGIS_generate_mipmap)
{
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, true);
glTexImage2D (GL_TEXTURE_2D, 0, iInternalFormat, tex->m_iSizeX, tex->m_iSizeY, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*) tex->mp_ucTexture);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, false);
}
else
{
gluBuild2DMipmaps (GL_TEXTURE_2D, iInternalFormat, tex->m_iSizeX, tex->m_iSizeY, GL_BGRA, GL_UNSIGNED_BYTE, (void*) tex->mp_ucTexture);
}

Jan.

Hi,

just found what you are looking for in my code;-)

//enable automatic mipmap generation:
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, true);

// enable mipmaping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

// upload texture
glTexImage2D(…)

Hope this helps…

Martin

There is also an extension function (found in, of all places, the FBO spec) that allows you to tell the hardware to generate mipmaps. It’s called, “glGenerateMipmapEXT”, which will generate mipmaps from the currently bound texture.

The problem with gluBuild3DMipmaps is that it’s all CPU work. glGenerateMipmapEXT allows the hardware to do the filtering. It’s also nicer than the SGIS extension, since that extension will build mipmaps anytime the texture changes, whereas glGenerateMipmapEXT does it only when you ask for it.

Originally posted by devdept:
Is this a good approach? Will I save time?
No. After generating just two mipmaps you’ve already done 94% of all processing, so stopping at that point just saves the last 6%. I would recommend you to always generate all mipmaps. There’s no little to no gain worrying about the mipmaps. Even if you removed all mipmaps and just saved the base level you still only save 25%.

Thanks a lot to you all.

I will try first GL_GENERATE_MIPMAP_SGIS and then glGenerateMipmapEXT and let you know.

Alberto

Hi Jan,

I tried your code but after creating mipmaps with the GL_GENERATE_MIPMAP_SGIS I don’t see them in action…Why?

If I disable them and use gluBuild2DMipmaps everything work perfectly.

The loading time difference is 0.025 sec with in house reascaling & resquaring & GL_GENERATE_MIPMAP_SGIS while 0.250 sec with the gluBuild2DMipmaps, that is very good.

Now I need only to fix the issue above. Of course I tried to call gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);

before and after.

Thanks,

Alberto

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);

Thanks zBuffer, but I am using the following code and does not work:

            gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
            gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 1);
            gl.TexImage2D   (gl.TEXTURE_2D, 0, gl.RGBA, data.Width, data.Height, 
                                            0, gl.BGRA, gl.UNSIGNED_BYTE, data.Scan0);
            gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 0);

Why?

Alberto

change:

gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 0);

to

gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 1);

=)
Kevin B

Surprising.
Not sure what programming language you use but did you try :
gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, gl.TRUE);

and remove the gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 0);

From the extension spec :

If GENERATE_MIPMAP_SGIS is enabled, the side effect occurs whenever
any change is made to the interior or edge image values of the base
level texture array.  The side effect is computation of a complete
set of mipmap arrays, all derived from the modified base level array.
Array levels BASE+1 through BASE+p are replaced with derived arrays,
regardless of their previous contents.  All other texture arrays,
including the base array, are left unchanged by this mipmap computation.

Maybe at another place you change the texture ?

I don’t see them in action…Why?

You mean only the base level is here, and when the texture becomes too small on screen it turns white ?
I never had problems with this auto texture generation.
Did you try with GL_NEAREST_MIPMAP_NEAREST to better see the mipmap ‘jump’ ?

Well, my code-snippet, that you used, does enable automatic-texture generation, then uploads the texture and then disables automatic-texture generation, to make sure, that the driver does not need to keep track of any changes, since there won’t be any.

This works for me, i use this code for several years now and i never had any issues neither on ATI nor NV hardware.

As mentioned above, try without the additional disabling of mipmap generation. However, i am a bit surprised and i cannot see any errors in your posted code snippet.

Of course, if you DO change the texture later on, you DO need to have mipmap generation left ON. I only disable it, because i KNOW that after loading the textures once, they won’t change anymore.

Jan.

Yes Guys,

Removing the

gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 0);

solves the problem and everything works fine. My Hardware is ATI FireGL 7200.

if (Viewport.OpenglExtensions.Contains("GL_SGIS_generate_mipmap"))
            {

                MakeSquareAndPowerOfTwo(ref bitmap);

                gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 1);
                gl.TexImage2D   (gl.TEXTURE_2D, 0, gl.RGBA, data.Width, data.Height, 
                                                0, gl.BGRA, gl.UNSIGNED_BYTE, data.Scan0);
                // gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 0);

            }
            else
            {

                                glu.Build2DMipmaps(gl.TEXTURE_2D, gl.RGBA,
                    data.Width, data.Height,
                    gl.BGRA, gl.UNSIGNED_BYTE,
                    data.Scan0);
            }

This code is called every time a texture is loaded. Should I call the gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP_SGIS, 1); every time or I can place it at the beginning of the program? What happens if the extension is not available? Our textures are loaded once, there is no need to change them at runtime.

Thanks again,

Alberto

  1. this is a gltexparameter, so put it with the others, like texture filters etc.
  2. you should always test for the extension presence, but this one is very largely supported :
    http://www.delphi3d.net/hardware/extsupport.php?extension=GL_SGIS_generate_mipmap