PDA

View Full Version : transitioning from 1 texture to another


Jake
2004.09.26, 08:13 PM
I recently have been working with multi texturing and I decided that a quick way to get GL Golf to look way better would be to blend the edges of surfaces together like this

http://nuclearnova.com/temp/transition.jpg

If I know each of the two textures and weight values as a percent, how would I do this?

arekkusu
2004.09.27, 04:23 AM
In general what you want to do is draw the underlying texture (let's call that "grass") with alpha=1.0 everywhere. And the overlying texture ("water") with alpha interpolating across the quad from 0.0 to 1.0.

There are a few different ways to achieve this: you could draw all your grass in one pass, then the water as separate meshes. Or you could draw them both over the same geometry with multitexturing. To fade the water out, you could use either the interpolated vertex alpha, or you could make a separate landscape mask texture, like a light map.

Which way you go depends on how much control you want of the blending edge. But let's say you want to do it in one pass with multitexturing, and don't care so much about pixel-level control:

Set "grass" to texture unit 0 and set up the texture environment to COMBINE (http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt) mode-- if you want to be able to colorize the grass with the vertex color (for brown/green/yellow colorization of the same texturemap) then you can use MODULATE for the RGB component; otherwise REPLACE. For the alpha, use a CONSTANT 1.0.

Set "water" to texture unit 1 and use COMBINE mode again. Use INTERPOLATE mode for both RGB and A to blend between the PREVIOUS (unit0) result and the TEXTURE ("water") fragment, using PRIMARY_COLOR (the vertex alpha) as source2, use SRC_ALPHA for operand2.

Jake
2004.09.27, 02:55 PM
Set "grass" to texture unit 0 and set up the texture environment to COMBINE (http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt) mode-- if you want to be able to colorize the grass with the vertex color (for brown/green/yellow colorization of the same texturemap) then you can use MODULATE for the RGB component; otherwise REPLACE. For the alpha, use a CONSTANT 1.0.

Set "water" to texture unit 1 and use COMBINE mode again. Use INTERPOLATE mode for both RGB and A to blend between the PREVIOUS (unit0) result and the TEXTURE ("water") fragment, using PRIMARY_COLOR (the vertex alpha) as source2, use SRC_ALPHA for operand2.

Thanks, I will test that tonight!

Jake
2004.09.28, 10:08 PM
I had a start to the code, but I am sure I am doing some stuff wrong. Can somone please fix this?

glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, gv->texture[k] );

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);

glActiveTexture(GL_TEXTURE1);
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, gv->texture[m] );

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);


Also, how do I send two alpha values with glColor4f?


glNormal3f(vertexCount[whichTriangle].x, vertexCount[whichTriangle].y, vertexCount[whichTriangle].z );
glMultiTexCoord2fARB(GL_TEXTURE0_ARB,i,j);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB,i,j);
glColor4f(0.0,0.0,0.0,mPer[0][i][j]);
glVertex3f(-(i+offsetx)*levelScale, mPer[2][i][j]*levelScale, (j+offsetz)*levelScale );

arekkusu
2004.09.29, 02:10 PM
This setup works as I described. I made a sample project, if you want I'll mail it to you.


void RenderMap() {
// set up the first texture unit for grass
glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[GRASS]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // example grass tinting
GLfloat constant[4] = {1, 1, 1, 1};
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_CONSTANT);

// set up the second texture unit for water
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[WATER]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);

// draw a mesh (just one quad for now)
glBegin(GL_QUAD_STRIP);

glColor4f(1, 0, 1, 0); // tint one grass corner purple as example
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
glVertex2f(0, 0);

glColor4f(1, 1, 1, 0); // normal grass color
glMultiTexCoord2f(GL_TEXTURE0, 0, 1);
glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
glVertex2f(0, 1);

glColor4f(1, 1, 1, 1); // normal water color
glMultiTexCoord2f(GL_TEXTURE0, 1, 0);
glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
glVertex2f(1, 0);

glMultiTexCoord2f(GL_TEXTURE0, 1, 1);
glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
glVertex2f(1, 1);
glEnd();
}


Note that this relies on some of the COMBINE default values-- see the spec to understand what they are. You can always set everything explicitly to be safe.

You don't need to set two alpha values. There's one primary alpha value per vertex, which is interpolated along the quad. It serves as the % of water texture to blend in.

Jake
2004.09.30, 09:22 PM
it always uses 100% water here


EDIT : It turned out that enabling lighting is what was screwing everything up, how do I light stuff and blend it together?



glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gv->texture[1] );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // example grass tinting
GLfloat constant[4] = {1, 1, 1, 1};
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_CONSTANT);

