Bump Mapping, does this sound right?

Ok, I just got a generic question. Is this how emboss bump mapping is done? First you create a texture, then you create a greyscale value of that texture. Then an inverted texture from the greyscale.

Then you combine the first texture with the inverted texture. to make a new texture. Then you map that texture to your model. You then do some math, ( i was simply going to find the angle of each vertex normal to the light vector for the scene ) and based on your calculations, you “shift” the Texture Coordinates of the greyscale texture from matching the other texture to slightly towards, or slightly away from the light source. Depending on the angle.

So say the first texture is an orange peel, you create a greyscale orange peel (hight map basicaly) then an inverted greyscale (to counteract the greyscale). Combine the inverted peel, with the original peel creats a brighter orange peel. then map the greyscale to the orange, which creates the proper look of the original orage piece, but then shift,the Tex Coords just “slightly” and walla, your done. Is this basicaly how Emboss works???

You don’t need to create an inverted version of the bumpmap, you can actually perform a subtractive blend, it was added to the blend equation ability in the ARB imaging extension.
Click here for information on subtractive blending

Using it looks like this:
glBlendEquation(FUNC_SUBTRACT);
or
glBlendEquation(FUNC_REVERSE_SUBTRACT);

Depending on your pass order.
The real gotcha is clamping in the framebuffer, subtraction helps a bit (vs inverted version), and self shadowing at > 90 degrees.

You also don’t create a greyscale version of the original texture, the greyscale texture should represent the surface detail of the object which won’t always correlate with the rgb -> greyscale image. Alternatively this could be called a height map to be clearer about its contents. There are other bumpmap representations which contain a signed vector as an RGB triplet.

Look here: http://www.dorbie.com/bumplogo.html

At the above link I describe the math for the texture coordinate displacement and explain the blending.

For making bumpmaps this might interest you: http://www.cgsd.com/

You should probably read the FAQ there.

[This message has been edited by dorbie (edited 06-27-2002).]

from a (very) old emboss bumpmap demo of mine
(i believe its correct, then again it mightnt be)

glBindTexture(GL_TEXTURE_2D, bumpmap_texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glDisable(GL_BLEND);
draw_Square(); 

glMatrixMode(GL_TEXTURE);
glPushMatrix();
	glTranslatef( float(cursorposX - w/2)/10000.0 , float(cursorposY - h/2)/10000.0, 0 );

	glBlendFunc(GL_ONE,GL_ONE);
	glEnable(GL_BLEND);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,	GL_COMBINE_EXT);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT,	GL_ADD_SIGNED_EXT);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT,	GL_PRIMARY_COLOR_EXT ); 
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT,	GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT,	GL_ONE_MINUS_SRC_COLOR); 
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT,	GL_ONE_MINUS_SRC_COLOR);

	draw_Square(); 

glPopMatrix();

glMatrixMode(GL_MODELVIEW);

glBindTexture(GL_TEXTURE_2D, background_texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,	GL_MODULATE);
glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);

draw_Square();

glTranslatef( float(cursorposX - w/2)/10000.0 , float(cursorposY - h/2)/10000.0, 0 );

Looks like you are embossing a flat poly with a distant light translated around by the mouse position.

I have some nits, this isn’t doing the tangent space math computation of the light vector required to illuminatie 3D objects and there’s no N.L diffuse term added for general illumination before the bump map emboss delta is applied. Both of these are essential requirements of emboss style bump mapping.

Is it possible to get an heightmap from just a picture of something? Say you have a picure of how leather looks like and want to implement that structure with bumps. Is that possible?

Not reliably unless you are sophisticated about it.

In order of increasing quality:

  1. just greyscale it (yeuch!)

  2. attempt to photoshop it based on the rgb to greyscale image (results will vary with skill) but you might get decent results, I’m sure most bumpmaps are created this way if they’re not procedural. And many bumpmaps you try to model detail rather than represent a photographed texture.

