Jump to content
  • Advertisement
Sign in to follow this  
karx11erx

Problem with color when multitexturing

This topic is 4449 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, when I am multitexturing a polygon in my program, the overlay texture is always rendered fully bright. How come, how can I fix that? Sample code:
typedef float tVertexf [3];
typedef struct tRGBAf {float r,g,b,a;} tRGBA;
typedef struct tTexCoordf {float u,v;} tTexCoord;

void RenderPoly (GLuint tex1, GLuint tex2, tVertexf *pv, tTexCoordf *ptc, int nv, tRGBAf *pc)
{
glEnable (GL_TEXTURE_2D);
//TMU 0 for base textures
glActiveTexture (GL_TEXTURE0_ARB);
glBindTexture (GL_TEXTURE_2D, tex1);
glEnable (GL_TEXTURE_2D);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// TMU 1 for overlay texture
glActiveTexture (GL_TEXTURE1_ARB);
glBindTexture (GL_TEXTURE_2D, tex2);
glEnable (GL_TEXTURE_2D);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBegin (GL_TRIANGLE_FAN);
for (; nv; nv--, pv++, ptc++) {
   glMultiTexCoord2f (GL_TEXTURE0_ARB, ptc->u, ptc->v);
   glMultiTexCoord2f (GL_TEXTURE1_ARB, ptc->u, ptc->v);
   glColor4f (pc->r, pc->g, pc->b, pc->a);
   glVertex3f (pv->x, pv->y, pv->z);
   }
glEnd ();
glDisable (GL_TEXTURE_2D);
}






[Edited by - karx11erx on April 7, 2006 10:19:03 AM]

Share this post


Link to post
Share on other sites
Advertisement

Probably you are modulating the base texture with your diffuse and then adding the second texture on top of it.

You should first blend the base and the second texture together (by alpha or what ever formula you want to use) and the modulate that result with the diffuse.

Share this post


Link to post
Share on other sites
There are a couple things I noticed that seem odd.

First, there is no glBind function. If it's a function you wrote, don't use the gl prefix; that is reserved for OpenGL's use. I'll assume that's actually glBindTexture(GL_TEXTURE_2D, ...) in your code.

Second, glTexEnv when pname is GL_TEXTURE_ENV_COLOR takes a 4-element array in params, not one of OpenGL's constants. I guess you aren't checking for OpenGL errors (you should be) because that would be throwing a GL_INVALID_ENUM error.

Now, what do you mean by "rendered fully bright?" I don't think you mean anything to do with lighting because I don't see any lighting-related function calls in there. Perhaps you could explain the problem a little more and possibly post a screenshot as well?

Share this post


Link to post
Share on other sites
The actual code calls glBindTexture.

I don't think prefixing self-written function names with 'gl' does any harm, as long as I don't use a real OpenGL name.

I have removed the erroneous calls to glTexEnv, didn't make a difference.

The application doesn't use any OpenGL lighting functions, everything is done with calls to glColor().

Here's a screenshot: The bright purple texture at the sides should be as dark as the rearward face. If I use GL_MODULATE instead of GL_DECAL for the overlay textures, this works - but then I have cases where the overlay textures gets almost completely merged with the background, instead of clearly standing out.



[Edited by - karx11erx on April 7, 2006 10:49:28 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by karx11erx
...
I don't think prefixing self-written function names with 'gl' does any harm, as long as I don't use a real OpenGL name.
...
True, it's not too big a deal. It is possible (extremely unlikely however) that there will eventually be a function with the same name added to OpenGL, but the main reason not to prefix your own functions with 'gl' is for code clarity; so that someone else (or maybe even you if you're looking back at your old code for some reason) who is reading your code doesn't get confused.
Quote:
Original post by karx11erx
...
Here's a screenshot: The bright purple texture at the sides should be as dark as the rearward face. If I use GL_MODULATE instead of GL_DECAL for the overlay textures, this works - but then I have cases where the overlay textures gets almost completely merged with the background, instead of clearly standing out.

