Dot3 bumpmapping: weird results

This is a discussion on Dot3 bumpmapping: weird results within the Game Programming forums, part of the General Programming Boards category; I added dot3 bumpmapping to my engine, based on a NeHe tutorial/article. However, i'm getting some weird results with my ...

  1. #1
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070

    Dot3 bumpmapping: weird results

    I added dot3 bumpmapping to my engine, based on a NeHe tutorial/article. However, i'm getting some weird results with my implementation (see attached image).

    The code...

    normalization cubemap generation (called on engine init):
    Code:
    int dot3::gennormcube(UINT size, GLuint &tex)
    {
    	glGenTextures(1, &tex);
    	glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
    
    	unsigned char* data = new unsigned char[size*size*3];
    
    	float offset = 0.5f;
    	float halfSize = size * 0.5f;
    	vector3d temp;
    	unsigned int bytePtr = 0;
    
    	for(unsigned int j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = halfSize;
    			temp[1] = (j+offset-halfSize);
    			temp[2] = -(i+offset-halfSize);
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	bytePtr = 0;
    	for(j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = -halfSize;
    			temp[1] = (j+offset-halfSize);
    			temp[2] = (i+offset-halfSize);
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	bytePtr = 0;
    	for(j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = i+offset-halfSize;
    			temp[1] = -halfSize;
    			temp[2] = j+offset-halfSize;
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	bytePtr = 0;
    	for(j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = i+offset-halfSize;
    			temp[1] = halfSize;
    			temp[2] = -(j+offset-halfSize);
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	bytePtr = 0;
    	for(j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = i+offset-halfSize;
    			temp[1] = (j+offset-halfSize);
    			temp[2] = halfSize;
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	bytePtr = 0;
    	for(j=0; j<size; j++)
    	{
    		for(unsigned int i=0; i<size; i++)
    		{
    			temp[0] = -(i+offset-halfSize);
    			temp[1] = (j+offset-halfSize);
    			temp[2] = -halfSize;
    			if(temp[0] <= 0)
    				temp[0] == 0;
    			if(temp[1] <= 0)
    				temp[1] == 0;
    			if(temp[2] <= 0)
    				temp[2] == 0;
    
    			if(temp[0] >= 1)
    				temp[0] == 1;
    			if(temp[1] >= 1)
    				temp[1] == 1;
    			if(temp[2] >= 1)
    				temp[2] == 1;
    
    			data[bytePtr] = (unsigned char)(temp[0] * 255.0f);
    			data[bytePtr+1] = (unsigned char)(temp[1] * 255.0f);
    			data[bytePtr+2] = (unsigned char)(temp[2] * 255.0f);
    
    			bytePtr+=3;
    		}
    	}
    	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
    			0, GL_RGB8, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    
    	delete [] data;
    
    	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    
    	return true;
    }
    rendering:
    Code:
    				glActiveTextureARB(GL_TEXTURE0_ARB);
    				glEnable(GL_TEXTURE_CUBE_MAP);
    				glBindTexture(GL_TEXTURE_CUBE_MAP, dot3texID);
    				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE) ;
    				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE) ;
    				
    				glActiveTextureARB(GL_TEXTURE2_ARB);
    				glEnable( GL_TEXTURE_2D );
    				glBindTexture( GL_TEXTURE_2D, objectP->m_pMaterials[materialIndex].m_texture );
    				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    				
    				glActiveTextureARB(GL_TEXTURE1_ARB);
    				glEnable( GL_TEXTURE_2D );
    				glBindTexture( GL_TEXTURE_2D, objectP->m_pMaterials[materialIndex].m_texture1 );
    				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB) ;
    				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS) ;
    				glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE) ;
    
    .
    .
    .
    
    		vector3d dist;
    		glBegin( GL_TRIANGLES );
    		{
    			for ( int j = 0; j < objectP->m_pMeshes[i].m_numTriangles; j++ )
    			{
    				int triangleIndex = objectP->m_pMeshes[i].m_pTriangleIndices[j];
    				const Triangle *pTri = &objectP->m_pTriangles[triangleIndex];
    				
    				index[0] = pTri->m_vertexIndices[0];
    				
    				dist.x = objectP->light.x - objectP->m_pVertices[index[0]].m_location[0];
    				dist.y = objectP->light.y - objectP->m_pVertices[index[0]].m_location[1];
    				dist.z = objectP->light.z - objectP->m_pVertices[index[0]].m_location[2];
    
    				glNormal3fv( pTri->m_vertexNormals[0] );
    				glMultiTexCoord3fARB(GL_TEXTURE0_ARB, dist.x, dist.y, dist.z);
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[0]*scaleX, pTri->m_t[0]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, pTri->m_s[0]*scaleX, pTri->m_t[0]*scaleY );
    				//if(environment...) { glMulti....};
    				glVertex3fv( objectP->m_pVertices[index[0]].m_location );
    				
    				index[1] = pTri->m_vertexIndices[1];
    
    				dist.x = objectP->light.x - objectP->m_pVertices[index[1]].m_location[0];
    				dist.y = objectP->light.y - objectP->m_pVertices[index[1]].m_location[1];
    				dist.z = objectP->light.z - objectP->m_pVertices[index[1]].m_location[2];
    
    				glNormal3fv( pTri->m_vertexNormals[1] );
    				glMultiTexCoord3fARB(GL_TEXTURE0_ARB, dist.x, dist.y, dist.z);
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[1]*scaleX, pTri->m_t[1]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, pTri->m_s[1]*scaleX, pTri->m_t[1]*scaleY );
    				//if(environment...) { glMulti....};
    				glVertex3fv( objectP->m_pVertices[index[1]].m_location );
    				
    				index[2] = pTri->m_vertexIndices[2];
    
    				dist.x = objectP->light.x - objectP->m_pVertices[index[2]].m_location[0];
    				dist.y = objectP->light.y - objectP->m_pVertices[index[2]].m_location[1];
    				dist.z = objectP->light.z - objectP->m_pVertices[index[2]].m_location[2];
    				
    				glNormal3fv( pTri->m_vertexNormals[2] );
    				glMultiTexCoord3fARB(GL_TEXTURE0_ARB, dist.x, dist.y, dist.z);
    				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, pTri->m_s[2]*scaleX, pTri->m_t[2]*scaleY );
    				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, pTri->m_s[2]*scaleX, pTri->m_t[2]*scaleY );
    				//if(environment...) { glMulti....};
    				glVertex3fv( objectP->m_pVertices[index[2]].m_location );
    			}
    		}
    		glEnd();
    Help or information will be much appreciated!
    -psychopath
    Attached Images Attached Images  
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  2. #2
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    Ok, I've fixed it up a bit. I forgot to normalize the vectors. I've also realized that my cubemap texture coords must be tangent space vectors. I've calculated my tangent vectors and dotted them with the light vector to get the final lighting vector, however, the lighting is still a little off.

    I'm looking at an example, and I now have another question....in my calculations, the light position is in world space. Does the light position need to be in object space? (ie, modelview_matrix*worldlightpos)
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  3. #3
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    Ok, nevermind, problem solved. My tangent space calculation was messed up. Everything now works perfectly, and looks great.
    Attached Images Attached Images  
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  4. #4

    Join Date
    May 2005
    Posts
    1,041
    Hey that looks really good man, sorry I don't know enough to have helped but I'm glad you solved the problem on your own.

    Keep it up and I'm sure you'll be producing some very impressive projects.

    I think that the next time I see a noob having trouble, I'll refer them to you as an example...you're doing everything that it takes to get good at this stuff, i.e, jumping into problems and working your way through them.
    I'm not immature, I'm refined in the opposite direction.

  5. #5
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    Thanks!
    I still need to get it working with multiple lights though.

    Another issue came up when I tried putting a light in a room, and moving the light around. For some reason, the centre of the light is translating more than where it should be (ie, if I move my light position marker 2 units right, the centre of radiation seems to move 4 units to the right.) That one really has me puzzled.
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  6. #6
    Call me AirBronto
    Join Date
    Sep 2004
    Location
    Indianapolis, Indiana
    Posts
    195
    Nice bumpmapping, looks great, is that perpixle or vertex lighting?

  7. #7
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    Per-pixel lighting.
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  8. #8
    Call me AirBronto
    Join Date
    Sep 2004
    Location
    Indianapolis, Indiana
    Posts
    195
    Now that i think about it, it is not possible to do bump mapping with out doing per-pixle lighting, is it? Well any way that looks just great man keep up the good work.

  9. #9
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    Sorry, I haven't had a chance to comment but the dot3 bump mapping looks very good. You may also want to look into a parallax shader that does parallax mapping for your objects. It's not too complex and adds a bit of visual quality to triangles having large z differences.

    Looks very very good.

  10. #10
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,070
    I've been looking at parallax mapping, and it's simpler than I thought. Really, the only thing that makes it any different than bumpmapping, is the offset of texture coords.

    I wouldn't be able to do it in a shader though (my dot3 code uses the OpenGL dot3 extensions). I tried running a shader that only offsets texture coords, within my dot3 code, and that didn't work out too well. I could probably get parallax mapping working with my dot3 extension code, but i'll have to figure out how to unpack vectors from a greyscale DDS or JPG...or even RAW, as long as it works (any information on how to do that would be a BIG help).
    Memorial University of Newfoundland
    Computer Science

    Mac and OpenGL evangelist.

  11. #11
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    You would have to create a sep RAW file or data file for the vertex information. There isn't enough room in the data type to include it with the image data or bump map data.

    ...wait yes there is, if you don't mind not using floats.

    RAW file:

    1 BYTE - greyscale bump value
    3 BYTES - vector information

    4 BYTES=1 DWORD

    I'm not sure how you are storing the bump data so maybe this won't work - it looks like you are encoding it into one byte from your snippet there.

  12. #12
    Call me AirBronto
    Join Date
    Sep 2004
    Location
    Indianapolis, Indiana
    Posts
    195
    Quote Originally Posted by Bubba
    You may also want to look into a parallax shader that does parallax mapping for your objects. It's not too complex and adds a bit of visual quality to triangles having large z differences.
    A bit of visual quality? i thought parallax mapping was the most detailed and advanced forms of bumpmapping and one of recent research for effeciecy?

  13. #13
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    Well I don't know about that, and honestly I cannot tell much difference between the two samples. I've notice in the past that some of the "most advanced technological graphics techniques" are nothing but a waste of time.

    You must ask yourself a couple of questions before going bonkers on visual candy.

    1. How fast is your game?
    If the game is so fast that the person will never notice the visual quality of certain objects, or never have time to comprehend them even if they tried, why waste FPS on them?

    2. How often will they see the object?
    Repetition is the key to someone really getting a good look at your objects. For instance in No One Lives Forever on level 1, most of us could care less about the nice shiny things lining the hallways. But after some time and after moving around the complex for awhile, you realize that those nice shiny things...are shiny and reflect the environment.
    So if you have a crate or a brick that people will see often, then wasting FPS on visual quality is ok in my book. If it's a once per level thing or once per two levels, then I wouldn't worry.

    3. Is there a possibility of the new technique glitching out?
    Every algorithm has it's limits and threshholds. Often I've found that yeah this cool trick works but only from certain angles or certain rotations. Sometimes when objects are far from the camera, you cannot see them enough to warrant detail texturing and even if you did, the pixels are so close together they begin to shimmer.
    I turn bumpmapping off on all objects if they are lie at some distance or greater from the camera. Bumpmapping looks hideous when there are not enough pixels on the object to see the effect.

    4. What part does the object play in the game? Does it add to the level/story significantly?
    If it's a major object like the mother ship then hell yeah, bump map and parralax map the crapola out of it. If it's just a fighter that will be blown to bits in a nanosecond, I'd say leave it alone. If the object is central to the story, then you need as much detail as possible and vice versa.

    Unforutantely we don't have the option to detail map every single object in a game and use as many tri's as we need to make everything look like a scene from a modern Star Wars movies.

    "One scene in Shrek or Finding Nemo takes over 11 hours to render, over 1 gigabyte of texture data and over 1 gigabyte of geometric data. To render that in real time with current hardware, we need to find an algo that speeds the system up by a factor of 500,000 to reach a simple 12 FPS." - Programming Vertex and Pixel Shaders
    Not gonna happen anytime soon.
    Use what gets the job done and if it's a big hefty algo, use it sparingly.
    Last edited by VirtualAce; 02-09-2006 at 01:43 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird Times I'm getting
    By afflictedd2 in forum Linux Programming
    Replies: 8
    Last Post: 07-23-2008, 08:18 AM
  2. really weird behavior, 16 bit asm w/masm
    By BobMcGee123 in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 12-01-2005, 06:45 PM
  3. Results of March Monthly Contest
    By PJYelton in forum Contests Board
    Replies: 23
    Last Post: 04-17-2005, 10:46 AM
  4. 72hour GDC Results
    By jverkoey in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 07-06-2004, 12:46 AM
  5. Same seed for srand yields different results
    By codegirl in forum C++ Programming
    Replies: 3
    Last Post: 06-23-2003, 03:39 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21