Multitexturing->Mix two textures

hello,

I try to mix two textures (grass and soil for example) but would setup the mix factor with a third texture that is a gray level texture…

these are the grass textures and soil texture:

I would mix the two textures above, using the color of this texture in order to setup the mix factor between them:

and I would obtain this:

But, I don’t how to do that with openg…
This is the code which I try to mix the textures but it doesn’t work…because I obtain the product of textures and 2 and not the product of textures 0 and 1 with texture 2 as mix factor…

In this code: nom[0] is soil texture
nom[1] is grass texture
nom[2] is level gray texture


glActiveTextureARB( GL_TEXTURE0_ARB );
glEnable( GL_TEXTURE_2D );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glBindTexture(GL_TEXTURE_2D,nom[0]);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

            glActiveTextureARB( GL_TEXTURE1_ARB );
            glEnable( GL_TEXTURE_2D );
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS );
            glBindTexture(GL_TEXTURE_2D,nom[1]);
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
            glBindTexture(GL_TEXTURE_2D,nom[2]);
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE );
            glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
            glTexEnvi( GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_MODULATE );

thank you very much.

with tex_env_crossbar or nv_combine4:
tex0 = unit0 with grass
tex1 = unit1 with soil
tex2 = unit2 with greyscale (you should pack greyscale as 8bit alpha-texture)

combiner
tex0 =
color: decal between tex0 and tex1, using tex2 alpha
tex1 = replace prev
tex2 = replace prev

without those extensions
units
tex0 = mix texture
tex1 = grass
tex2 = soil

combiner
tex0 = replace
tex1 = colorop: replace tex , alphaop: replace prev
tex2 = decal: between prev and tex using prev.alpha

You can do it with vanilla ARB env combine and ARB crossbar and a single combiner unit. Simply set each texture as each of the three inputs and use an INTERPOLATE capability to interpolate between the two images using your ramp texture, the ramp would be the third input (arg2).

http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt

This will be supported functionality on pretty much all modern cards and is even part of core OpenGL now so you can use it with confidence.

Thank you for replying me and excuse me for this late answer…
But I’m only a beginner with multitexturing and I didn’t understand all you have said…

In fact I don’t know how I can adapt all you have said…

How can I integrate tex_env_crossbar or nv_combine4 or vanilla ARB env combine and ARB crossbar in my code??

Thank you.

ARB combiners and ARB crossbar are part of the core.

Vanilla just means ‘nothing fancy’, or unadulterated.

No need to integrate to integrate anything, do it my way and use a single texenv unit and 3 texture images… hmmm you may need to use the last available texture unit instead of the first. It’s all supported in teh shipping values. You need only make the OpenGL texparameter calls with the appropriate combiner and crossbar tokens, it’s easy.

Maybe i’m hopeless but I don’t understand how I can do that!
Can you explain me with an example, please?

And I saw in a discussion this:

INTERPOLATE_ARB – Interpolate (blend) between source0 and source1 using source2 as a t factor

It seems to be easy but when I set grass as source0 , soil as source1 and greyscale texture as source2 it doesn’t work…

thans a lot for your patience!

Just removed the dust from a tool I wrote a couple of years ago (yuck, am I doing this for that long time already :rolleyes: ). It lets one “click” everything together and generates proper code for it :slight_smile:

Originally posted by CrazyButcher:
with tex_env_crossbar or nv_combine4:
tex0 = unit0 with grass
tex1 = unit1 with soil
tex2 = unit2 with greyscale (you should pack greyscale as 8bit alpha-texture)

combiner
tex0 =
color: decal between tex0 and tex1, using tex2 alpha
tex1 = replace prev
tex2 = replace prev

Originally posted by CrazyButcher:
without those extensions:
units
tex0 = mix texture
tex1 = grass
tex2 = soil

combiner
tex0 = replace
tex1 = colorop: replace tex , alphaop: replace prev
tex2 = decal: between prev and tex using prev.alpha[/qb]

// OpenGL texture environment
// file generated by gl_tut texture environment

//----------------
//|texture unit 0|
//----------------
GLuint  tex_id0;
GLfloat env_color0[4] = {0.808740f,0.193304f,0.563585f,0.001251f};
GLint   rgb_scale0    = 1;
GLint   alpha_scale0  = 1;

glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,tex_id0);

glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,env_color0);
glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_RGB_SCALE,rgb_scale0);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE1);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale0);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_ALPHA);

//----------------
//|texture unit 1|
//----------------
GLuint  tex_id1;
GLfloat env_color1[4] = {0.895962f,0.350291f,0.479873f,0.585009f};
GLint   rgb_scale1    = 1;
GLint   alpha_scale1  = 1;

glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,tex_id1);

glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,env_color1);
glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_RGB_SCALE,rgb_scale1);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale1);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_ALPHA);

//----------------
//|texture unit 2|
//----------------
GLuint  tex_id2;
GLfloat env_color2[4] = {0.858943f,0.174108f,0.746605f,0.822840f};
GLint   rgb_scale2    = 1;
GLint   alpha_scale2  = 1;

glActiveTexture(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,tex_id2);

glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,env_color2);
glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_INTERPOLATE);
glTexEnvi (GL_TEXTURE_ENV,GL_RGB_SCALE,rgb_scale2);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
// arg 1
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
// arg 2
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE2_RGB,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND2_RGB,GL_SRC_ALPHA);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale2);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_ALPHA);
// arg 1
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE1_ALPHA,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND1_ALPHA,GL_SRC_ALPHA);
// arg 2
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE2_ALPHA,GL_CONSTANT);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND2_ALPHA,GL_SRC_ALPHA);

this tool is quite old, but illustrates arb_tex_env_combine

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

nv_combine4 or arb_tex_env_crossbar let you pick different source textures (not just current/previous)

ScottManDeath> Thank you for your reply, but your solution seems to be a little complicated…

I’ve try to integrate it in my code but it doesn’t work…
Moreover, the textures that I use haven’t an alpha layer…and severals lines in this code seems to be not useful ( for what i want to do), like these:

glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,env_color2);
or
glTexEnvi (GL_TEXTURE_ENV,GL_RGB_SCALE,rgb_scale2);

CrazyButcher> thank you but this tool illustrate only blending between two textures using their alpha layer and not a gray scale texture…

interpolate operand can be set to COLOR as well, so you dont necessarily need to use alpha.

the sample actually lets you change many parameters

you dont need to use those 2 commands. in your original post you were already using tex_env_combine, you just didnt set all commands, like operands, and sources.

like for interpolate, source2 set to your texture that contains the greyscale, you would also need to set the operand to COLOR and not ALPHA with following

glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);

In ARB_texture_env_combine specs I saw this :

COMBINE_RGB_ARB Texture Function


REPLACE Arg0
MODULATE Arg0 * Arg1
ADD Arg0 + Arg1
ADD_SIGNED_ARB Arg0 + Arg1 - 0.5
INTERPOLATE_ARB Arg0 * (Arg2) + Arg1 * (1-Arg2)
SUBTRACT_ARB Arg0 - Arg1

So if I set grass as source0, soil as source2 and grayscale texture as source1 I would obtain what I want to do…
But there is something wrong because if I do that it doesn’t work:

            glActiveTextureARB( GL_TEXTURE0_ARB );
            glEnable( GL_TEXTURE_2D );
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
            glBindTexture(GL_TEXTURE_2D,nom[0]);
            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
            glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
            
            glActiveTextureARB( GL_TEXTURE1_ARB );
            glEnable( GL_TEXTURE_2D );
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
            
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS );
            glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
            
            glBindTexture(GL_TEXTURE_2D,nom[2]);
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
            glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);
            
            glBindTexture(GL_TEXTURE_2D,nom[1]);
            glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
            glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND2_RGB,GL_SRC_COLOR);

            glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE );

where nom[0] is soil
nom[1] grass
nom[2] grayscale

Moreover it is really strange but if I invert the two last paragraphs It does’nt do the same thing!!
With the code above I obtain a the product between grass and soil only…and with tje code below I obtain the product between soil and greyscale only…where is interpolation here??

glActiveTextureARB( GL_TEXTURE0_ARB );
glEnable( GL_TEXTURE_2D );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glBindTexture(GL_TEXTURE_2D,nom[0]);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

glActiveTextureARB( GL_TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);

glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS );
glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

glBindTexture(GL_TEXTURE_2D,nom[1]);
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND2_RGB,GL_SRC_COLOR);

glBindTexture(GL_TEXTURE_2D,nom[2]);
glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
glTexEnvi( GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);

glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE );

you are not using arb_combine correctly
it works per-stage, not as total effect

the ati sample actually illustrates this, too

e.g. you want to interpolate between 2 textures
you would bind texture 0 and set it to replace
then you would bind texture 1 and set combiner_rgb to interpolate.
now you need to specify all operands/sources for this stage.
which results into something what ScottManDeath has posted.
each combiner runs independent of the ones bound to other texture units.