2.5) If photographs are taken under overcast circumstances this will work better, especially if the surface is monotone or you can paint it white.

  1. Illuminate it with a surrounding diffuse light but shadowed almost entirely from above and photograph it, grey scale it and then photoshop it a bit.

  2. Do number 3 after painting the surface matte white.

  3. Illuminate from various angles with a distant point light source and try to infer the bump map based on a reverse illumination calculation. I = L.N, where you have L and want N and I is the value in the photograph. If you understand this equation you’ll see that there’s a degree of freedom missing in the result. You can’t get N from the reverse dot product. But by varying L to get several values for I and changing but known L you can calculate N. This gives you a vector, you then need to reconstruct a height map by generating a skin. Using a vector based bump representation might be a better option for this one.

  4. Paint the surface matte white and do 5.

7 or 4.5) Not sure about the quality of this (it varies with the software) but some stereo photography and height extraction would be possible.

  1. use some kind of commercial surface scanning technology, laser of photography based.

5 is an order of magnitude more tricky than 3, and might be only marginally better in many circumstances.

[This message has been edited by dorbie (edited 06-28-2002).]

Ok, here we go. This is what I have thus far, I havent had a change to compile it yet, so I have NO idea if it works. Is this similar to what you all were talking about? I am very curious as to how I would get rid of using the Inverted bump map. Could one of you please show me where in the code I would need to change something, and what, in order to remove that particular piece. Also would that remove the need for the second pass???

//Texture 0
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, BumpImage);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);

//Texture 1
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, InvertedBumpImage);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);

// General Switches
glDisable(GL_BLEND);
glDisable(GL_LIGHTING);

//Setup Vertex info
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &Map.VertPT);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, &Map.NormalPT);

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &Map.TextureBasePT);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &Map.TextureBumpPT);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Draw first pass
glLockArraysEXT(0, Map.NumVerts);
glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, &Map.VertIndexPT);
glUnlockArraysEXT();

//Reset texture information
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);

glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glBindTexture(GL_TEXTURE_2D,BaseImage);
glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);

//Turn stuff back on
glEnable(GL_BLEND);
glEnable(GL_LIGHTING);

//Resetup Vertex info
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &Map.VertPT);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, &Map.NormalPT);

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, &Map.TextureBasePT);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Redraw
glLockArraysEXT(0, Map.NumVerts);
glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_INT, &Map.VertIndexPT);
glUnlockArraysEXT();

I run the all the verts though a function that finds the offset of each texture coord and saves the total of the old tex coord, and the distance moved into the array pointed to by Map.TextureBumpPT, so that is where i get the ofset values from.

[This message has been edited by dabeav (edited 06-28-2002).]

The code you have is using multitexture, so the bump mapping is done in a single pass and with texture environments not the belndfunc, but you also modulate by a diffuse texture which takes another pass.

The code is doing a modulate texenv with an inverted map. On modern platforms you can invert the bump texture in hardware saving that texture unit. You could reimplement for a single bump texture and a texture register invert on platforms which support it. This would save you a texture unit and therefore a pass.

The function you call is peturbing TextureBasePT into TextureBumpPT using the tangent space light projection (I assume you give it tangent and binormal vectors too).

You are boosting the brightness by multiplying source * destination + destination * source for the final base texture, again this lets you keep the textures dark to avoid clamping at the cost of one bit of precision, but you can do this inside texture operations these days and still boost brightness at the end, and the internal precision is generally higher than the boosted framebuffer brightness.

Your code path is OK for a basic multiutexture system limited to two textures that doesn’t support other interesting extensions.

[This message has been edited by dorbie (edited 06-28-2002).]

That was kind of my goal, I want this to be able to run on just about any system that supports multitexturing at all. Yes I am using the shifting algorithm you have said, by using tangent space. (NeHe tutorial). My only concern now is this, This would require 3 texture maps in memory PER texture. So at the very worst, if I use 2048*2048 textures (not saying that i am, but at worst case scenario) If i were to use a 32bit texture (since most cards internaly convert 24bit to 32 bit anyhow) that would use up 16megs of video memory for the first texture. Then say I shrink the bump map by 1/4 (NeHe said this could be done, with fairly desireable results) this would give me another 1/2 a meg for the bump and a 1/2 a meg for the inverted bump. plus say 9megs for the z buffer (on a 1024x768 screen) that leaves me with 26 megs of ram used for just the textures. Not including the verticies, or anything else. I know its not much but I could really use a way to save space. Does anyone know of one?? Well besides using a BSP tree for removing the z buffer test.