1
votes

Following problem: I have two textures and I want to combine these two into a new texture. Thus, one texture is used as background, the other will be overlaid. The overlay texture is getting initialized with glClearColor(1.0, 1.0, 1.0, 0.0). Objects are draw onto the texture, these objects do have alpha values.

Now blending between the two textures leaves a white border around the objects. The border comes from the fact that the background color in the second texture is white, isn't it?

How can I use alpha blending where I do not have to think about the background color of the overlaying texture?

4
Wouldn't you like to post this question here instead? gamedev.stackexchange.comAlexanderMP
@AlexanderMP: Why? This is purely a graphics question; it has nothing to do with games or game development specifically.Nicol Bolas
If I thought that it shouldn't belong here at all, I'd vote to close it. However, I think that on a specialized site this question would receive a good answer faster. It was more like a suggestion. :) Here on SO, questions that are hard, or regarding very specific stuff, tend to get lost, sometimes never to be found again unless a bounty is set.AlexanderMP
I'm afraid I don't understand the question. "The border comes from the fact that the background color in the second texture is white, isn't it?" Which "second texture"? Are you talking about the texture in the back or the texture you overlay on top? Because you just said that you set its background to black and zero-alpha. Did you forget to call glClear after setting the clear color?Nicol Bolas
@AlexanderMP: My point is that you could say the exact same thing about every question with the OpenGL tag on it. Or D3D tag. And the vast majority of them get answers. There isn't anything that singles this question out from the thousands of others under those tags.Nicol Bolas

4 Answers

5
votes

I solved the problem myself, but thanks a lot to all of you guys!

The problem was following: to combine both textures I used glblend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) which does not work due to the fact that OpenGL uses pre-multiplied alpha values. Blending with glblend(GL_ONE, GL_ONE_MINUS_SRC_ALPHA), works as the source term now will be: 1*src_alpha*src_color!

1
votes

How can i use alpha blending where i do not have to think about the background color of the overlaying texture?

You can't; your blend function incorporates the background color into it, because it may not actually be the "background". You render multiple objects to the texture, so the "background" color may in fact be a previously rendered object.

Your best bet is to minimize the impact. There's no particular need for the background color to be white. Just make it black. This won't make the artifacts go away; it will hopefully just make it less noticeable.

The simple fact is that blending in graphics cards simply isn't designed to be able to do the kinds of compositing you're doing. It works best when what you're blending with is opaque. Even if there are layers of transparency between the opaque surface and what you're rendering, it still works.

But if the background is actually transparent, with no fully opaque color, the math simply stops working. You will get artifacts; the question is how noticeable they will be.

If you have access to more advanced hardware, you could use some shader-based programmatic blending techniques. But these will have a performance impact.

0
votes

Although I think you probably get better results with a black background, as Nicol Bolas pointed out. But you should double check your blending functions, because as you point out, it SHOULD not matter...

1.0 * 0.0 + 0.734 * 1.0 = 0.734

What I don't really get is why your base texture is fully transparent? Is that intended? Unless you blend the textures and then use them somewhere else initializing to Alpha = 1.0 is a batter idea.

0
votes

Make sure you disable depth writing before you draw the transparent texture (so one transparent texture can't "block" another, preventing part of it from being drawn). To do so just call glDepthMask(false). Once you are done drawing transparent objects, call glDepthMask(true) to set depth writing back to normal.