I am having a few issues rendering alpha channels from JUCE into OpenGL textures. Specifically, the issue is with anti-aliasing.
Please look at these tests, where I am loading a PNG image with transparency into an OpenGL texture. You will see white text on a color background. The text is the texture image (white text on transparent background), the background color is made by OpenGL.
In this example, the PNG is loaded with JUCE’s ImageFileFormat::loadFrom, and then sent to OpenGL:
In this one, the PNG is loaded via SDL and SDL_image, composed in OpenGL using JUCE.
Notice that JUCE’s image seems to blend those semi-transparent edge pixels to black. What is interesting is that none of this happens if the JUCE image is composed on a Component with a solid color background.
This behavior is repeated on anything that has an alpha channel in JUCE. For example, if you create a snapshot of a component that, say, has a Drawable on it, but no background, the edges of the pixels in that snapshot will also be black once they are rendered by GL.
It seems like the alpha channel in JUCE is not finalized unless the image is composed within JUCE. That is great if you are just working in JUCE, but it is not as nice if you are trying to use JUCE to load translucent textures to GL.
I don’t know about about SDL_image, but I think it is because juce’s Image class stores pixels with premultiplied alpha.
You have to set your blending mode accordingly
From what I understand, that is the way GL likes it. I’ve tried every blending mode combination I can think of, however, and it doesn’t make a difference.
Anyone rendered translucent textures loaded from JUCE? What is the secret?
BTW, I am in OS X, if that makes a difference. (And I have noticed some issues with GL in OS X, btw. For instance, lines are ALWAYS antialiased, even when I disable blending and multisampling).
Just a tip – the glHint(GL_LINE_SMOOTH_HINT, …) lets you change what you (probably) want to change, if Apple will allow you to set it. And also for your other problem, if it truly is premultiplied with black…
[quote]Using glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) lets you render premultiplied with black alpha textures correctly, and bilinear filtering does the right thing. In the original case, the neighborhood of the white pixel evaluates to a full white (premultiplied by the alpha which drops away), removing the dark fringing.
So you know, I will be doing some OpenGL textures from JUCE on linux pretty soon, so I’ll be able to let you know how it’s handled on linux (though I assume it would be the same way).
well on macosx, it was forced to 4x FSAA.
don’t have a mac here, but you should try this:
in build/macosx/platform_specific_code/juce_mac_Windowing.cpp : 3392
[code] // xxx not sure how to do fullSceneAntiAliasingNumSamples…
attribs[n++] = AGL_SAMPLE_BUFFERS_ARB;
attribs[n++] = 1;
attribs[n++] = AGL_SAMPLES_ARB;
attribs[n++] = pixelFormat.fullSceneAntiAliasingNumSamples; // <- this was 4 before
trip099, could you tell us if it works now ?
that could be useful for others…
Hmm, thats odd, I remember replying to this and going “yay”… and telling the board to notify me via email…
Anyways, the translucent textures work. The solution was the one proposed by Sastraxi:
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
which indeed handles premultiplied alpha. PNG’s and anything drawn via JUCE now looks properly translucent in GL. So many thanks Sastraxi!
As far as AA lines, I couldn’t get rid of them. glHint(GL_LINE_SMOOTH_HINT, …) doesn’t seem to do anything, and fiddling with juce_mac_Windowing.cpp, apart from not being too practical, didn’t quite work out. The non-AA lines ended up in the wrong place for some reason. This wasn’t huge deal for me though, so I let it go.
Anyways, thanks for all your help!