glBlendFunc results - error or expected?

Hello and apologies for what must surely be a beginner mistake.

I have two images, taken from Anders Riggelsen’s Blend Equations site:
image
(Foreground, transparent)
image
Background

In my 2D Opengl engine, I do the following (it’s in lua but you get the idea):

DrawSprite(flamingobg,0,500,300)
GPUSetBlendFunc(BM_1M_SRC_COLOR, BM_1M_SRC_COLOR)
DrawSprite(flamingos,0,500,300)
GPUSetBlendFunc(BM_SRC_ALPHA,BM_1M_SRC_ALPHA)

And I get this result: <= THIS IS WHAT I WANT TO FIX!
image
Essentially, the “hidden” transparent parts of the foreground image are now visible.

However, both in Anders’ website and in GameMaker studio, using the exact equivalent functions, I get this:
image

So my question is whether there is some opengl setting I have omitted.

When I use
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
(ie the “default” alpha blending mode), the result is pretty much the expected one:
image

Lastly, depth testing is disabled, blending is enabled, and my fragment shader is your basic “passthrough” shader:
FragColor = vColor * texture(baseTex,TexCoord);

I would really appreciate some input in this!

why are you showing the blend functions being set “after” drawing the sprites.

What are they “before” drawing the sprites?

Also, what are you clearing the background to? Are you sure you’ve got exactly the same texture content you’re starting with (color and alpha)? And what’s your goal with this?

Initially (ie when the program begins), blending is enabled and the blend function is set to “default”, ie
GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA

The code I posted is in a Draw event of an object. So, every frame, the flow is this:

  • Use existing blend mode (that is, the default)
  • Draw background
  • Set blend mode to GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR
  • Draw foreground
  • Set blend mode again to default

To end any doubts about the order of operations, specifically setting blend mode to “default” first before drawing the background changes nothing.

The application is creating a “main” texture/fbo (ie the “application surface”). When the drawing phase begins, it is being cleared to (0,0,0,1). Creating another surface and clearing to any color and then doing the same things with it makes no difference.

The background is fully opaque and thus it overwrites any existing content when using the “default” alpha blending mode shown above.

I checked the texture page containing these images and they are OK in it.

My goal is to make blending modes work correctly in my program. I am not trying to achieve a specific effect by using these images. I’m doing this just for testing and verifying it works OK (apparently it doesn’t).

Well, yes. I believe that’s what you asked for with:

The BlendFunc before the 2nd DrawSprite() says: Use the 1-SRC_COLOR (RGB) of the foreground image (flamingos) to determine the blend factors between: 1) the foreground image (flamingos) and 2) the current framebuffer’s color values.

So yeah, it matters what kind of trash you might have in the foreground image’s RGB channels where Alpha == 0.0 (and in general, where A < 1.0).

Sounds like the blending process you’re trying to emulate expects the foreground image to be premultiplied alpha. That is, to have the ALPHA value premultiplied to the RGB channels (ar, ag, a*b, a ). If you do so, you’ve got 100% black in RGB anywhere the foreground is 100% transparent (i.e. RGBA = (0.0, 0.0, 0.0, 0.0)).

With this, in the areas of the foreground image which are 100% transparent (RGB = Black, Alpha = 0.0), 1-SRC_COLOR gives you a 1.0 blend factor, resulting in you adding flamingos (which is black here) to the framebuffer color, resulting in the framebuffer w/o change.

@Dark_Photon I understand what you’re saying! Just bear with me for a moment.

Indeed, there’s trash in the transparent sections of the foreground image. Let’s remove transparency:
image
These patterns are evident in my first example. Now if I go wherever alpha is originally zero, and make RGB black there, I get this
image
Which is p.close to Anders’ site results.

However!!

Just take a look at the flamingos image from Anders’ site:

Save it, open it in an image editing program, anything. You will find out that this “trash” in the transparent regions exists. Then…why the hell using this image/blending combo in his website return this??

Shouldn’t the same “trash” appear there too?
What about GameMaker? Shouldn’t trash appear there too? I opened the flamingos image in GM’s sprite editor and I confirmed that the trash colors are present there too! No premultiplied alpha in both cases! What on earth is going on??

For his input foreground image, you can tell that the 100% transparent areas of that input image contain 100% black (RGB = (0,0,0)) in a few ways.

The one that makes it most obvious is, select:

  • Source = GL_ONE
  • Dest = GL_ZERO
  • Blend equation = GL_FUNC_ADD

What do you see?

You’re looking at the exact RGB in the source image, before any alpha blending hocus-pocus.

You can see that the 100% transparent areas of the source image contain black.
Now the not-quite-100% transparent areas with partial alpha? They don’t contain black.
Now click the Premultiply toggle, which maps its (R,G,B,A) → (A*R, A*G, A*B, A).
You can see that this fades-out the RGBs around the translucent fringes of the swans, with the near-zero alpha values.

OK it seems you are correct! I also checked the image in Gamemaker since it had a similar effect. While the image in the Sprite Editor still had that RGB garbage in its transparent areas, apparently when it goes in the texture page, this garbage is substituted by black.

I am actually very happy that this is the case since it shows that blending modes in my program actually do work. I just wish that other programs handled these cases with a bit more…

…transparency.

(CSI Miami music plays)

Thanks @Dark_Photon for taking the time to look at this!

Sure thing! Glad we got it figured out.