another mistake is that you bind 2 textures to the same textureunit (nom1 and nom2) so only the last one nom2 will be really used.

you can only bind 1 texture per texture unit.

So what can I do to solve this problem?

I don’t know how I can do this without two glBindTexture…

you cant do this effect if your card supports just 2 texture units.

if you have more, use activetexture to activate the third texture unit and bind the proper texture to it.

the thread should contain enough info, after all scottman already posted large portions of code. you have to work yourself thru understanding arb_tex_env_combine and how multi-texturing works in general…

My graphic card support more than 2 textures…
But I’m a beginner with multitexturing in opengl and I swear that I tried to use scottManDeath’s code but in my opinion it is really difficult to obtain the effect that I want! Moreover scottManDeath in his code set alpha layer for all texture unit…and what I want to do is just mix grass texture and soil texture with grayscale as mix factor…
Perhaps I could multiply grass texture with grayscale and on a other side multiply soil texture with grayscale inverted and finally adding the two textures obtained…but I think it is not possible to do this with opengl and it is not fast…

I have another question: what is the difference between GL_TEXTURE and GL_TEXTURE1 ?? When I replace GL_TEXTURE in scottManDeath’s code by GL_TEXTURE it don’t work at all!

thank you

this what I do now to set up the textures, but I don’t understand why it doesn’t work…

nom[0] is soil
nom[1] grass
nom[2] grayscale (now it is a TGA texture were the gray scale is the alpha layer)

//|texture unit 0|
//----------------
GLint alpha_scale0 = 1;

glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,nom[2]);

glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE1);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale0);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_ALPHA);

//----------------
//|texture unit 1|
//----------------
GLint alpha_scale1 = 1;

glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,nom[1]);

glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);

// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale1);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_ALPHA,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_ALPHA,GL_SRC_ALPHA);

//----------------
//|texture unit 2|
//----------------
GLint alpha_scale2 = 1;

glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,nom[0]);

glTexEnvi (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);

// RGB combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_ADD);

// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE0_RGB,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND0_RGB,GL_SRC_COLOR);
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND1_RGB,GL_SRC_COLOR);

// ALPHA combiner setup
glTexEnvi (GL_TEXTURE_ENV,GL_COMBINE_ALPHA,GL_REPLACE);
glTexEnvi (GL_TEXTURE_ENV,GL_ALPHA_SCALE,alpha_scale2);
// arg 0
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE1_ALPHA,GL_PREVIOUS);
glTexEnvi (GL_TEXTURE_ENV,GL_OPERAND1_ALPHA,GL_ONE_MINUS_SRC
_ALPHA);

The comment says “texture unit 2” but the code i still using TU 1.

It doesn’t work because you’ve not done what some posters have written here.

Use interpolate and crossbar, 3 texture images into one texenv unit with interpolate. Use the last unit.

Unless your next post begins “It’s working!” or “I’ve tried to use interpolate on the third texenv unit with 3 active textures as the inputs in the few combinations available” then don’t post until you’ve done some more work on the problem.

It is simple to use crossbar, you just specify a texture unit token (numbered unit) as the input to a combiner argument.

Set up the textures on 3 enabled units and on unit 3 (i.e. GL_TEXTURE2) the one with the ramp image do this:

glActiveTextureARB(GL_TEXTURE2);

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);
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE1_RGB,GL_TEXTURE1);
glTexEnvi (GL_TEXTURE_ENV,GL_SOURCE2_RGB,GL_TEXTURE2);

No need for alpha if your ramp is grey in color. See how simple it could have been :wink:
(You are invited to go back & read my first post in this thread now.)

Butcher tried to help too (gj) but this thread went to hell fast. Butcher’s DECAL (P.S. decal isn’t but blend would be(P.P.S. BLEND equivalency isn’t a biggie since there’s a dependency of crossbar on combine)) on the first unit with passthrough on later units is equivalent. All this got lost in the noise. Just because someone posts code doesn’t mean you should ignore other posters, you were told the simplest way to do this at least twice from two sources in this thread.

I have really work on this part of code, I have spent hours on this , modifying it, trying to find the way to do the mix that I want, searching on the net documentations…on extensions but they are always not explicit!
So, please, don’t tell me that I have not work on it! I don’t understand how I could guess the way to do multitexturing with opengl without some piece of code who show me the way to use GL_ARB_texture_env_crossbar…
I try to do this, enablig UNIT0 and 1 to use the color of grass and soil texture and enabling finally Unit2 and do what you show me in your last post.But it still don’t work…

tamlin> thank you! it was a careless mistake!

thank you.