Blending modes (textures and masking)

Hi

First of all, I’ve searched, read tutorials, all that stuff.

Still I can’t figure out how to use OpenGL and blending to mix 2 textures with one mask (no, I’m not using shaders, neither extensions, and I don’t plan to use it, unless it’s the only possible way to achieve what I want).

Here’s the deal:

2 Textures, 128x128, one completly green, another completly red, should be mixed based on another (128x128) texture, that is black and white:

How do I put Red where is black, and green where is white?

My current code looks something like:


Enable Blend;
Disable Depth Test;

glBlendFunc(GL_DST_COLOR, GL_ZERO);
DrawMask;

glBlendFunc(GL_ONE, GL_ONE);
DrawRed; // Now, where was black there's red now

Now what should I put in glBlendFunc() to make the white become green?

Should I draw the mask again? With what parameters?

This is what I got so far:


Disable Depth Test;
Enable Blend;

glBlendFunc(GL_DST_COLOR, GL_ZERO);
Draw the Inverted Mask (A bmp that was color-inverted);

glBlendFunc(GL_ONE, GL_ONE);
Draw Red; 

glBlendFunc(GL_DST_COLOR, GL_ZERO);
Draw the mask (not the inverted one);


This gives me Red and black, as I want. Now, I only need to figure out the parameters to put green where is black.

Any ideas?

There are two main places to do the mixing. The blending stage which is what you’re trying, and in the texture combiners. First one requires three passes, second one requires one pass but a three-texture multitexture setup.

The blending approach requires an alpha channel in the frame buffer, and that the mask is loaded as an alpha texture.
1: Set the depth test function to GL_LEQUAL. Draw the mask to the frame buffer, which means the alpha channel contains the blending factors.
2: Set blend function to draw the first texture scaled by the destination alpha and draw it. glBlendFunc(GL_DST_ALPHA, GL_ZERO).
3: Set blend function to add the frame buffer to the second texture scale by the inverse of the destination alpha. glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE).

Second approach using texture combiners. Check the specification, or some other documentation for the combiners.
1: Bind first and second texture and the mask to first, second and third texture units (order doesn’t matter, but I will refer to them in the order I just mentioned).
2: Set first and second texture combiner to GL_REPLACE. Actual combiner function is irrelevant though. The mixing is performed exclusively in the third combiner.
3: Set third texture combiner to peform interpolation.
3.1: Set combiner mode to GL_COMBINE.
3.2: Set combiner function to GL_INTERPOLATE.
3.3: The interpolation function blends ARG0 and ARG1 using ARG2 as interpolation factor. So set ARG2 to TEXTURE2 (first texture unit is the mask, or the interpolation factor), and ARG0 and ARG1 to TEXTURE0 and TEXTURE1, respectively (the textures to be blended).

The first approach is the simplest in terms of texturing requirements, as it requires just single-texturing. It does, however, require a destination alpha channel and some special care with the depth test function. The second approach requires three texture units, but is capable of doing it in one pass, and is also more flexible as it can control blend factors per color channel (the mask can be RGB and control the individual channels separately).

Thank you very much.

I’m using Delphi and GLScene, if this matter, and I’m still trying to get this working. I tried so far only the first approach you described, if I’ll not get this working, I’ll try the seccond method. Your second method is the same as this one http://www.gamedev.net/community/forums/topic.asp?topic_id=482462 ?

I haven’t looked at combiners yet, but from what I see in the post of V-man, I don’t get when should I bind the mask and the two others textures. Is something missing on that topic?

As for the method #1, I can’t get it to work. When I render only the alpha texture, I get a white quad. What should I see (shoulnd’t it be something like transparent where is black)?
And, for the depth testing, should I leave it on, while drawing all textures? I’ve tried switching on, off, changing places, etc, etc, and nothing get it right. I even set up 6 boxes that let me pick the glBlendFunc() parameters for each texture, so I could try all combinations, but none gave me the results I want.

Please, if I’m not asking much, does anyone knows of a demo I could see?

Thank you.

Edit: For the alpha texture, should I use it as transparent, modulate, replace? And the blending? Should I leave it off while drawing the mask?