// set up the second texture unit for water
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gv->texture[4]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);

glBegin(GL_QUADS);
for( i = 1; i < (levelx-1); i++ )
{
for( j = 1; j < (levely-1); j++ )
{
if ((mTex[0][i][j] == k && mTex[1][i][j] == m) && (mPer[0][i][j] != 1.0)) {
whichTriangle = [self whichTria:i z:j];
glColor4f(1.0,1.0,1.0,0.0);
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
glVertex3f(-(i+offsetx)*levelScale, mPer[2][i][j]*levelScale, (j+offsetz)*levelScale );

whichTriangle = [self whichTria:i+1 z:j];
glColor4f(1.0,1.0,1.0,1.0);
glMultiTexCoord2f(GL_TEXTURE0, 0, 1);
glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
glVertex3f(-((i+offsetx)+1)*levelScale, mPer[2][i+1][j]*levelScale, ((j+offsetz))*levelScale );

whichTriangle = [self whichTria:i z:j+1];
glMultiTexCoord2f(GL_TEXTURE0, 1, 0);
glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
glColor4f(1.0,1.0,1.0,mPer[0][i][j+1]);
glVertex3f(-((i+offsetx)+1)*levelScale, mPer[2][i+1][j+1]*levelScale, ((j+offsetz)+1)*levelScale );

whichTriangle = [self whichTria:i+1 z:j+1];
glMultiTexCoord2f(GL_TEXTURE0, 1, 1);
glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
glColor4f(1.0,1.0,1.0,mPer[0][i+1][j+1]);
glVertex3f(-((i+offsetx))*levelScale, mPer[2][i][j+1]*levelScale, ((j+offsetz)+1)*levelScale );

}
}

arekkusu
2004.09.30, 11:27 PM
(mailed reply:)
man glColorMaterial

arekkusu
2004.10.25, 11:27 PM
Revisiting this, Jake has lighting enabled. In that case, what you want is the lit vertex color modulated with the two textures which have been interpolated according to the vertex alpha. Or:

LIT_PRIMARY_RGB * (TEXTURE0*PRIMARY_A + TEXTURE1*(1-PRIMARY_A))

This is equivalent to the problem I had (http://www.idevgames.com/forum/showthread.php?t=1232) with interpolating two alpha textures modulated by the polygon color.

As OSC described there, you can do this with three texture units: REPLACE, INTERPOLATE, MODULATE. But then it won't work on older GPUs.

Henry pointed out that it might be possible with two units if the vertex alpha is always one. Well, Jake doesn't care about the resulting vertex alpha (the terrain will always be opaque), he only uses the vertex alpha as an interpolator.

Can anyone see a clever way to do lit two-texture terrain in one pass with two texture units?

Jake
2004.10.28, 04:20 PM
Thanks Alex for posting, I was actually just getting on to restate the question, but you already did for me!

I have friday off of school so I am going to spend some time getting this finished out, and I will have a big of enough update to make GL Golf 1.4.

Jake
2004.10.29, 10:42 AM
Here is an update - I tried to add the third texture unit but I am getting the same results - Here is a snippet of the relevant code.

But first, in this thread someone said that it is possible to use two texture units if the alpha is only going to be a 0 or 1, how can I do that because that is true for me?
http://www.idevgames.com/forum/showthread.php?t=1232

Thanks


glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);

for(k=0; k<5; k++)
{
for(m=0; m<5; m++)
{
if (m != k) {
// set up the first texture unit for the main textre
glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gv->texture[m] );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); // example grass tinting
GLfloat constant[4] = {1, 1, 1, 1};
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_CONSTANT);

// set up the second texture unit for blended texture
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gv->texture[k]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);

// set up the third texture unit for light modulation
glActiveTextureARB(GL_TEXTURE2);
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_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);

