Archived

This topic is now archived and is closed to further replies.

Ilici

3 textures with DOT3 - 1 pass ?

Recommended Posts

Hi, For my terrain engine i'm using dynamic lighting with DOT3 bumpmapping. I setup the first texture stage with the normalmap and the env mode. Then the second texture - the color map using GL_MODULATE. Now i want to add a detail texture to the combiner. I've tried to use the combiner with GL_MODULATE with source0: texture and source1: previous but it does not work. 1.Does anyone have any ideea if this is possible in one pass and how to set up the combiner? 2.How should i bias the DOT3 bumpmapping to create the effect of a ambient color? here's the code:
	GL.ActiveTexture(GL_TEXTURE0_ARB);
	GL.Enable(GL_TEXTURE_2D);
	GL.BindTexture(GL_TEXTURE_2D, terLight.GetName());

	float envc[4] = {Game.Sky.GetSunPos().x, Game.Sky.GetSunPos().y, Game.Sky.GetSunPos().z, 1.0f};
	
	GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envc);

	GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
	GL.TextureEnv(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);

	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
	GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB);
	GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

	GL.ActiveTexture(GL_TEXTURE1_ARB);
	GL.Enable(GL_TEXTURE_2D);
	GL.BindTexture(GL_TEXTURE_2D, terTexture.GetName());

	GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// or maybe use this (??)

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);


	GL.ActiveTexture(GL_TEXTURE2_ARB);
	GL.Enable(GL_TEXTURE_2D);
	GL.BindTexture(GL_TEXTURE_2D, terDetail.GetName());

//this part screws things up

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);

	
//	GL.TextureEnv(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);

//	GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);


	GL.MatrixMode(GL_TEXTURE);
	GL.PushMatrix();
	GL.Scale(64.0f, 64.0f, 1.0f);

	GL.ClientActiveTexture(GL_TEXTURE0_ARB);
	GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);

	GL.ClientActiveTexture(GL_TEXTURE1_ARB);
	GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);

	GL.ClientActiveTexture(GL_TEXTURE2_ARB);
	GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
[ My Site ] 'I wish life was not so short,' he thought. 'Languages take such a time, and so do all the things one wants to know about.' - J.R.R Tolkien /*ilici*/ [edited by - Ilici on October 8, 2003 4:25:36 PM] [edited by - Ilici on October 8, 2003 4:26:31 PM]

Share this post


Link to post
Share on other sites
Your DOT3 part is right. However, you still have to use GL_COMBINE_ARB for modulating each other texture as well.