First let me ask, am I right in assuming that the face in the middle of the screen has just one texture and that's why that one is working fine?

Okay, I think I understand your problem. The problem with what you have now is that the overlay texture isn't being modulated by your pc parameter because you are using GL_DECAL environment mode. When you set it to GL_MODULATE you get the wrong result because it doesn't take into account the overlay texture's alpha channel when it blends. What you want is for the background texture and the overlay texture to both by modulated with the pc color and then blended like in GL_DECAL. ie:
What you have now...
(TbCp)(1-Ao) + ToAo

What you want...
(TbCp)(1-Ao) + (ToCp)Ao
where Tb is the color of the background texture, To is the color of the overlay texture, Ao is the alpha of the overlay texture, and Cp is the primary color (glColor4f). Does all that sound right?

If that is what you want, I think you should be able to do this with a little help from texture combiners (became core in OpenGL v1.3, so if you're on Windows you'll have to access it as an extension).

With a little fiddling you can get that function above to be this...
     Cp(Tb(1-Ao) + ToAo)
which you can see is the primary color modulated by the result of the GL_DECAL function without first modulating the background texture. I'm pretty sure you can do this with texture combiners (it's been a while since I've used them). What you do is set the first texture unit's environment to output just the background texture (GL_REPLACE). Set the second texture unit environment to GL_DECAL so that it outputs what's inside the parentheses above. This is the part I'm not 100% sure about... that you can set up a texture unit environment stage without having a texture bound to that unit. So assuming that's possible, you can set texture unit 2's environment to GL_COMBINE, set the GL_COMBINE_RGB mode to GL_MODULATE, and set the two sources to GL_PRIMARY_COLOR and GL_PREVIOUS.

If you want I can post a little source snippet later (gotta get lunch now) to help out, but I won't be able to test it here at work.

Hope that all helps (and works!)

EDIT: Actually, you definitely shouldn't need to bind a texture to tex unit 2 because the default texture will be bound. You will probably need to enable texturing on that texture unit though.

[Edited by - Kalidor on April 7, 2006 12:00:22 PM]

Share this post


Link to post
Share on other sites
Kalidor,

thank you very much for your reply.

Actually, I don't use any functions prefixed 'gl' ... ;)

If you could provide a code snippet I'd appreciate it. I find the OpenGL docs pretty hard to understand.

Share this post


Link to post
Share on other sites
Quote:
Original post by karx11erx
Kalidor,

thank you very much for your reply.

Actually, I don't use any functions prefixed 'gl' ... ;)

If you could provide a code snippet I'd appreciate it. I find the OpenGL docs pretty hard to understand.
Yeah, they certainly take some getting used to. [grin]

Here's a little code snippet for you, and remember it's completely untested so it's very likely there's a problem or two (hopefully just syntactic or a typo instead of logical).
//Set up texture unit 0 to output just the background texture
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, backgroundTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

//Set up texture unit 1 to output the overlay texture blended
//with the background texture using the GL_DECAL function
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, overlayTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

//Now here is the texture combiner part
//Set up texture unit 2 to output the background/overlay blend
//modulated by the primary color
glActiveTexture(GL_TEXTURE2);
glEnable(GL_TEXTURE_2D);
//Note we don't bind a texture since we don't use it in the environment
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

//What that does is set texture unit 2's environment to the modulate
//combine function (arg0 * arg1) and sets arg0 to the primary color
//and arg1 to the result from the previous texture combiner stage

//Now you render your geometry

//Remember to disable texturing on all the texture units so we don't
//accidently mess up something else we try to do after this
glActiveTexture(GL_TEXTURE2);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);



Hope that works for you. If there are any problems you can't figure out just post back and I'll try to look into it more.

Share this post


Link to post
Share on other sites
Thank you very much indeed. I wonder how long it would have taken me to figure that by reading OpenGL docs and tutorials. Probably forever. :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!