glBegin(GL_QUADS);
for( i = 1; i < (levelx-1); i++ )
{
for( j = 1; j < (levely-1); j++ )
{
whichTriangle = [self whichTria:i z:j];
if (mPer[3][i][j] == m && (mTex[0][i][j] == k || mTex[1][i][j] == k) && mPer[0][i][j] != 1) {
glNormal3f(vertexCount[whichTriangle].x, vertexCount[whichTriangle].y, vertexCount[whichTriangle].z );
glMultiTexCoord2f(GL_TEXTURE0, (i)*levelScale/textureSizes[m], (j)*levelScale/textureSizes[m]);
glMultiTexCoord2f(GL_TEXTURE1, (i)*levelScale/textureSizes[k], (j)*levelScale/textureSizes[k]);
glColor4f(1.0,1.0,1.0,0.0);
glVertex3f(-(i+offsetx)*levelScale, mPer[2][i][j]*levelScale, (j+offsetz)*levelScale );

arekkusu
2004.10.29, 07:37 PM
No solutions, but just for reference these threads discuss the same problem:
one (http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=2;t=008991)
two (http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=2;t=007611)

Jake
2004.11.01, 05:38 PM
What is wrong with this piece of code - it doesn't seam to be correctly modulating the color with the second texture (unit #1)?


// set up the third texture unit for light modulation
glActiveTextureARB(GL_TEXTURE2);
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_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR)

arekkusu
2004.11.01, 05:50 PM
Is unit2 enabled?

[Edit: it looks like you have to actually have a texture bound to the active unit, even if you don't sample the texture data in the combine stage for that unit. Blah. Here's code using three units:]


void RenderMap() {
// set up the first texture unit for grass
glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[GRASS]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

// set up the second texture unit for water
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[WATER]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);

// set up the third texture unit for primary color tinting
glActiveTextureARB(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[WATER]); // dummy texture, not sampled
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);
GLfloat constant[4] = {1, 1, 1, 1}; // force final output alpha to 1, doesn't matter if not blending
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);

// draw a mesh (just one quad for now)
glBegin(GL_QUAD_STRIP);
glColor4f(1, 0, 0, 0); // tint top edge red as example
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
glVertex2f(0, 0);

glColor4f(1, 1, 1, 0); // normal grass color
glMultiTexCoord2f(GL_TEXTURE0, 0, 1);
glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
glVertex2f(0, 1);

glColor4f(1, 0, 0, 1); // tint top edge red as example
glMultiTexCoord2f(GL_TEXTURE0, 1, 0);
glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
glVertex2f(1, 0);

glColor4f(1, 1, 1, 1); // normal water color
glMultiTexCoord2f(GL_TEXTURE0, 1, 1);
glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
glVertex2f(1, 1);
glEnd();
}

arekkusu
2004.11.01, 06:23 PM
And here's another approach, which does the interpolation and color tinting using only two texture units:


void RenderMap() {
// set up the first texture unit to interpolate between grass and water using crossbar extension
glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[GRASS]);
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_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);

// set up the second texture unit for primary color tinting
glActiveTextureARB(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[WATER]); // sampled only by first unit
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);
GLfloat constant[4] = {1, 1, 1, 1}; // force final output alpha to 1, doesn't matter if not blending
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);

// draw a mesh (just one quad for now)
glBegin(GL_QUAD_STRIP);
glColor4f(1, 0, 0, 0); // tint top edge red as example
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
glMultiTexCoord2f(GL_TEXTURE1, 0, 0);
glVertex2f(0, 0);

glColor4f(1, 1, 1, 0); // normal grass color
glMultiTexCoord2f(GL_TEXTURE0, 0, 1);
glMultiTexCoord2f(GL_TEXTURE1, 0, 1);
glVertex2f(0, 1);

glColor4f(1, 0, 0, 1); // tint top edge red as example
glMultiTexCoord2f(GL_TEXTURE0, 1, 0);
glMultiTexCoord2f(GL_TEXTURE1, 1, 0);
glVertex2f(1, 0);

glColor4f(1, 1, 1, 1); // normal water color
glMultiTexCoord2f(GL_TEXTURE0, 1, 1);
glMultiTexCoord2f(GL_TEXTURE1, 1, 1);
glVertex2f(1, 1);
glEnd();
}


However this uses ARB_texture_env_crossbar functionality, which is only exported on Radeon7000+ under 10.3 (or Radeon9600 under 10.2.) It won't work on Rage128 due to hardware limitations. It *might* work on the nvidia cards even though the extension isn't exported, I haven't tested. So this might be a way to get your effect to work on GF2MX and GF4MX cards in only one pass. But you'll still need two passes for Rage128.

Jake
2004.11.01, 06:30 PM
Thanks for the help, that cleaned up my code and got it working!

But It has 3 side effects...

1. There is a red tint to everything, mostly in the distance
2. Anything with blending is now messed up (tree transparencies are now black)

Is there a way to revert back to the normal texture mode after I am done?

2. Here is how I normally go back to 1 texture unit when I am done


glActiveTexture(GL_TEXTURE2);
glDisable( GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE1);
glDisable( GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE0);


Even if I do that AFTER I am done drawing my multitextures it screws the multitextured quads...

I can get some screenshots if needed, but my internet is sketching out now so I will only get them if you need them.

Thanks!

arekkusu
2004.11.01, 07:27 PM
You need to revert all of the state. So for example, with the 3-unit code, I set texture0 to
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
That will kill all transparency, you need to set it back to DECAL or MODULATE depending if you're doing blending.

