DOT3 Bump mapping problem...

Hy,this is my first post…
I’ve a problem with DOT3 Bump mapping, if I render only the Bump texure all semms ok but when I enable the second unit the result it’s wrong…

DOT3 Texture only: http://www.lib.unimib.it/students/bianchifr/3d/bump00.jpg

Final: http://www.lib.unimib.it/students/bianchifr/3d/bump01.jpg

…here’s my code:

glEnableClientState ( GL_COLOR_ARRAY );

//--------- dot3 bump map --------------------------------------------------
glClientActiveTexture(GL_TEXTURE0_ARB);
glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, Scene.Texture[ CMat.Bump->MapRef].Map);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT , GL_DOT3_RGB_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT , GL_TEXTURE );
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT , GL_PRIMARY_COLOR_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );

//---------- base texture --------------------------------------------------
glClientActiveTexture(GL_TEXTURE1_ARB);
glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, Scene.Texture[ CMat.Diffuse->MapRef].Map);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT , GL_MODULATE );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT , GL_PREVIOUS_EXT );
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT , GL_TEXTURE );
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
//---------------------------------------------------------------------------
glDisable(GL_LIGHTING);

int Offset = O.Offset;
float m[9], lv[3], tc[3], len;

for (int j=0 ; j<O.NTriangle ; j++)
{
for( int k=0 ; k<3 ; k++)
{
// Vettore Luce
lv[0]=(Scene.Light[0].Position[0] - Scene.VBuffer[O.Triangle[j].Edge[k]].Coord[0]);
lv[1]=(Scene.Light[0].Position[1] - Scene.VBuffer[O.Triangle[j].Edge[k]].Coord[1]);
lv[2]=(Scene.Light[0].Position[2] - Scene.VBuffer[O.Triangle[j].Edge[k]].Coord[2]);

	len=(float)sqrt((lv[0]*lv[0])+(lv[1]*lv[1])+(lv[2]*lv[2]));
	if(len != 0.0f)
		{
		lv[0] /=len;
		lv[1] /=len;
		lv[2] /=len;
		}
				
	// Tangent Space
	m[0]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset ].Tg[0];
	m[1]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset ].Bn[0];
	m[2]=Scene.VBuffer[O.Triangle[j].Edge[k]].Normal[0];

	m[3]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset].Tg[1];
	m[4]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset].Bn[1];
	m[5]=Scene.VBuffer[O.Triangle[j].Edge[k]].Normal[1];
				
	m[6]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset].Tg[2];
	m[7]=O.DOT3Vertex[ O.Triangle[j].Edge[k]-Offset].Bn[2];
	m[8]=Scene.VBuffer[O.Triangle[j].Edge[k]].Normal[2];

	// Ruotiamo lv in TangentSpace per essere nello stesso spazio delle normali
	tc[0]=(lv[0]*m[0])+(lv[1]*m[3])+(lv[2]*m[6]);
	tc[1]=(lv[0]*m[1])+(lv[1]*m[4])+(lv[2]*m[7]);
	tc[2]=(lv[0]*m[2])+(lv[1]*m[5])+(lv[2]*m[8]);

	// Colore per Vertice
	tc[0]=(tc[0]*0.5f)+0.5f;
	tc[1]=(tc[1]*0.5f)+0.5f;
	tc[2]=(tc[2]*0.5f)+0.5f;
				
	O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color[0] = tc[0];//FLOAT_TO_UBYTE(tc[0]);
	O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color[1] = tc[1];//FLOAT_TO_UBYTE(tc[1]);
	O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color[2] = tc[2];//FLOAT_TO_UBYTE(tc[2]);
	O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color[3] = 1.0f;

	if (RenderMode == ATI)
		{
		glUpdateObjectBufferATI( ATI_VBuffer  , 
								 8*SFLOAT+((O.Triangle[j].Edge[k])*sizeof(_Vertex)) , 
						 		 4*SFLOAT, 
								 O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color, 
								 GL_DISCARD_ATI);
		}		
	}
}

switch ( RenderMode)
{
case ATI :
{
glArrayObjectATI(GL_ELEMENT_ARRAY_ATI, 1, GL_UNSIGNED_INT, 0, O.IBuffer , 0);
glDrawElementArrayATI( GL_TRIANGLES, O.NVertex );
} break;
}

Someone can help me?!?
thanks and sorry for my english

(Looks like your bump texture is being used as a RGB diffuse texture) - DOH ignore that last sentence, really need to see it moving seeing as its bump mapped. At a glance my first suggestion would be: are you sending 2 sets of texture coords across? e.g. using MultiTexCoord2f - otherwise its more than likely something to do with texture params. I don’t think you need the second block of glTexEnvf commands for the diffuse texture. The texture should just need to be set up to modulate at creation time.

[This message has been edited by paulc (edited 11-14-2002).]

yeah, gl texture environment is part of the entire texture object, so you only need to set these parametes after the first glBind()… the texture environment is restored when you call it, so only change it when you need to. this applies to texture units as well

as for the wrong colours, wll, what’s the diffuse texture supposed to look like? seriously though, from what i can see, is it possible that the red and blue channels have been swapped? i’m just thinking, opengl uses rgba ordering by default, while windows and its file formats use bgra… if so, could be easily fixed by specifying GL_BGRA_EXT instead of GL_RGBA when calling glTexImage… as far as i know, this token’s been in gl since version 1.1, so you can take it that it’s there for granted.

if, on the other hand, you’re not cursed by windows and you’re running linux or something else, this’ll be a lot less helpful though the file format you’re loading the texture image from could still be bgra instead of rgba…

I see your problem. Your second texture unit should not use GL_COMBINE_EXT. Just use GL_MODULATE.

BTW, you could optimize that routine by a LOT. Just loop through the vertices and skip the triangle indices.