glTextureEnv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTextureEnv (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

glTextureEnv (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTextureEnv (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTextureEnv (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
glTextureEnv (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

I think that''s it, at least. . . I''m not at home to confirm this, though. . .

Share this post


Link to post
Share on other sites
I''ve tried modulating the color map and the detail map but the detail just replaces the color:

GL.ActiveTexture(GL_TEXTURE0_ARB);
GL.Enable(GL_TEXTURE_2D);
GL.BindTexture(GL_TEXTURE_2D, terLight.GetName());

float envc[4] = {Game.Sky.GetSunPos().x, Game.Sky.GetSunPos().y, Game.Sky.GetSunPos().z, 1.0f};

GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envc);

GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
GL.TextureEnv(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);

GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

GL.ActiveTexture(GL_TEXTURE1_ARB);
GL.Enable(GL_TEXTURE_2D);
GL.BindTexture(GL_TEXTURE_2D, terTexture.GetName());

GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);

GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

GL.ActiveTexture(GL_TEXTURE2_ARB);
GL.Enable(GL_TEXTURE_2D);
GL.BindTexture(GL_TEXTURE_2D, terDetail.GetName());

GL.TextureEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
GL.TextureEnv(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);

GL.TextureEnv(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
GL.TextureEnv(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
GL.TextureEnv(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

This should evaluate (tex1 dot light) * tex2 * tex3 right?



[ My Site ]
''I wish life was not so short,'' he thought. ''Languages take such a time, and so do all the things one wants to know about.'' - J.R.R Tolkien
/*ilici*/

Share this post


Link to post
Share on other sites
Strange. . . I''ve tested it with a modified version of a simple bump-mapping tutorial and it works fine, for me. The following code uses a normalization cube-map (to normalize the light vectors), but ignoring that it''s basically the same as what you''re doing:


glActiveTextureARB (GL_TEXTURE0_ARB);
glBindTexture (GL_TEXTURE_2D, normalMap);
glEnable (GL_TEXTURE_2D);

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

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

glActiveTextureARB (GL_TEXTURE1_ARB);
glBindTexture (GL_TEXTURE_CUBE_MAP_ARB, normalisationCubeMap);
glEnable (GL_TEXTURE_CUBE_MAP_ARB);

glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

glActiveTextureARB (GL_TEXTURE2_ARB);
glBindTexture (GL_TEXTURE_2D, decalTexture);
glEnable (GL_TEXTURE_2D);

glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

glActiveTextureARB (GL_TEXTURE3_ARB);
glBindTexture (GL_TEXTURE_2D, detailTexture);
glEnable (GL_TEXTURE_2D);

glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);


What does your detail texture look like?

Share this post


Link to post
Share on other sites
8Bit Greyscale 512x512
it's the one everyone uses from the heightmap tutorial on gametutorials.com.

I'll test my code on another video card, maybe there is a driver problem on my Radeon.

EDIT: Tested it on GeForce2 but does not work.

[ My Site ]
'I wish life was not so short,' he thought. 'Languages take such a time, and so do all the things one wants to know about.' - J.R.R Tolkien
/*ilici*/


[edited by - Ilici on October 9, 2003 9:51:52 AM]

Share this post


Link to post
Share on other sites
Radeon(1) DDR 64mb VRAM.

The other rendering code:


GL.SetVertexPointer(3, GL_FLOAT, sizeof(tTerrainVertex), &patch->pVertices[0].Vertex);

GL.ClientActiveTexture(GL_TEXTURE2_ARB);
GL.SetTexCoordPointer(2, GL_FLOAT, sizeof(tTerrainVertex), &patch->pVertices[0].TexCoords);

GL.ClientActiveTexture(GL_TEXTURE1_ARB);
GL.SetTexCoordPointer(2, GL_FLOAT, sizeof(tTerrainVertex), &patch->pVertices[0].TexCoords);

GL.ClientActiveTexture(GL_TEXTURE0_ARB);
GL.SetTexCoordPointer(2, GL_FLOAT, sizeof(tTerrainVertex), &patch->pVertices[0].TexCoords);

GL.DrawIndexedArrays(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, indexArray);



[ My Site ]
''I wish life was not so short,'' he thought. ''Languages take such a time, and so do all the things one wants to know about.'' - J.R.R Tolkien
/*ilici*/

Share this post


Link to post
Share on other sites
Well, assuming you''ve also remembered to enable the GL_TEXTURE_COORD_ARRAY client states for each glClientActiveTexture. . . I have no idea what''s going wrong. When that Radeon you have came out, ATI specifically advertised its ability to render three textures in a single pass.

Share this post


Link to post
Share on other sites
yep, it has 3 texture units.

here''s the code u were talking about:

GL.ClientActiveTexture(GL_TEXTURE0_ARB);
GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);

GL.ClientActiveTexture(GL_TEXTURE1_ARB);
GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);

GL.ClientActiveTexture(GL_TEXTURE2_ARB);
GL.EnableClientState(GL_TEXTURE_COORD_ARRAY);



[ My Site ]
''I wish life was not so short,'' he thought. ''Languages take such a time, and so do all the things one wants to know about.'' - J.R.R Tolkien
/*ilici*/

Share this post


Link to post
Share on other sites
OMG, OH TEH NOOOES!! I am teh stupid!!

When declaring GL_TEXTURE2_ARB i copyed the def of GL_TEXTURE1_ARB changed the "1" to "2" but forgot to change the value so GL_TEXTURE2_ARB refered to GL_TEXTURE1_ARB.

*bangs head against keyboard in rage* I hate it when problems that seem hard are corrected by changing one character.

Any idees on the other question (How to bias the result from the DOT3 to create the effect of ambient light) ?



[ My Site ]
'I wish life was not so short,' he thought. 'Languages take such a time, and so do all the things one wants to know about.' - J.R.R Tolkien
/*ilici*/


[edited by - Ilici on October 9, 2003 10:26:10 AM]

Share this post


Link to post
Share on other sites
LOL! Well, I''m glad that''s fixed.

I''m not sure about the ambient light, though. . . With only three texture units, you''re at the limit already, and I''m guessing that adding another multitexturing stage would require yet another texture unit. It''s likely that you''d have to do ambient light in a second pass.

Share this post


Link to post
Share on other sites
And how would i do it with another pass?

I''m guessing a blank white texture blended into the frame buffer. But how should it be blended (what equation)?

[ My Site ]
''I wish life was not so short,'' he thought. ''Languages take such a time, and so do all the things one wants to know about.'' - J.R.R Tolkien
/*ilici*/

Share this post


Link to post
Share on other sites
Well, I suppose you could just render a quad the colour of your ambient light over everything. . . That''s not something I''ve ever done before (actually, I''m using fragment programs almost all the time, now), but I suppose it could work if you use a blend factor of (GL_DST_COLOR, GL_ONE). Shouldn''t using a standard OpenGL fixed function ambient light work as well, though?

Share this post


Link to post
Share on other sites
Using a fixed function will mean that i have to enable lighting which i certanly do not want. And even if I did, because the DOT3 texture is black applying color to the vertices wont change anything.

I discovered that there is some sort of artifact - the DOT3 texture does not look right:

the resulting terrain for light = (0, 1, 0)

the heightmap:

the normalmap:



[ My Site ]
'I wish life was not so short,' he thought. 'Languages take such a time, and so do all the things one wants to know about.' - J.R.R Tolkien
/*ilici*/


[edited by - Ilici on October 9, 2003 2:08:59 PM]

Share this post


Link to post
Share on other sites
I used my own routine for generating it. Here it is:

It converts a 2^n + 1 height map to 2^n normal map by averaging the normals of the four corners of the pixel. It also loops the texture (when i = size -> i = 0)

int i, j, ci, cj;
CVector3 vSum, v1, v2, v3;

Img.Create(ImgSize - 1, ImgSize - 1, 3);

CVector3* Normals;

Normals = new CVector3[ImgSize * ImgSize];

for (i = 0; i < ImgSize; i++)
{
for (j = 0; j < ImgSize; j++)
{
vSum = CVector3(0, 0, 0);
v1 = CVector3(i, SrcImg[i * ImgSize + j], j);

ci = i - 1; cj = j; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v2 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);
ci = i; cj = j + 1; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v3 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);

vSum = vSum + Cross(v1 - v2, v1 - v3);

ci = i; cj = j + 1; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v2 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);
ci = i + 1; cj = j; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v3 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);

vSum = vSum + Cross(v1 - v2, v1 - v3);

ci = i + 1; cj = j; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v2 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);
ci = i; cj = j - 1; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v3 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);

