I'm currently learning OpenGL and try to make a simple GUI. So far I know very little about shaders and didn't use any.
One of the tricks I made to accelerate text rendering is to render the text quads to a transparent frame buffer object before rendering them to screen. The speedup is significant, but I noticed the text is poorly drawn on the edges. I noticed then if I made the transparent texture be of another transparent color, then the text would blend with that color. In the example I rendered to a transparent green texture:
I use the following parameters for blending:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)
with glBlendEquation being default (GL_ADD
).
My understanding from the documentation is that each pixel is sent through an equation that is source_rgb * blend_factor + dest_rgb * blend_factor
.
I would typically want that, when a texture is transparent, it's RGB to be ignored, both sides of the blending, so if I could I would compute the rgb with a similar equation:
source_rgb * source_alpha / total_alpha + dest_rgb * dest_alpha / total_alpha
where total_alpha is the sums of the alphas. Which doesn't seem supported.
Is there something that can help me with minimum headache? I'm open to suggestions, from fixes, to rewriting everything to using a library that already does it.
The full source code is available here if you are interested. Please let me know if you need relevant extracts.
EDIT: I did try before to remove the GL_ONE, GL_ONE from my alpha blending and simply use (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
for RGBA, but the results weren't great either. I get similar results.
Solved the problem using premultiplication as suggested.
First of all, total_alpha
isn't the sum of the alphas but rather the following:
total_alpha = 1 - (1 - source_alpha)*(1 - dest_alpha)
As you noted correctly, OpenGL doesn't support that final division by total_alpha
. But it doesn't need to. All you need is to switch into thinking and working in terms of pre-multiplied alpha. With that the simple
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
does the right thing.