glBlendFunc and alpha channel - c++

I'm trying to render some transparent objects using:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
However, I don't get the result I want.
I draw a fully opaque square, and then i draw a semi-transparent square. The colors are just as a I would expect however, the alpha channel is NOT fully white as I want.
Basically I want the following equation:
r = old_r*(1.0-a)+r*a;
g = old_g*(1.0-a)+g*a;
b = old_b*(1.0-a)+b*a;
a = old_a + a;
Is this possible to achieve using glBlendFunc or do I have to resort to shaders and multiple FBOs for read-back?

You basically want separate blend functions for color and alpha, and this is achieved by using glBlendFuncSeparate:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
Does the blend func you want.

Just draw your opaque square, then check the alpha channel. If it's not showing up as fully white when a known-opaque square is rendered, you may have a problem with some other setting.

Related

Creating an OpenGL texture with alpha using NSBitmapImageRep

I am loading a PNG using:
theImage = [NSBitmapImageRep imageRepWithContentsOfFile:imagePath];
from which I can successfully create a gl texture and render correctly without any transparency. However, when I switch blending on using:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
The texture renders with the correct transparent background, but the image colours are incorrect.
I have tried several options in the blend function, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA, etc.
I was taught maybe I need to reorder the bits in the image data, maybe the channels have been mixed up, but I would not expect it to render correctly when blending is off in that case.
Alternatively, I could use libPNG I guess, but I would like to try using a NSBitmapImageRep if it is possible.
How about supplying a screenshot?
Anyway, your blending function is wrong either way for simple transparency channel blending. It should be either
normal alpha: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
or
premultiplied alpha: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

Procedure for alpha blending textured quads in OpenGL 3+?

I am attempting to put together a simple program that just displays two textured quads overlapping each other, and the textures have alpha channels.
I have successfully been able to get the quads themselves to display, and the textures look correct except for the transparency.
On this topic, the GL_BLEND flag does not seem to do anything at all, whether it is enabled or not. Is this particular flag inapplicable when shaders are being used?
I know for a fact that the alpha is being rendered in correctly, since if I set out_color = texture.aaaa, I get a nice pattern of blacks/whites/grays that match the original texture.
So, if GL_BLEND doesn't work, what are the usual methods for getting alpha blending working?
All that glEnable(GL_BLEND) does is turn blending on and off. It does not say what the blending will do; that is controlled by the various blending functions. If you want a typical alpha transparency blend, you do this:
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
If you use pre-multiplied alpha (and you probably should), you would do:
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

OpenGL - Textures - Replacing black (white) with color

I am generating a bitmap for a text display with OpenGL using Cairo/Pango. I generate the bitmap as RGBA with a transparent background and with the text in either black or white. (Let's assume black.)
If I load this bitmap as an OpenGL texture and display it, it appears as black text or white text, as expected.
I'd like to be able to color the text using only the original texture, but with OpenGL taking care of the coloring.
Preferably, I'd like to use glColor to set the color, but I'm willing to use glBlendColor or GL_TEXTURE_ENV_COLOR.
However, I can't get any of those options to work.
I've try what seem like innumerable combinations of
- white text or black text
- enabling blending or using GL_TEXTURE_ENV_MODE's GL_BLEND
- trying GL_MODULATE, GL_REPLACE, and GL_COMBINE
- trying various differnt glBlendFunc combinations
I've been searching online and reading the spec for a few hours and I'm really at the end of my rope.
Can anyone point me to the right place to get the answer to this?
The simplest way to go is to have your text bitmap with white text and transparent background.
Then, to color it, you have to make sure that TEXTURE_ENV_MODE is set to MODULATE :
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
With this, the draw color will be glColor * textureColor == glColor (as textureColor is white)
Then you have to enable blending to handle your transparent background :
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
or, if your bitmaps are in premultiplied alpha form :
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Instead of supplying a full RGBA set, let the text just determinine the non-/transparency, i.e. just supply an alpha channel. Then use the normal glColor to set the text color.
It sounds like you can create the bitmap as you see fit. If that's the case, instead of black on white, I'd draw the text into the alpha channel. Then to color the text, you draw a rectangle (or whatever) of the color you want. Then draw your texture over it. Where the texture is opaque, you'll get the texture color. Where the texture is transparent, the background color will show through.
To do that, you will have to set up glBlendFunc. The usual should be fine:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
You also have to turn on blending for texturing:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);

Coloring grayscale image in OpenGL

I'm trying to draw grayscale image in color as texture in OpenGL using two colors. Black goes to color1 and white goes to color2. Texture is loaded using GL_RGBA.
I have tried two solutions:
1)
Load image as texture
Draw image on screen
Enable blending
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); and draw rectangle with color1
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE); and draw rectangle with color2
But... When I apply first color, there is no black color on screen and when second color is applied it is combined with first color too.
2)
Save image as texture but don't use grayscale image, use white image with alpha channel that is same as grayscale
Draw rectangle with color1
Draw image
But... When image is drawn it doesn't use color1 where image is transparent, instead it uses current color set with glColor.
Any help will come in handy :)
In general, when dealing with OpenGL texturing pipeline, I recommend writing down the end result you want. here, you want your grayscale color to be used as an interpolant between your 2 colors.
out_color = mix(color1, color2, texValue)
The math for this actually is something like:
out_color = color1 + (color2 - color1) * texValue
So... is there a texture environment value that helps do that ? Yes, and it's also called GL_BLEND (not to be confused with the blending to frame buffer that glEnable(GL_BLEND) enables).
So... something like
// pass color1 as the incoming color to the texture unit
glColor4fv(color1);
GLfloat color2[4] = { ... };
// ask for the texture to be blended/mixed/lerped with incoming color
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_BLEND);
// specify the color2 as per the TexEnv documentation
glTexEnvfv(GL_TEXTURE_2D, GL_TEXTURE_ENV_COLOR, color2)
There is no need to draw multiple times or anything more complicated than this, like you tried to do. The texturing pipeline has plenty of ways to get controlled. Learn them to your advantage!
Your #2 idea would work, but it seems like you didn't set blending correctly.
It should be:
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

How to setup blending for additive color overlays?

Is it possible in opengl to setup blending to achieve additive color overlays?
Red + green = yellow, cyan + magenta = white, etc.. (see diagram)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
should do it.
Have a look at the full description of glBlendFunc
EDIT: Old tutorial link seems to be dead (403 Forbidden). Wayback'd.
Simple additive blending is achieved with glBlendFunc (GL_ONE, GL_ONE). You need to be aware of the fact that OpenGL's color value range is limited to [0,1], and values greater than 1 will be clamped to 1, so adding bright colors may not produce physically correctly blended colors. If you want to achieve that, you will have to add and scale the colors in your own software rather than having OpenGL handle it, or write a shader program that does that while rendering.