Here’s a quick example:
for (int j=0 ; j<O.NVerts ; j++)
{
// Vettore Luce
lv[0]=(Scene.Light[0].Position[0] - Scene.VBuffer[j].Coord[0]);
lv[1]=(Scene.Light[0].Position[1] - Scene.VBuffer[j].Coord[1]);
lv[2]=(Scene.Light[0].Position[2] - Scene.VBuffer[j].Coord[2]);

len=(float)sqrt((lv[0]*lv[0])+(lv[1]*lv[1])+(lv[2]*lv[2]));
if(len != 0.0f)
{
lv[0] /=len;
lv[1] /=len;
lv[2] /=len;
}

//==I DON’T KNOW WHAT OFFSET IS FOR SO YOU CAN MODIFY THIS IF I’M WRONG

// Tangent Space
m[0]=O.DOT3Vertex[ j ].Tg[0];
m[1]=O.DOT3Vertex[ j ].Bn[0];
m[2]=Scene.VBuffer[j].Normal[0];

m[3]=O.DOT3Vertex[j].Tg[1];
m[4]=O.DOT3Vertex[j].Bn[1];
m[5]=Scene.VBuffer[j].Normal[1];

m[6]=O.DOT3Vertex[j].Tg[2];
m[7]=O.DOT3Vertex[j].Bn[2];
m[8]=Scene.VBuffer[j].Normal[2];

// Ruotiamo lv in TangentSpace per essere nello stesso spazio delle normali
tc[0]=(lv[0]*m[0])+(lv[1]*m[3])+(lv[2]*m[6]);
tc[1]=(lv[0]*m[1])+(lv[1]*m[4])+(lv[2]*m[7]);
tc[2]=(lv[0]*m[2])+(lv[1]*m[5])+(lv[2]*m[8]);

// Colore per Vertice
tc[0]=(tc[0]*0.5f)+0.5f;
tc[1]=(tc[1]*0.5f)+0.5f;
tc[2]=(tc[2]*0.5f)+0.5f;

O.DOT3Vertex[j].Color[0] = tc[0];//FLOAT_TO_UBYTE(tc[0]);
O.DOT3Vertex[j].Color[1] = tc[1];//FLOAT_TO_UBYTE(tc[1]);
O.DOT3Vertex[j].Color[2] = tc[2];//FLOAT_TO_UBYTE(tc[2]);
O.DOT3Vertex[j].Color[3] = 1.0f;

if (RenderMode == ATI)
{
glUpdateObjectBufferATI( ATI_VBuffer ,
8*SFLOAT+((O.Triangle[j].Edge[k])sizeof(_Vertex)) ,
4
SFLOAT,
O.DOT3Vertex[O.Triangle[j].Edge[k]-Offset].Color,
GL_DISCARD_ATI);
}
}
}

switch ( RenderMode)
{
case ATI :
{
glArrayObjectATI(GL_ELEMENT_ARRAY_ATI, 1, GL_UNSIGNED_INT, 0, O.IBuffer , 0);
glDrawElementArrayATI( GL_TRIANGLES, O.NVertex );
} break;
}

I do it like that but all my vertex elements line up. If you have a different set of induces for each element because they don’t align then of course you can’t do what I just pointed out.

Elements = Vertices, Colors, Normals, TexCoords

For example, I could index all three of those properly with one set of indices…but I guess I could assume you already do that if you use glDrawElements . So in that case my suggestion would work for you.

To be absolutely correct…

TexEnv is not part of the texture object. This is a relatively common error, but when you really stop and think about it, it makes sense.

When you’re setting TexEnv state, you’re setting up state for the texturing system (i.e. TexEnv is a property of the current texture unit, not the current texture object). It gets slightly confusing since TexParameter state is part of the texture object, but this makes sense too. State like the current wrap mode or filtering mode isn’t a property of the texturing system, it is part of an individual texture.

So this really means that you don’t need to set your TexParameter state after each Bind, but you do need to set your TexEnv state (unless, of course, you’re sure it hasn’t changed).

Also, for what it’s worth, setting TexEnv as specified for the second unit isn’t a bad thing. It’s arguably a little more verbose than it needs to be, but in the end it does just do a MODULATE. I don’t think that’s where the problem is.

– Ben

Thanks very much

  • mattc : I’m using Win so there are no problem in RGB ordering

  • WhatEver : I’ll try GL_MODULATE…and about optimization I think it’s too early…before I’d like to see all things working
    Offset is the Offset of Indices in Vertex Buffer…for the first Object Offset=0 , for the second the NVertex
    of Object 0…for the third Object Offset= NVertex(0) + NVertex(1).
    Every object has some indices pointing to a single unique big VBuffer…to recicle the same indices for other structures like DOT3Vertex which are specific of the Object I subtract the Offset to the indices…mmhhh I don’t speak Italian very well (…and I’m italian…)…but I think my english is even worse…

  • bashbaug : I based my code from the ATI example at : http://www.ati.com/developer/sdk/RadeonSDK/Html/Samples/OpenGL/RadeonSimpleDOT3.html

…other suggestions?

Do you have total ensurance that your video card supports GL_combine_ext and dot_3_RGBA_ext ?
if you don´t , write a subroutine that search the extension name string at GL_extensions

If your card does have the support , are you correctly setting up parmeters for the TexEnv , in the first unit you´re telling the hardware to perform dot3 between the assigned texture and current light ( assigned with glColorxf ou glColorPointer), in the second unit , you only need to use GL_modulate to combine the dot3 N*L vector and the base texture …
So if you want to, you could post the code fragment in which you set up current color
for the vertex and the texture assignment , that must be done with glMultiTexCoordARB

about the above post …
it´s not N*L vector anymore … : )they are only colors at the time of the second combining