vSum = vSum + Cross(v1 - v2, v1 - v3);

ci = i; cj = j - 1; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v2 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);
ci = i - 1; cj = j; ci = abs(ci % ImgSize); cj = abs(cj % ImgSize);
v3 = CVector3(ci, SrcImg[ci * ImgSize + cj], cj);

vSum = vSum + Cross(v2 - v1, v3 - v1);

vSum = Normalize(vSum);

Normals[i * ImgSize + j] = vSum;
}
}

int Size = ImgSize - 1;
for (i = 0; i < Size; i++)
{
for (j = 0; j < Size; j++)
{
vSum = Normals[i * ImgSize + j] +
Normals[i * ImgSize + j + 1] +
Normals[(i + 1) * ImgSize + j] +
Normals[(i + 1) * ImgSize + j + 1];

vSum = Normalize(vSum);

Img.PutPixel((i * Size + j) * 3 ,(BYTE)(vSum.x * 127.0f + 128));
Img.PutPixel((i * Size + j) * 3 + 1,(BYTE)(vSum.y * 127.0f + 128));
Img.PutPixel((i * Size + j) * 3 + 2,(BYTE)(vSum.z * 127.0f + 128));
}
}

delete [] Normals;

Img.SaveToFile("data\\normal.bmp");

if (!built)
{
texnum = 0;
while (GL.IsTexture(texnum)) texnum++;

GL.GenTextures(1, &texnum);
}

GL.BindTexture(GL_TEXTURE_2D, texnum);

GL.BuildMipmaps2D(GL_TEXTURE_2D, GL_RGB8, Size, Size, GL_RGB, GL_UNSIGNED_BYTE, Img.GetDataPointer());

GL.TextureParam(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
GL.TextureParam(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

GL.TextureParam(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GL.TextureParam(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);




I was thinking the same - the normals are screwed up - and i dont have that utility for generating normals, but i''ll search for it.


[ My Site ]
''I wish life was not so short,'' he thought. ''Languages take such a time, and so do all the things one wants to know about.'' - J.R.R Tolkien
/*ilici*/

Share this post


Link to post
Share on other sites
I've used that and it works nice now. Thnx a lot Ostsol!

The DOT3, when the angle is 90 or more results always to 0 so to get a nice effect the angle must not be allowed to go above ~90.
Also, specifing a material color (eg: glColor4f(1.0f, 0.0f, 0.0f, 0.0f) does not affect the DOT3 op as it would without it because the result is not modulated with the primary color

I think i'll have to make my own dynamic lightmap for the terrain because without pixel shaders the DOT3 is not satisfactory. I'm gonna use a smaller size normalmap to do the calculations and then load it as a texture.


EDIT: just implemented my own dot3 function, for ambient light just clamp the values below to the light value.


[ My Site ]
'I wish life was not so short,' he thought. 'Languages take such a time, and so do all the things one wants to know about.' - J.R.R Tolkien
/*ilici*/


[edited by - Ilici on October 11, 2003 7:32:26 AM]

Share this post


Link to post
Share on other sites