How to use semi-transparent QPixmaps as textures?
-
I have posted a similar question on stackoverflow and QtCentre with unsuccessful results, so I'll rephrase if anyone has seen those.
I want to use QPixmaps as textures in a QGLWidget. The problem I am encountering is that the alpha seems to be applied to the color channels twice because the format of QPixmaps with transparency is premultiplied alpha. If I use a QImage then the alpha is applied only once and the texture has the correct colors. I don't want to use QImages as textures though because they are noticeably slower than QPixmaps because they are in main memory.
My procedure is to call QPixmap::fill with a semitransparent QColor, and then call QGLWidget::bind/drawTexture on that QPixmap. If I use a color with a red value of 0.5 and an alpha of 0.5, then before binding the QPixmap (and after converting to a QImage for pixel sampling, in format ARGB32_Premultiplied), then the sampled values for the red channel are 0.25. This verifies the format as premultiplied alpha. When the bound QPixmap is drawn to the QGLWidget as a texture and the scene is rendered, the red channel then becomes 0.125, meaning the alpha has been applied twice, once for the premultiplication and again when rendering the scene.
It seems logical that QPixmaps would be used as textures for QGLWidgets since QPixmaps can reside in video memory. How then do I use semi-transparent QPixmaps as textures without applying the alpha twice? Is there some procedure I am missing?
-
Why not just use QImage? QImage's can be created and drawn on in any thread whereas QPixmaps can only be used in the main GUI thread. Also, if you are using the raster paint engine then QPixmap shares a backend with QImage anyway since it is entirely software based.
Once you bind the image as an OpenGL texture (and perhaps have mipmaps generated) they reside in graphics memory anyway (resource permitting) since OpenGL converts them to the most appropriate type for that implementation.
-
I did not want to use use QImages because they are stored in system memory and I was binding and deleting textures frequently. I refactored my code to use QImages and minimize binds, thus minimizing sending the data over the bus. The performance is good.
Still, I think it is an oversight that semi-transparent QPixmaps used as textures are not displayed correctly, if my explanation of this phenomenon is indeed the case. It would be great in the future if there was a QGLContext::BindOption that did the inverse of PremultipliedAlphaBindOption and undid any premultiplication that had already occurred.