PDA

View Full Version : Multitexturing (again).



dabeav
07-09-2002, 04:50 AM
I want to make a simple multitexture program. I want to apply a "lightmap" to a poly, then multiply by the "base texture" (creating a "shadow of the light" map accross the base texture). Then I draw my model. I then do another pass to "add" the same lightmap to the scene. (Which should create a specular effect on the scene). But I only get the First "lightmap" to apply along with the "base texture". So i do get a shadowy effect, but NO specular.

CODE HERE:

void Render(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH BUFFER_BIT);

glDisable(GL_BLEND);
glDisable(GL_LIGHTING);

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, LightMap);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, BaseMap);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &Verts);

glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &TextureVerts);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTexture(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &TextureVerts);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Draw the first pass
glDrawArrays(GL_TRIANGLES, 0, count);

glEnable(GL_BLEND);

//Reset up texture info
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, LightMap);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
glBlendFunc(GL_ONE, GL_ONE);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &Verts);

glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &TextureVerts);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//draw the second pass
glDrawArrays(GL_TRIANGLES, 0, count);

glutPostRedisplay();
glutSwapBuffers();
}

Anyone see what I could be doign wrong??

[This message has been edited by dabeav (edited 07-09-2002).]

[This message has been edited by dabeav (edited 07-09-2002).]

Relic
07-09-2002, 05:10 AM
Simple things first: Whats the depth func?Did you make sure the depth test for the second pass passes?

dabeav
07-09-2002, 05:12 AM
Edit:

Ok, i checked the DepthFunc, I reset it to GL_LEQUAL, instead of GL_LESS, and I still get the same results? any other ideas??

[This message has been edited by dabeav (edited 07-09-2002).]

Dan82181
07-09-2002, 05:44 AM
I don't see you setting up blending for the second rendering pass, unless you're doing it but forgot to paste it in your post.

Dan

dabeav
07-09-2002, 06:10 AM
OK I have edited the first code paste, to reflect what I feel the "correct" blending should be. But I am NOT very familiar with blending at all. This may be where my problem lyes. But I am really not sure. Any ideas?

Dan82181
07-09-2002, 06:47 AM
Ok, try this....

In your second pass, set the texture environment mode to GL_REPLACE. This is because the only thing you want on your model in the second pass is what you are going to use as specular light correct?! You're calling
glEnable(GL_BLEND);
ok, now call this...
glBlendFunc(GL_ONE, GL_ONE);
That will do an additive blend in the framebuffer of what you rendered in the first pass with what you are doing in the second pass (i.e. 1st pass + 2nd pass) See if that does what you want

edit {
and don't forget your glDepthFunc(...)!!!!!
};

edit2 {
actually, if you're using backface culling, you could just do glDepthMask(GL_FALSE); to temporarily disable the Z-buffer and just call glDepthMask(GL_TRUE); when you're done (I feel so stupid editing my own post twice, oh well)
};

Dan

[This message has been edited by Dan82181 (edited 07-09-2002).]

[This message has been edited by Dan82181 (edited 07-09-2002).]

dabeav
07-09-2002, 06:55 AM
Ok, i changed the syntax to reflect what you have said to do, and still nothing. I have even tried applying different textures "all kinds, black and white, color, inverted, etc" and its like its not displaying them at all. I get the first 2 images blended just the way I want them to. But on the second pass, NOTHING changes. Any ideas? I am soooo lost.

Edit:
Also if I have back face culling on, and my depthFunc is set to LEQUAL, then I should be fine with my depth buffer correct??

[This message has been edited by dabeav (edited 07-09-2002).]

Dan82181
07-09-2002, 07:59 AM
Well, lets take this one thing at a time.

