Skip to main content
GameDev.net gamedev.net
🔒 Locked

Multitexturing

Started by DuckWizard May 16, 2004 at 9:43 AM 2 replies 500+ views
Original Post
DuckWizard
DuckWizard
Hello, short question this time: I'm trying to do dot3 bump mapping. I have a normal map which contains the normals for each pixel encoded in it - X, Y, Z into R, G, B. This is pretty standard procedure I think. The tutorials I've seen go into complicated math on creating another map which contains the vector to the light at each pixel (from what I understand, which is not much). "Well, no problem," I thought, because I'm using only a flat plane and a single infinite light source. So I thought I'd cheat by loading a premade texture that is just gray and use that for the light vector map. The trouble is, I don't really understand what all these commands do, and all I get is pure white. Here is the code:
	glBindTexture(GL_TEXTURE_2D, waterbumps[0]); //waterbumps[0] contains GL name of normal map

	glEnable(GL_TEXTURE_2D);

	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D, textures[TEX_LIGHTMAP]); //this contains the gray map

	//glEnable(GL_TEXTURE_CUBE_MAP_ARB);

	glActiveTextureARB(GL_TEXTURE0_ARB);

	//Set up texture environment to do (tex0 dot tex1)*color

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);

	glActiveTextureARB(GL_TEXTURE1_ARB);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);

	glActiveTextureARB(GL_TEXTURE0_ARB);

which was pretty much ripped from Paul's tutorial at http://www.paulsprojects.net/tutorials/simplebump/simplebump.html and then modified to use the premade gray texture instead of the calculated light vector map. I'm totally lost - anything anyone could give me (like a document on what these commands do for beginners) would be awesome. It seems like given the fact that it's an infinite light source, this should be simple. But of course, it isn't :-) If anyone has an easier way, I'm all ears. EDIT - edited source because I pasted it wrong... [edited by - DuckWizard on May 16, 2004 10:45:31 AM]
Ostsol
Ostsol
The vector map is a normalization cubemap. When you sample a texel from a cubemap, you use a 3 component vector. The direction of this vector is what determines which texel you get. A normalization cubemap is built such that the sampled texel is a normalized version of the vector that addressed it. It does not have to be used for light vectors -- in fact it can be used for normalizing any vector you want.

A good place to look for information is the OpenGL Extension Registery, specifically the ARB_texture_env_combine and ARB_texture_env_dot3 extensions.

Basically, though, glTexEnvi just sets texture environment parameters.

GL_TEXTURE_ENV is a required token. GL_TEXTURE_ENV_MODE tells OpenGL that you want to set the texture environment mode. Coupled with GL_COMBINE_ARB sets the texture environment mode to GL_COMBINE_ARB.

GL_SOURCEx_RGB_ARB is used to set an RGB source parameter for the texture combining operation. With GL_TEXTURE as the third parameter, this sets the currently bound texture as the parameter.

GL_COMBINE_RGB_ARB indicates that you are setting the texture combining operation. GL_REPLACE will set the current result to the source parameter. If you want to think of it as an equation, then. . .

glActiveTextureARB(GL_TEXTURE0_ARB);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);


. . . basically says:

result = texture0

When a source paremter is set to GL_PREVIOUS_ARB, the parameter is equal to the result of the previous combine operation.

GL_DOT3_RGB_ARB sets the operation to be a dot product operation.

Once again translating code to equations. . .

glActiveTextureARB(GL_TEXTURE1_ARB);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);


. . . is equivalent to:

result = texture1 DOT3 result

If you don't know what a dot3 product is, then you may want to take a look at some 3d math tutorials. Anyways, the above dot3 operation can be interpreted as:

result.xyz = texture1.x * result.x + texture1.y * result.y + texture1.z * result.z

Actually it's a bit more complicated than that. The only way to store a signed vector in an RGB8 texture, which can only store unsigned values, is to scale and bias the values such that 0 represents -1, 0.5 represents 0, and 1 remains representing 1. The is done by taking the original normalized vector, dividing it by two and adding 0.5. As such, when that dot3 operation is executed, each component of the vectors is first converted back to the original state. As such, the full equation is:

result.xyz = 2 * (texture1.x - 0.5) * 2 * (result.x - 0.5) + 2 * (texture1.y - 0.5) * 2 * (result.y - 0.5) + 2 * (texture1.z - 0.5) * 2 * (result.z - 0.5)

Keep this in mind in case you want to use a constant for the light vector or encode it in a texture. You must scale and bias the vector such that its range is [0,1].

[edited by - Ostsol on May 16, 2004 2:09:58 PM]

[edited by - Ostsol on May 17, 2004 12:16:11 AM]
-Ostsol
Fingers_
Fingers_
You don''t need the normalization cubemap at all in this case. If your normals use the same coordinate system as the directional light vector, you can just use glColor3f to set the light vector (scale it like Ostsol described) and don''t even need multitexturing except if you''re also combining it with another texture.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.