Jump to content
  • Advertisement
Sign in to follow this  
Ravuya

OpenGL White "seams" between cubes

This topic is 4823 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay, I was working on a little 3D engine and I am using cubes (scaled to 2x their height) to represent solid tiles. Here's the problem: Yup. Lookit them seams. They sure are ugly. I render the cubes using a display list of GL_QUADS (the same problem persists if I render them with a display list of GL_TRIANGLES). Here's my map drawing code:
void CGame::drawFPMap(float playerX, float playerY, float playerZ) {
	int tx = (int)playerX;
	int tz = (int)playerZ;
	
	// Set up OGL
	glLoadIdentity();
	// Rotate up and down
	glRotatef(player->angleUpDown, 1.0f, 0.0f, 0.0f);
	// Rotate left and right
	glRotatef(-player->direction, 0.0f, 1.0f, 0.0f);
	
	// Move camera to world
	if(player->bMoved) {
		glTranslatef(-playerX, -(playerY+(player->headBob/BOB_DIVIDE_AMOUNT)), -playerZ);
	}
	else {
		glTranslatef(-playerX, -playerY, -playerZ);
	}
	
	for(int x = tx - VIEW_RANGE_X; x < tx + VIEW_RANGE_X; x++) {
		float fx = (float)x;
		for(int z = tz - VIEW_RANGE_Z; z < tz + VIEW_RANGE_Z; z++) {
			float fz = (float)z;
			if(x < 0) { x = 0; fx = 0; }
			else if(x >= MAPWIDTH) { continue; }
			if(z < 0) { z = 0; fz = 0; }
			else if(z >= MAPHEIGHT) { continue; }

			glPushMatrix();
			glTranslatef(fx,0,fz);
			glBindTexture(GL_TEXTURE_2D, *textures->getSprite(theMap->getTileAt(x,z,0)));
			glColor3f(1.0f, 1.0f, 1.0f);
			if(theMap->isSolidTile(x,z,0)) {
				// Draw wall tile
				glScalef(1.0f, 2.0f, 1.0f);
				glCallList(solidList);
				// The floor gets drawn anyway, let's continue
				// While we could save some speed by not drawing the floor
				// for solid tiles I want to expand to having 3D maps later on.
			}
			// Draw flat floor tile (ceilings later)
			glCallList(floorList);
			glPopMatrix();
		}
	}
}



Here's my display-list building code (it's frightening, please look away):
#define WALL_WIDTH 1.0f
#define WALL_HEIGHT 1.0f

void Map::generateDisplayList() {
	//	Builds an OpenGL display list of our map using the rendering code
	printf("INFO) Building OpenGL display lists (using quads)\n");
	
	cubes = glGenLists(2);
	glNewList(cubes, GL_COMPILE);
	
	glBegin(GL_QUADS);
	// ROOF
	glNormal3f(0,1,0);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0.0f, WALL_HEIGHT, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(0.0f, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, 0.0f);
	// WALL (FRONT)
	glNormal3f(1, 0, 0);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0.0f, WALL_HEIGHT, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, 0.0f);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(WALL_WIDTH, 0, 0.0f);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(0.0f, 0, 0.0f);
	// WALL (REAR LEFT)
	glNormal3f(0, 0, -1);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0.0f, WALL_HEIGHT, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(0.0f, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(0.0f, 0, WALL_WIDTH);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, 0.0f);
	// WALL (REAR RIGHT)
	glNormal3f(0, 0, 1);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(WALL_WIDTH, 0, WALL_WIDTH);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(WALL_WIDTH, 0, 0.0f);
	// WALL (REAR)
	glNormal3f(-1,0,0);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0.0f, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(WALL_WIDTH, WALL_HEIGHT, WALL_WIDTH);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(WALL_WIDTH, 0, WALL_WIDTH);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(0.0f, 0, WALL_WIDTH);
	glEnd();
	glEndList();
	
	floor = cubes + 1;
	glNewList(floor, GL_COMPILE);
	
	glBegin(GL_QUADS);
	glNormal3f(0.0f,1.0f,0.0f);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0.0f, 0, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(0.0f, 0, WALL_WIDTH);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(WALL_WIDTH, 0, WALL_WIDTH);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(WALL_WIDTH, 0, 0.0f);
	glEnd();
	glEndList();
}



