I'm adding dynamic cubemap reflections and image-based ambient lighting to my engine (using OpenGL) and have encountered a problem that I'm not sure how to handle. I can render the scene 6 times to a cube map successfully, and use the cube map for reflections.
However, when I try to generate mipmaps for the reflection cube map using glGenerateMipmap(), it is unbelievably slow (like 30-100ms for a tiny 8 pixel cube map). In the other places I am calling glGenerateMipmap() every frame, such as on a copy of the main framebuffer, it is about 1000 times faster. Surely I am doing something wrong to get such bad performance.
My rendering pipeline is like this:
- I create an FBO with a color cube map and depth cube map bound. This is done once on the first frame, and the FBO+maps are reused each frame.
- When rendering reflections, I first bind the FBO, then render the scene 6 times, each time I calll glFramebufferTexture2D() to switch to the right cube map face. Afterwards all faces are done, I unbind the FBO.
- Then I generate mipmaps for the new cube map contents using glGenerateMipmap().
- For testing purposes I am not even using the cube map for any further rendering.
These are the things I have tried to resolve this:
- I tried unbinding the texture from the FBO before calling glGenerateMipmap(), with no effect.
- I tried creating multiple FBO+map assemblies and rotating between them on each frame, with no effect.
- If I never bind the FBO for rendering, then glGenerateMipmap() is fast (though it has garbage image).
- If I bind the FBO for rendering but don't draw anything, mip generation is fast. Even adding glClear() makes it slow again.
- Calling glGenerateMipmap() again after the first time is fast.
My feeling is that this is somehow related to the texture being bound to an FBO at the same time, though there are lots of other places (e.g. shadow maps, water refraction pass) where I use a texture immediately after rendering to it in an FBO, without any problems. For instance, for refraction, I blit the main framebuffer to another texture (also bound to an FBO), and can generate mipmaps very quickly (30us). The only thing particular to this situation is that the texture is a cube map, and that I'm rendering into it rather than calling glBlitFramebuffer().
One potential workaround is to render into a 2D texture instead, then glBlitFramebuffer() the 2D texture into the cube map faces after rendering. I haven't tried this and would like to avoid it.
Does anyone have any ideas or pointers for how to resolve this performance issue?