Similarly disable glColorMaterial and any other state that was changed for the terrain render. GL is just a big state machine, remember...

Jake
2004.11.02, 06:36 PM
That makes perfect sense, and simply putting a glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); on each texture fixed that.

But I still have an odd red tint, here is a screenshot

http://nuclearnova.com/temp/redtint.jpg

arekkusu
2004.11.02, 10:07 PM
There is a red tint to everything, mostly in the distance

Since it's in the distance, it could be fog or mipmap related. But I'm not sure what'd be causing that in relation to the texture combine environment. I'd start with searching all your source for red color constants. My code snippets used a red tint as an example, but your actual material colors should be 1.0, 1.0, 1.0, blendfactor...

Jake
2004.11.02, 10:37 PM
Hum... I just commented out any line with fog and turned the textures to linear and it still didn't help. I searched for any occurrence of 1.0 or 0.0 in my render code and didn't find anything red. I am clueless here...

Hog
2004.11.03, 04:13 AM
what about red textures? try turning off all texture units

Jake
2004.11.03, 06:52 PM
I got rid of the second and third texutre unit, leaving this


glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);


glActiveTextureARB(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gv->texture[m]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);


Meaning its probably the colormaterial

Jake
2004.11.03, 07:12 PM
And here's another approach, which does the interpolation and color tinting using only two texture units:

However this uses ARB_texture_env_crossbar functionality, which is only exported on Radeon7000+ under 10.3 (or Radeon9600 under 10.2.) It won't work on Rage128 due to hardware limitations. It *might* work on the nvidia cards even though the extension isn't exported, I haven't tested. So this might be a way to get your effect to work on GF2MX and GF4MX cards in only one pass. But you'll still need two passes for Rage128.

WOW! I missed over that post completely! I just added that to my code and it works great with a mobile 9200. Can anyone confirm if that works on a nvidia card?

Also, the red tint is still there :(

arekkusu
2004.11.03, 08:25 PM
Meaning its probably the colormaterial
Well, look at your vertex colors then. Don't use red.

Can anyone confirm if that works on a nvidia card?
I did test this in the lab on Tuesday and it looks like texture_env_crossbar will work under 10.3 on all nvidia and ATI cards newer than the Rage128. However the extension isn't exported on any nvidia cards. There is a discussion about this here (http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=3;t=007321) (and searching for "nvidia crossbar" finds many other threads.)

It also isn't exported on 10.2 on a lot of ATI cards, I don't know if it will work or not there. I'm at the point where I'm requiring 10.3 for all new projects...

Jake
2004.11.03, 09:01 PM
My vertex colors are all 1.0,1.0,1.0 though, how could that only effect red?

I want to be really safe because this is a shareware game I want everyone to be able to play.I should check the version of OS X, if its 10.2 use 3 texture units, and if its 10.3 use 2 units, but first check to see if I have that many units available first. Right?

arekkusu
2004.11.03, 09:14 PM
You have lighting on though. So the vertex colors are affected by the light and ambient colors.

If you want to support 10.2 and Rage 128, I think your fallback mechanism will have to do two passes. You may be able to run on all other cards with only two units using crossbar, on both 10.2 and 10.3. But you'll have to test it to make sure it works. That's what labs and public beta tests are good for.

Jake
2004.11.04, 04:18 PM
Ah, I just found out I needed to put a glColor3f(.3,.3,.3) before these lines, thats where my red tint was coming from.

glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);

I should have a public beta soon, I am kind of excited about this release because I have put a lot of effort into it and it should help my registration conversion rate, as well as a smaller file size should get more downloads.

arekkusu
2004.11.10, 07:26 AM
... it looks like texture_env_crossbar will work under 10.3 on all nvidia and ATI cards newer than the Rage128. However the extension isn't exported on any nvidia cards.

As of 10.3.6, it is exported on all nvidia cards, see chart (http://homepage.mac.com/arekkusu/bugs/GLInfo.html). That's a hint that it will work in any OS version, though you still need to test it.

arekkusu
2004.11.11, 01:59 AM
It also isn't exported on 10.2 on a lot of ATI cards, I don't know if it will work or not there.
Looks like it definitely does not work on some ATI cards under 10.2.8; the 7000, 7200, and 7500 at least. It appears to work on the 9000, 9200, 9600 and nvidia cards, at least the one case I tried. Probably safest to just require 10.3.

Jake
2004.11.11, 06:50 PM
Thanks. What I am doing now is if the user has 10.2 I default to my OLD render mode, if they have 10.2 with >=3 texture units, I use the 3 texture unit solution you made. If they have 10.3 and >1 texture unit I use the crossbar method.