The important thing to notice out of the first source snippet is the glTranslate call in the map-rendering loop. My only assumption now is that there is some sort of rounding error with floating point precision (and I can't figure out a way to make them 'share' vertices). I attempted to change the texture filtering mode to GL_NEAREST like I read in a skybox-seams solution, but the problem persists there as well (and makes the textures ugly). I also attempted to "bloat" them a little bit by extending geometry. I haven't attempted offsetting textures, but I seriously doubt it's a texture issue. The only idea I have is to try and move the x- and z-components of the translation individually tile by tile rather than pushing and popping, but that will probably introduce the same problem. I've been banging on this for a few days, and I have absolutely no idea how to fix this.

Share this post


Link to post
Share on other sites
Advertisement
The seams are visible because each quad is being transformed by a different modelview matrix, and so rounding errors result in a slightly different position each time.

To fix it, avoid changing the modelview matrix at all while rendering the cubes, and generate the vertex positions yourself using a simple, consistent algorithm (like cube_x * 3.0f + 1.0f or something). Then adjacent vertices will have exactly the same final coordinates, and no seams will be visible.

Share this post


Link to post
Share on other sites
what might also help is using a tighter depth range, so where ever you call gluPerspective, set Z Near to no less than 1.0f and Z Far to around 100.0f. The z buffer is not linear, so changing Z far from 100 to 200 is like a 4x step the depth "range".

Cheers
-Danu

Share this post


Link to post
Share on other sites
Quote:
Original post by silvermace
what might also help is using a tighter depth range, so where ever you call gluPerspective, set Z Near to no less than 1.0f and Z Far to around 100.0f. The z buffer is not linear, so changing Z far from 100 to 200 is like a 4x step the depth "range".

Cheers
-Danu


I had Z-Near set to 0.01f before, so I put it up to 1.0f. That seems to have eliminated the appearance of seams, but now world geometry clips my HUD layer, and it also clips off early (so facing down a hallway allows you to see inside the walls).

Looking straight down only renders about half of the viewpoint (the content "in front" of the player).

I will have to figure out some sort of way to fix this so geometry is rendered further away from the viewpoint of the player, so I can use the depth range that fixes this problem without causing excessive clipping due to the player running into walls.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ravuya
Quote:
Original post by silvermace
what might also help is using a tighter depth range, so where ever you call gluPerspective, set Z Near to no less than 1.0f and Z Far to around 100.0f. The z buffer is not linear, so changing Z far from 100 to 200 is like a 4x step the depth "range".

Cheers
-Danu


I had Z-Near set to 0.01f before, so I put it up to 1.0f. That seems to have eliminated the appearance of seams, but now world geometry clips my HUD layer, and it also clips off early (so facing down a hallway allows you to see inside the walls).

Looking straight down only renders about half of the viewpoint (the content "in front" of the player).

I will have to figure out some sort of way to fix this so geometry is rendered further away from the viewpoint of the player, so I can use the depth range that fixes this problem without causing excessive clipping due to the player running into walls.


If 1.0 to 100.0 dosn't work, scale them both back by the same factor (or scale your world up).

On the subject of the HUD layer, you should probably be changing projection matrix modes (to orthographic) for that anyway, and so you should set different depth buffer settings again there (not to mention, your HUD should probably have depth-buffering off).

Share this post


Link to post
Share on other sites
Quote:
Original post by Andrew Russell
Quote:
Original post by Ravuya
Quote:
Original post by silvermace
what might also help is using a tighter depth range, so where ever you call gluPerspective, set Z Near to no less than 1.0f and Z Far to around 100.0f. The z buffer is not linear, so changing Z far from 100 to 200 is like a 4x step the depth "range".

Cheers
-Danu


I had Z-Near set to 0.01f before, so I put it up to 1.0f. That seems to have eliminated the appearance of seams, but now world geometry clips my HUD layer, and it also clips off early (so facing down a hallway allows you to see inside the walls).

Looking straight down only renders about half of the viewpoint (the content "in front" of the player).

I will have to figure out some sort of way to fix this so geometry is rendered further away from the viewpoint of the player, so I can use the depth range that fixes this problem without causing excessive clipping due to the player running into walls.


If 1.0 to 100.0 dosn't work, scale them both back by the same factor (or scale your world up).

On the subject of the HUD layer, you should probably be changing projection matrix modes (to orthographic) for that anyway, and so you should set different depth buffer settings again there (not to mention, your HUD should probably have depth-buffering off).


That seems to have fixed it. Thanks, everyone!

Now just to debug the collision. [crying]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!