Tricky Blending

I originally asked this in the beginners group awhile back, but the responses, while helpful, didn’t solve my problem so I decided to bump it up here.

Basically I’m working with two texture units and polygon color. What I would like to do is have both texture units be modulated with the polygon color but not with each other. I have no idea if it’s possible, I hope it is.

There are two methods that come close but don’t quite do it.

Polygon
Texture1: Modulated
Texture2: Decal.

or

Polygon
Texture1: Decal
Texture2: Modulated,
…Source0 Polygon
…Source1 Texture2

The second one comes the closest but it causes the first texture to be masked out. I’ve tried hundreds of ways, changing everything from the blendmodes to rgbsources. I’ve gotten close, but can’t seem to do it.

Any help would be greatly appreciated.

use crossbar functionality:
ARB_texture_env_crossbar or NV_texture_env_combine4 extensions will help you.

using ARB_texture_env_combine you can do

tex0: interpolate tex0 and tex1
tex1: modulate prev with primary color

I’m still trying to get to grips with texture combiners myself (especially since I’m not sure if all texenv calls are local to the active texture stage), but how about something like this:

glActiveTexture(GL_TEXTURE0);
glBindTexture(walltextureID);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

glActiveTexture(GL_TEXTURE1);
glBindTexture(decaltextureID);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB,GL_SRC_ALPHA);

glActiveTexture(GL_TEXTURE2);
glBindTexture(walltextureID); // used as dummy texture
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PRIMARY_COLOR);

 

Using three combiners, and ignoring the polygon color in the first stage. The decal would have to have an alpha channel (I presume it does).

The third stage modulates the combined “texture” with the primary color.

Originally posted by CrazyButcher:
[b]use crossbar functionality:
ARB_texture_env_crossbar or NV_texture_env_combine4 extensions will help you.

using ARB_texture_env_combine you can do

tex0: interpolate tex0 and tex1
tex1: modulate prev with primary color[/b]
Where can I find more on crossbar functionality? Well I found the Spec on it. Example source code would probably be more helpful.

It’s a really simple extension that extends the combiners.

It just allows you to use GL_TEXTURE?_ARB (with ? being the number of a texture unit) as argument for GL_SOURCE?_RGB (or ALPHA), just like you would use GL_TEXTURE when you want the current texture unit.

crossbar/combine4 allow you to use new targets in tex_combine functions as sources to the operation.

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCEx_RGB,TARGET);

TARGET can be GL_TEXTURE, GL_TEXTURE0_ARB, GL_TEXTURE1_ARB… GL_PRIMARY_COLOR, GL_CONSTANT, GL_PREVIOUS

you could also like T101 said use 3 stages, but likely if your hardware has more than 2 texture stages it will have crossbar or combine4

if you want to know more about ARB_texture_env_combine just use it as search keyword on the advanced forum you will find plenty threads

also this little app helps to play with the extension

http://www.ati.com/developer/sdk/rage128sdk/Multex/OGLMultex.html

I think I’m a little over my head here. I’m a little confused about how these two extensions are used. It’d be helpful to see an example. All I can find is documentation. I can’t find any example code.

Well, judging from the descriptions, you should be able to do this:

glActiveTexture(GL_TEXTURE0_ARB);
glBindTexture(walltextureID);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB,GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB,GL_SRC_ALPHA);

glActiveTexture(GL_TEXTURE1_ARB);
glBindTexture(decaltextureID);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);

Although it will only work if the extension is supported.
And you should check your header file if it’s GL_TEXTUREn or GL_TEXTUREn_ARB.

Obviously on combiner stage 0, GL_TEXTURE is equivalent to GL_TEXTURE0 etc.

So I don’t have to do anything to enable it in code, if it’s supported it will just work?

Judging by the extension spec (new state: none), you don’t need to enable it.

So for a quick and dirty version, you should be able to just use it.
But if you want to be robust, you should check at runtime if the extension is supported on the card, and use a different method (3 units or multipass) if it’s not.