1 - I take it that your TextureVerts array _is_ supposed to be the same for both texture units in the first pass. _Is_ it supposed to be the same for the 1st texture unit in the second pass? (I'm guessing yes since it is the lightmap, just want to make sure though)

2 - You still have GL_TEXTURE_COORD_ARRAY enabled on TEXTURE1_ARB in the second pass, so disable that.

3 - Why are you using the GL_TEXTURE_ENV_COMBINE_{ARB|EXT} extension in the first pass? Just use GL_REPLACE and GL_MODULATE if all you are doing is [tex0 * tex1]

4 - Why are you also using GL_TEXTURE_ENV_COMBINE_{ARB|EXT} extension in the second pass? Just use GL_REPLACE and call it done.

5 - For the second rendering pass, you shouldn't have to re-enable vertex arrays or rebind the light map if it is still bound on the first texture. Same thing with the texure coordinate arrays.

6 - Your vertices for your triangles are only 2 components?

7 - Quote: "Also if I have back face culling on, and my depthFunc is set to LEQUAL, then I should be fine with my depth buffer correct??" Answer: Yes, you should be. But for each pixel you are rendering, your GF2MX will be testing the Z values from the second pass with the ones from the first pass. When drawing 3D objects that have their backs culled or thrown away durring the rendering process, you can get by with completely disabling Z buffer writes and testing because the values you want are already in the Z buffer and you know that something else hasn't already been rendered on top of it. Certain situations do arise when you sometimes can't do it that way (object is partially obscured by another, etc.), but it should give a speed increase none the less.

8 - If you disable the second pass, does the image look exactly the same?

9 - If you disable the first pass, how does the image look, and is it the result you would like to be combined with the first pass?

Dan

dabeav
07-09-2002, 08:22 AM
THANK YOU!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

It finaly works now, I guess it REALY didnt like me redrawing the data with the same arrays, cause soon as I removed them. BOOM it works like a charm. Thank you all sooooooo much for your help.

Edit:

Question for you though. What is the difference between using

the EXT GL_ADD, and using GL_REPLACE, they seem to do the same thing??

[This message has been edited by dabeav (edited 07-09-2002).]

dabeav
07-09-2002, 09:14 AM
Ok, one more question. Say I want to create an emboss bump mapping, along with the specularlight/shadowlight map, as well as using the base texture. It would work something like this.

I would first replace the scene with the bump map. Then I would add an inverted bump map to the bump map, with a slight off set. I would then add the light map. I would then want to multiply the whole thing so far by teh base, then finaly add the light map again for specular highlights.

((Bump+InvBump)+LightMap)*Base+LightMap

One would think you need only 3 passes for such a mapping with 2 texture units available. Like this.

Tex0 is Bump
Tex1 is Invbump
DrawScene

Tex0 is LightMap
Tex1 is Base
DrawScene

Tex0 is LightMap
DrawScene

But that dosnt seem to work. It seems i have to do this.

Tex0 is Bump
Tex1 is Invbump
DrawScene

Tex0 is LightMap
DrawScene

Tex1 is Base
DrawScene

Tex0 is LightMap
DrawScene

is there any way to use only 3 passes, I want the Base to be multiplied by the Bump, the InvBump, and the LightMap, but I cant seem to get it to work with only 3 passes.

Sorry about the strange question, its more of an order of operations thing. You know, addition after multiplication.

dorbie
07-09-2002, 10:50 AM
The replace gives you the texture fragment as the color out from the texture unit, the add gives you color fragment + texture fragment.

The equation in your last post seems all wrong to me. You multiply by the lightmap ONCE, if you want specular you'd also have to bump map that and it's done differently.

You probably want to modulate the specular by the lightmap too but it depends on what you're up to.

((Bump+InvBump)*base + (Bump+InvBump) )*LightMap

By base I assume you mean the diffuse map texture. You also would eb adding general diffuse illumination terms to the first Bump + InvBump and a specular term to the second Bump+InvBump. The second Bump+InvBump is actually the specular term and the peturbation for InvBump should be very different. ALso you don't want to use InvBump unless you have to. Use the subtractive blending available.

If I were writing your equation it would look like this:

( (vertex_diffuse+Bump_texture-Bump_texture)*diffuse_texture + (vertex_specular+Bump_texture-Bump_texture) )*LightMap

You can see that Bump_texture is the same term everywhere. Only 3 textures are used in this equation, the bump map the diffuse map and the light map. There's no exponent on specular but it could be added on some hardware. The texture coordinate peturbation on the second emboss for specular is done differently.

P.S.
Terms like this are why you use GL_ADD not GL_REPLACE in some texture environments:

vertex_diffuse+Bump_texture


[This message has been edited by dorbie (edited 07-09-2002).]